В этой статье показано как с помощью одноплатного компьютера и Pi4J сделать мигающий светодиод. Можно сказать, что это первый «урок для начинающих» из этой серии.
Проект Pi4J — это мост между оборудованием Raspberry Pi и Java с объектно-ориентированным подходом. Pi4J — проект с открытым исходным кодом. В дополнение к базовым функциональным возможностям доступа к аппаратным средствам, этот проект также пытается предоставить набор расширенных функций, которые делают работу с Raspberry Pi простой в использовании и более удобной для Java-разработчиков.
И так, для начала нужно установить библиотеки Pi4J на ваш компьютер. Pi4J поддерживает следующие платы: Raspberry Pi, Banana Pi, Banana Pro, Synovoip BPI, Odroid, Orange Pi и NanoPi. По умолчанию Pi4J настроен под Raspberry Pi.
Необходимые компоненты
Чтобы зажечь светодиод понадобится:
- одноплатный компьютер (в моём случае — это Orange Pi PC);
- светодиод;
- резистор 220 Ом.
Подключение светодиода
Мы подключаем резистор сопротивлением 220 Ом к выходу номер 24 (GPIO.24), к резистору в свою очередь подключаем анод (обычно длинная ножка) светодиода. Катод подсоединяем к земле (GND или 0v).
определить какой пин 24-й, так это колонка wpi после выполнения gpio readall
.
Инициализация компонентов
Если у вас есть Raspberry Pi, тогда вам не надо выбирать платформу. У меня Orange Pi PC, по этому я должны явно указывать платформу — Orange Pi.
PlatformManager.setPlatform(Platform.ORANGEPI);
Перед взаимодействием с Pi4J мы должны сначала создать экземпляр контроллера GPIO. GpioFactory
включает метод getInstance
для создания контроллера GPIO. Проект будет содержать только один экземпляр контроллера GPIO, так как паттерн Singleton гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
final GpioController gpio = GpioFactory.getInstance();
Чтобы получить доступ к пинам GPIO, мы должны сначала обеспечить нужный пин. С помощью методов provisionDigitalOutputPin
мы можем настроить пин в режиме выхода, задать имя и состояние пина при запуске (0 или 1).
GpioPinDigitalOutput myLed = gpio.provisionDigitalOutputPin( OrangePiPin.GPIO_24, // Номер пина по WiringPi "Светодиод", // Имя пина (необязательный) PinState.LOW); // Состояние пина при запуске (необязательный)
Pi4J обеспечивает реализацию для автоматического задания состояний выводов GPIO, когда приложение завершает работу. К примеру, нам нужно освободить пин, установить в режим входа, отключить подтягивающий резистор и задать состояние LOW (0), чтобы вернуть пин в исходное состояние.
myLed.setShutdownOptions( true, // освобождаем пин PinState.LOW, // задаём состояние 0 PinPullResistance.OFF, // отключаем подтягивающий резистор PinMode.DIGITAL_INPUT);// установливаем режим входа
Если необходимо исполнять какой-то код во время изменения состояния пина (из 0 в 1 или наоборот), тогда нужно создать «слушатель». Обычно они нужны в случае подключения, к примеру, кнопки или датчика движения. В этом примере мы просто будем выводить в консоль имя и состояние пина.
myLed.addListener(new GpioPinListenerDigital() { @Override public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { System.out.println(" --> Состояние пина: " + event.getPin() + " = " + event.getState()); } });
Интерфейс GpioPinDigitalOutput
Интерфейс GpioPinDigitalOutput
содержит методы для подачи (логический «1
«) или снятия (логический «0
«) рабочего напряжения на пины GPIO. Все методы этого интерфейса описаны ниже.
void high();
отправляет на цифровой вывод значение HIGH
.
void low();
отправляет на цифровой вывод значение LOW
.
void toggle();
отправляет на цифровой вывод значение HIGH
, если текущее значение LOW
или LOW
— если HIGH
.
Future<?> blink(long delay);
непрерывно отправляет на цифровой вывод значение HIGH
и LOW
.
Параметры:
long delay
— интервал в миллисекундах;
Future<?> blink(long delay, PinState blinkState);
непрерывно отправляет на цифровой вывод значение HIGH
и LOW
.
Параметры:
long delay
— интервал в миллисекундах;PinState blinkState
— начальное значение:PinState.LOW
илиPinState.HIGH
.
Future<?> blink(long delay, long duration);
отправляет на цифровой вывод значение HIGH
и LOW
.
Параметры:
long delay
— это интервал в миллисекундах;long duration
— продолжительность в миллисекундах.
Future<?> blink(long delay, long duration, PinState blinkState);
отправляет на цифровой вывод значение HIGH
и LOW
.
Параметры:
long delay
— это интервал в миллисекундах;long duration
— продолжительность в миллисекундах;PinState blinkState
— начальное значение:PinState.LOW
илиPinState.HIGH
.
Future<?> pulse(long duration);
отправляет на цифровой вывод значение HIGH
.
Параметры:
long duration
— продолжительность в миллисекундах.
Future<?> pulse(long duration, Callable<Void> callback);
отправляет на цифровой вывод значение HIGH
.
Параметры:
long duration
— продолжительность в миллисекундах;Callable<Void> callback
— задача, которая будет выполняться по истечению времениduration
.
Future<?> pulse(long duration, boolean blocking);
отправляет на цифровой вывод значение HIGH
.
Параметры:
long duration
— продолжительность в миллисекундах;boolean blocking
—true
блокирует текущий поток на время выполнения импульса иfalse
— запуск импульса в отдельный поток (в фоновом режиме).
Future<?> pulse(long duration, boolean blocking, Callable<Void> callback);
отправляет на цифровой вывод значение HIGH
.
Параметры:
long duration
— продолжительность в миллисекундах;boolean blocking
—true
блокирует текущий поток на время выполнения импульса иfalse
— запуск импульса в отдельный поток (в фоновом режиме);Callable<Void> callback
— задача, которая будет выполняться по истечению времениduration
.
Future<?> pulse(long duration, PinState pulseState);
отправляет на цифровой вывод значение.
Параметры:
long duration
— это продолжительность в миллисекундах;PinState pulseState
— это, непосредственно, значениеPinState.LOW
илиPinState.HIGH
.
Future<?> pulse(long duration, PinState pulseState, Callable<Void> callback);
отправляет на цифровой вывод значение.
Параметры:
long duration
— продолжительность в миллисекундах;PinState pulseState
— значениеPinState.LOW
илиPinState.HIGH
;Callable<Void> callback
— задача которая будет выполняться по истечению времениduration
.
Future<?> pulse(long duration, PinState pulseState, boolean blocking);
отправляет на цифровой вывод значение.
Параметры:
long duration
— продолжительность в миллисекундах;PinState pulseState
— значениеPinState.LOW
илиPinState.HIGH
;boolean blocking
—true
блокирует текущий поток на время выполнения импульса иfalse
— запуск импульса в отдельный поток (в фоновом режиме).
Future<?> pulse(long duration, PinState pulseState, boolean blocking, Callable<Void> callback);
отправляет на цифровой вывод значение.
Параметры:
long duration
— продолжительность в миллисекундах;PinState pulseState
— значениеPinState.LOW
илиPinState.HIGH
;boolean blocking
—true
блокирует текущий поток на время выполнения импульса иfalse
— запуск импульса в отдельный поток (в фоновом режиме);Callable<Void> callback
— задача которая будет выполняться по истечению времениduration
.
void setState(PinState state);
отправляет на цифровой вывод значение HIGH
и LOW
.
Параметры:
PinState pulseState
— значениеPinState.LOW
илиPinState.HIGH
;
void setState(boolean state);
отправляет на цифровой вывод значение HIGH
и LOW
.
Параметры:
boolean state
— значениеtrue
илиfalse
.
Future — это интерфейс для получения результатов работы асинхронной операции. Ключевым методом здесь является метод get, который блокирует текущий поток (с таймаутом или без) до завершения работы асинхронной операции в другом потоке. Также, дополнительно существуют методы для отмены операции и проверки текущего статуса.
Мигающий светодиод — примеры
Мигать светодиодом можно несколькими способами. Первый способ — используя методы void high();
и void low();
— зажигаем и выключаем светодиод соответственно.
for (int i = 0; i < 10; i++) { myLed.high(); Thread.sleep(500); myLed.low(); Thread.sleep(500); }
Второй способ — используя методы void setState(PinState state);
и void setState(boolean state);
— задаёт состояние пина в зависимости от значения параметра arg0
: true
и false
или PinState.LOW
и PinState.HIGH
.
for (int i = 0; i < 10; i++) { myLed.setState(true); Thread.sleep(500); myLed.setState(PinState.LOW); Thread.sleep(500); }
Третий способ — используя метод void toggle();
. Этот метод работает как переключатель, если пин в состоянии «1», тогда меняет её в «0» и наоборот.
for (int i = 0; i < 20; i++) { myLed.toggle(); Thread.sleep(500); }
Четвёртый способ — используя методы Future<?> blink(long delay);
. Как по мне, так это самый интересный способ мигать светодиодом. К примеру, нам нужно мигать непрерывно светодиодом пока программа запущена.
Future<?> future = myLed.blink(500);
Или непрерывно мигать в течении некоторого времени.
// непрерывно мигает светодиод каждые 1/2 секунды в течение 15 секунд Future<?> future = myLed.blink(500, 15000); // Ждём окончания мигания while (!future.isDone()) { Thread.sleep(50); }
Завершение программы
Метод shutdown()
остановливает все действия/потоки GPIO, выключив контроллер GPIO, другими словами, этот метод будет принудительно отключать все потоки мониторинга GPIO и задачи.
gpio.shutdown();
Пример Java программы
Ниже привёл пример программы «мигающий светодиод» с использованием функции Future<?> blink(long arg0, long arg1);
. Программа непрерывно мигает светодиод каждые 1/4 секунды в течение 3 секунд.
import java.util.concurrent.Future; import com.pi4j.io.gpio.GpioController; import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinDigitalOutput; import com.pi4j.io.gpio.OrangePiPin; import com.pi4j.io.gpio.PinMode; import com.pi4j.io.gpio.PinPullResistance; import com.pi4j.io.gpio.PinState; import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent; import com.pi4j.io.gpio.event.GpioPinListenerDigital; import com.pi4j.platform.Platform; import com.pi4j.platform.PlatformManager; public class LedBlinking { public static void main(String[] args) { try { /* * Поскольку мы не используем платформу Raspberry Pi, мы должны явно * указывать платформу, в нашем случае - это Orange Pi. */ PlatformManager.setPlatform(Platform.ORANGEPI); /* * Создаём экземпляр контроллера GPIO */ final GpioController gpio = GpioFactory.getInstance(); /* * настройка вывода GPIO.24, задаём режим выхода и установливаем значение * LOW при запуске */ GpioPinDigitalOutput myLed = gpio.provisionDigitalOutputPin( OrangePiPin.GPIO_24, // Номер пина по WiringPi "Светодиод", // Имя пина (необязательный) PinState.LOW); // Состояние пина при запуске (необязательный) /* * настроика поведения выключения */ myLed.setShutdownOptions( true, // освобождаем пин PinState.LOW, // задаём состояние 0 PinPullResistance.OFF, // отключаем подтягивающий резистор PinMode.DIGITAL_INPUT);// установливаем режим входа /* * Это объект, который "слушает" и исполняет код в зависимости от события. */ myLed.addListener(new GpioPinListenerDigital() { @Override public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { System.out.println(" --> Состояние пина: " + event.getPin() + " = " + event.getState()); } }); // непрерывно мигает светодиод каждые 1/4 секунды в течение 3 секунд Future<?> future = myLed.blink(250, 3000); // ждёт окончания мигания while (!future.isDone()) { Thread.sleep(50); } gpio.shutdown(); } catch (Exception e) { e.printStackTrace(); } } }
Как скомпилировать Java файла
Для компиляции этой программы используйте следующую команду:
javac -classpath .:classes:/opt/pi4j/lib/'*' -d . LedBlinking.java
Как запуск class файла
Следующая команда запустит этот пример программы:
sudo java -classpath .:classes:/opt/pi4j/lib/'*' LedBlinking