PI4J, control del GPIO de Raspberry Pi con Java

PI4J es un proyecto que provee un puente entre librerías nativas y Java para ganar acceso a los pines de comunicación GPIO del Raspberry PI.

Los autores de las librerias nos recuerdan que es un proyecto joven, en constante cambio, y nos alentan a probar las versiones snapshot, cosa que haremos.
 

Que es GPIO


El conector GPIO del PI es un interfaz en forma de serie de pines al cual enchufar hardware externo:

Las funciones de estos pines son las siguientes:

  • GPIO Real (General Purpose Input Output) pines para controlar leds, etc
  • El interfaz I2C permite conectar módulos controlados con tan solo dos pines
  • Interfaz SPI un estándar alternativo al I2C
  • Pines Rx and Tx comunicación con dispositivos en serie
  • PWM control de dispositivos como pueden motores y servos

 

Preparativos


Partimos de una instalación básica de Raspberry Pi

https://unpocodejava.wordpress.com/2013/07/05/java-en-un-raspberry-pi-desde-cero-2/

Incluyendo la instalación de la versión 1.8.0 de Java, que vendrá muy bien.

Aunque Java 1.7 dice no ser compatible sobre el sistema operativo Raspbian “wheezy” (se sugiere la alternativa “wheezy” soft-float), parece que a versión Java 1.8 no ha dado ningún tipo de problemas con el Wheezy. De modo que nos mantenemos en esta versión.

Pi4J implementa un envoltorio JNI de la librería WiringPI https://projects.drogon.net/raspberry-pi/wiringpi/

image032 image033

Y utiliza esta numeración de pines (que abstrae la numeración hardware, para mantenerla constante en caso de cambios)
 

Preparar Java

Para completar la instalación JDK del post anterior, le indicaremos al sistema donde está localizada la JVM.
>sudo update-alternatives –install «/usr/bin/java» «java» «/opt/jdk1.8.0/bin/java» 1

Indicamos al sistema cual es la JDK por defecto.
>sudo update-alternatives –set java /opt/jdk1.8.0/bin/java

Configuramos la variable de entorno JAVA_HOME en el entorno
>sudo nano /etc/environment

y añadimos

JAVA_HOME="/opt/jdk1.8.0"

Despues editar
>sudo nano ~/.bashrc
y añadir

export JAVA_HOME="/opt/jdk1.8.0"
export PATH=$PATH:$JAVA_HOME/bin

>sudo reboot

 

Configuración


En el PI descargamos una copia del último paquete de instalación
>wget http://pi4j.googlecode.com/files/pi4j-0.0.5.deb

Lo descomprimimos e instalamos
>sudo dpkg -i pi4j-0.0.5.deb

Los paquetes instalados irán a las rutas

/opt/pi4j/lib
/opt/pi4j/examples

Es necesario incluir el directorio lib en el classpath de java, como veremos más adelante. Los ejemplos se pueden compilar con
>cd /opt/pi4j/examples
>./build

 

Instalación


Aparte del PI necesitaremos:

Y lo conectamos todo de este modo:

image0041

image005

 

Ejemplo de Salida


Aquí hay un ejemplo para controlar el led mediante la salida GPIO_01

>sudo nano ControlGpioExample

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
/**
 * Ejemplo encendido/apagado de un led
 */
public class ControlGpioExample {

 public static void main(String[] args) throws InterruptedException {

 System.out.println("<--Pi4J--> GPIO Control Example ... started.");

  // crear controlador gpio
 final GpioController gpio = GpioFactory.getInstance();

 // provisionar pin #01 como output y encenderlo como estado inicial
 final GpioPinDigitalOutput pin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, "MyLED", PinState.HIGH);
 System.out.println("--> GPIO state: ON");

 Thread.sleep(5000);

 // apagarlo gpio pin #01
 pin.low();
 System.out.println("--> GPIO stat: OFF");
 Thread.sleep(5000);
 // cambiar al estado contrario (should turn on)
 pin.toggle();
 System.out.println("--> GPIO state: ON");
 Thread.sleep(5000);
 // toggle (should turn off)
 pin.toggle();
 System.out.println("--> GPIO state: OFF");

 Thread.sleep(5000);
 // encender gpio pin #01 1 segundo y apagar
 System.out.println("--> GPIO state: ON 1 second");
 pin.pulse(1000, true); // set second argument to 'true' use a blocking call

 // acabar con todos los hilos del controlador gpio
 gpio.shutdown();
 }
}


Salvamos y compilamos con la orden
>javac -classpath .:classes:/opt/pi4j/lib/'*' -d . ./ControlGpioExample.java

aparecerá el .class

