Páginas

domingo, 1 de marzo de 2015

Comunicación entre Java y Arduino Uno mediante el puerto serie /dev/ttyACM0

Hola

En ésta entrada vamos a ver cómo leer desde un aplicativo Java los valores que Arduino Uno envía a través del puerto serie de Ubuntu (/dev/ttyACM0). Estos valores podrían ser cualquier cosa, en el ejemplo no recogemos nada concreto de ningún sensor, sólo enviamos la letra 'a'.

Cuando reciba el kit de sensores que tengo encargados, el aplicativo Java podría recibir datos de un sensor de sonido, de movimiento, etc, enviando luego un aviso por correo electrónico, con lo que tendríamos una alarma rudimentaria.

El código del programa Arduino será muy simple. Una vez compilado, lo cargamos en la memoria flash de la placa y podríamos cerrar el IDE, puesto que no será necesario. Si no lo cerramos tampoco pasa nada. El código sería:

void setup() {
  Serial.begin(9600);
}

void loop(){
  Serial.write('a');
}


Antes de montar el proyecto Java tendremos que hacernos con la librería de java rxtx. Como he tenido problemas con distintas versiones descargadas desde la web (http://rxtx.qbang.org), por problemas con las librerías *.so necesarias en un entorno de 64 bits, finalmente he dado los siguientes pasos:

1) Bajarme la librería desde el repositorio de Ubuntu 14.04 LTS con:

  sudo apt-get install librxtx-java

2) Importamos en el proyecto la librería: /usr/share/java/RXTXcomm-2.2pre2.jar (descargada e instalada al bajar el paquete descrito en el punto 1)

3) Ajustamos la propiedad 'Native Library' del jar RXTXcomm-2.2pre2.jar con el path /usr/lib/jni (es donde está la librería /usr/lib/jni/librxtxSerial-2.2pre1.so que también se descargó e instalcon el paquete del punto 1)

El código Java sería:

package org.dune.arduino.serial;

import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;

public class ComArduino {

    private static final int TIMEOUT = 2000;

    InputStream inputStream;
    SerialPort serialPort;

    public SerialPort abrirPuertoSerie(final String nombrePuerto) throws Exception {
        CommPortIdentifier puerto;
        SerialPort puertoSerie;
        final Enumeration listaPuertos = CommPortIdentifier.getPortIdentifiers();
        while (listaPuertos.hasMoreElements()) {
            puerto = (CommPortIdentifier) listaPuertos.nextElement();
            if (puerto.getName().equals(nombrePuerto)) {
                puertoSerie = (SerialPort)puerto.open("PuertoSerie",TIMEOUT);
                puertoSerie.setSerialPortParams(9600, 

                                                                       SerialPort.DATABITS_8, 
                                                                       SerialPort.STOPBITS_1, 
                                                                       SerialPort.PARITY_NONE);
                return puertoSerie;
            }
        }
        throw new Exception("Nombre de puerto invalido");
    }

    public String leer(final SerialPort puertoSerie, final int total) throws Exception {

        final StringBuilder recibido = new StringBuilder();
        char caracterLeido;
        int nunBytesRecibidos=0;
        while ((caracterLeido = (char)puertoSerie.getInputStream().read()) > 0 &&

                   nunBytesRecibidos<=total) {
            recibido.append(caracterLeido);
            nunBytesRecibidos++;
        }
        return recibido.toString();
    }

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

        final ComArduino ac = new ComArduino();
        final SerialPort port = ac.abrirPuertoSerie("/dev/ttyACM0");
       
        final String recibido = ac.leer(port,100);
        System.out.println(recibido);
    }
}


Siguen aumentando las posibilidades de ésta placa ;-)

Un saludo