В этой статье показано как с помощью одноплатного компьютера и 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