y ejecutamos
>sudo java -classpath .:classes:/opt/pi4j/lib/'*' ControlGpioExample

Si todo ha ido bien el led se encenderá y apagará 3 veces

 

Desarrollo en PC


Aunque podemos compilar en el raspberry pi
>javac -classpath .:classes:/opt/pi4j/lib/'*' ...

Es mejor optar por la ventaja multiplataforma de java y desarrollar y compilar en un PC de desarrollo con eclipse.

Para ello podemos importar las librerías

O montar un proyecto maven con el repositorio en el POM.XML

<repositories>
 <repository>
 <id>oss-snapshots-repo</id>
 <name>Sonatype OSS Maven Repository</name>
 <url>https://oss.sonatype.org/content/groups/public</url>
 <snapshots>
 <enabled>true</enabled>
 <updatePolicy>always</updatePolicy>
 </snapshots>
 </repository>
</repositories>

Y las dependencias

<dependency>
 <groupId>com.pi4j</groupId>
 <artifactId>pi4j-core</artifactId>
 <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
 <groupId>com.pi4j</groupId>
 <artifactId>pi4j-gpio-extension</artifactId>
 <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
 <groupId>com.pi4j</groupId>
 <artifactId>pi4j-device</artifactId>
 <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
 <groupId>com.pi4j</groupId>
 <artifactId>pi4j-example</artifactId>
 <version>1.0-SNAPSHOT</version>
</dependency>

 

Otros Ejemplos


Con Pi4J podemos realizar lectura asíncrona de señales

// provision gpio pin #02 as an input pin with its internal pull down resistor enabled
 final GpioPinDigitalInput myButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN);
 // create and register gpio pin listener
 myButton.addListener(new GpioPinListenerDigital() {
 @Override
 public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
 // display pin state on console
 System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
 }

 });

Crear triggers que realizan callbacks y redirección de señales entre pines

// provision gpio pin #02 as an input pin with its internal pull down resistor enabled
 final GpioPinDigitalInput myButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN);
 // create and register gpio pin listener
 myButton.addListener(new GpioPinListenerDigital() {
 @Override
 public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
 // display pin state on console
 System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
 }

 });

Lectura y escritura del puerto serie

// create an instance of the serial communications class
 final Serial serial = SerialFactory.createInstance();
 // create and register the serial data listener
 serial.addListener(new SerialDataListener() {
 @Override
 public void dataReceived(SerialDataEvent event) {
 // print out the data received to the console
 System.out.print(event.getData());
 } 
 });

 // open the default serial port provided on the GPIO header
 serial.open(Serial.DEFAULT_COM_PORT, 38400);

 // write a formatted string to the serial transmit buffer
 serial.write("CURRENT TIME: %s", new Date().toString());

En el javadoc y los ejemplos podemos encontrar más operaciones, como definición de estados en caso de shutdown, obtener información de la placa, creación de pulsos de amplitud modulada (PWM) , etc.

 

Referencias


http://pi4j.com
https://projects.drogon.net/raspberry-pi/wiringpi/

7 comentarios

  1. Amigo muy bueno el tutorial, pero tengo un problema. A la hora de escribir el comando para ejecutar el programa (sudo java -classpath .:classes:/opt/pi4j/lib/’*’ ControlGpioExample), me sale en la terminal «sudo: java: command no found». Quisiera saber si me podria ayudar. Gracias.

  2. Parece que o no has instalado la maquina virtual de java correctamente (ver final del tutorial)
    https://unpocodejava.wordpress.com/2013/07/05/java-en-un-raspberry-pi-desde-cero-2/

    o lo mas seguro es que la orden no encuentra la ruta a «java». Pruebas a escribir la ruta completa al comando:
    >sudo /opt/jdk1.8.0/bin/java -classpath .:classes:/opt/pi4j/lib/’*’ ControlGpioExample

    ——————-

    Si quieres que se ejecute el comando desde cualquier directorio -sin poner la ruta completa- tienes que hacer lo siguiente.
    Añade al fichero «/etc/environment» con un editor
    >nano /etc/environment
    la linea
    JAVA_HOME=»/opt/jdk1.8.0″

    Despues edita el fichero «/home/pi/.bashrc» con el editor nano
    >nano /home/pi/.bashrc
    ya añade estas dos lineas al final y salva:
    export JAVA_HOME=»/opt/jdk1.8.0″
    export PATH=$PATH:$JAVA_HOME/bin

    Reinicia el sistema para que se apliquen los cambios
    >sudo reboot

  3. hola tengo un problema al ejecutar
    sudo update-alternatives –install “/usr/bin/java” “java” “/opt/jdk1.8.0/bin/java” 1
    me manda un error de que install no es un argumento reconocido

Deja un comentario