TODOPIC

Otros Microcontroladores / Dispositivos programables => Arduino => Mensaje iniciado por: CompSystems en 26 de Marzo de 2016, 13:08:24

Título: Conexión μCtrol (ARDUINO, RASPBERRY- π, …) <-> JAVA(PC/LINUX/MAC)
Publicado por: CompSystems en 26 de Marzo de 2016, 13:08:24
Conexión μCtrol (ARDUINO, RASPBERRY- π, …) <-> JAVA(PC/LINUX/MAC) por medio de la "RXTX Java Library 2.1-7r2"

Ya tengo otro hilo relacionado, pero este incluira biblioteca propias.

Existe una biblioteca para JAVA llamada "RXTX Java Library” que permite enlazar JAVA(PC/LINUX/MAC) con diferentes dispositivos como ARDUINO (μctrl ATMEL), RASPBERRY-PI (Procesador), y creo que también cualquier otra tarjeta con μcontrolador como PIC, FREESCALE, esta biblioteca contiene diferentes métodos o funciones para la comunicación serial, pero no anexa un archivo de configuración como tal.

He creado un archivo de configuración denominado "Configuracion_JAVA_uCtrol_RXTX_library.JAVA" que a diferencia de otros que se encuentran en la WEB, esta queda independiente (archivo aparte) del código de control (JAVA) a utilizar permitiendo organizar mejor un proyecto.

Archivo (versión 0.2 marzo 26 2016) por: Jaimeza (AKA compsystems )   
basado en: http:/playground.arduino.cc/Interfacing/Java

En el archivo principalmente se cambió los IDs usuario de inglés a español, se detalla muy bien los mensajes de error, se agregaron unas funciones para el manejo de la transferencia y recepción de datos, un elemental parser (analizador de cadenas) para decodificar los mensajes provenientes de un μcontrolador.

Espero mejorar la biblioteca paralelamente a medida que mis conocimientos en JAVA aumenten.

Se escucha sugerencias para mejorar la biblioteca, alternativas u otras bibliotecas, mejoras en los códigos, etc. …

A: ¿Dónde descargar  "RXTX Java Library 2.1-7r2" ?

Página para descargar la última versión de "RXTX Java Library 2.1-7r2" http://rxtx.qbang.org/wiki/index.php/Download
/!\ Descargar la biblioteca adecuada, tener en cuenta si su OS es de 32/64 bits

B: ¿Cómo incorporarla (Setup / Instalación) “RXTX Java Library 2.1-7r2" a un proyecto en JAVA?

"RXTX Java Library 2.1-7r2" tiene 3 archivos principales: RXTXcomm.jar, rxtxSerial.dll y rxtxParallel.dll
copiar rxtxSerial.dll y rxtxParallel.dll dentro del JRE (…/lib/ext) y JDK (…/bin) de JAVA
por ejemplo, según la versión del JRE/JDK (actual version1.8.77) y del OS puede variar el lugar del directorio
C:\Program Files/Java/jre1.8.77/lib/ext
C:\Program Files (x86) /Java/jre1.8.77/lib/ext
C:\Program Files/Java/jdk1.8.77/bin

En el proyecto creado en JAVA con el IDE escogido, buscar del árbol de proyectos, carpeta Bibliotecas/Libraries, agregar el archivo .JAR: RXTXcomm.jar y listo  :)

Código fuente en JAVA
Código: Java
  1. // Archivo JAVA: Configuracion_JAVA_μCtrol_RXTX_library.JAVA
  2.  
  3. import gnu.io.CommPort;
  4. import gnu.io.CommPortIdentifier;
  5. import gnu.io.SerialPort;
  6. import gnu.io.SerialPortEvent;
  7. import gnu.io.SerialPortEventListener;
  8. import java.io.BufferedReader;
  9. //import java.io.IOException;
  10. //import java.io.InputStream;
  11. import java.io.InputStreamReader;
  12. import java.io.OutputStream;
  13. import java.util.Enumeration;
  14.  
  15. import javax.swing.JOptionPane;
  16.  
  17. /**
  18.  *
  19.  * @author  compsystems
  20.  */
  21. public class Configuracion_JAVA_uCtrol_RXTX_library implements SerialPortEventListener {
  22.  
  23.     // Id puertoSerial para inicializar el puerto serial
  24.     SerialPort puertoSerial; // requiere agregar: import gnu.io.SerialPort;
  25.  
  26.     /**
  27.      * Lista de los puertos donde normalmente se va a conectar el μControlador.
  28.      */
  29.     private String NOMBRES_DE_PUERTOS[] = {
  30.         "", //"COMx", // WindowsOS, Ver Administrador de Dispositivos Puertos COM, por ejp μControlador x conectado en COM3
  31.         //"/dev/tty.usbserial-A9007UX1", // MacOS-X
  32.         //"/dev/ttyACM0", // RaspberryPI
  33.         //"/dev/ttyUSB0", // LinuxOS
  34.     };
  35.  
  36.     /**
  37.      * Streams
  38.      */
  39.     // OutputStream es una clase abstracta de la que no pueden crearse objetos. No obstante,
  40.     // todos los objetos que se creen de clases derivadas dispondrán de algunas operaciones interesantes:
  41.     // que respectivamente escriben un byte, un array de bytes, o una zona de un vector de bytes.
  42.     /**
  43.      * The output stream to the port
  44.      */
  45.     // ID para contener el dato a enviar
  46.     private OutputStream serialSalida = null; // requiere: import java.io.OutputStream;
  47.  
  48.     /**
  49.      * A BufferedReader which will be fed by a InputStreamReader converting the
  50.      * bytes into characters making the displayed results codepage independent
  51.      */
  52.     private BufferedReader serialEntrada = null; // requiere: import java.io.BufferedReader;
  53.     // forma alternativa
  54.     //private BufferedReader serialReader = null; // requiere: import java.io.BufferedReader;
  55.     //private InputStream serialEntrada = null; // requiere: import java.io.InputStream;
  56.  
  57.     /**
  58.      * Milliseconds to block while waiting for port open
  59.      */
  60.     // Tiempo de espera (ms) mientras se abre el puerto serie
  61.     private int TIEMPO_MUERTO; // TIME_OUT 2 seg
  62.  
  63.     /**
  64.      * Default bits per second for COM port.
  65.      */
  66.     private int VELOCIDAD_DE_DATOS; // DATA_RATE
  67.  
  68.     private int LONGITUD_DE_CADENA; //
  69.  
  70.     public void parametrosComunicacion(int int_time_out, int int_data_rate, String str_puerto, int int_longCadena) {
  71.         TIEMPO_MUERTO = int_time_out;
  72.         VELOCIDAD_DE_DATOS = int_data_rate;
  73.         NOMBRES_DE_PUERTOS[0] = str_puerto;
  74.         LONGITUD_DE_CADENA = int_longCadena;
  75.     }
  76.  
  77.     public void inicializarConexion() {
  78.         // the next line is for Raspberry Pi and
  79.         // gets us into the while loop and was suggested here was suggested http://www.raspberrypi.org/phpBB3/viewtopic.php?f=81&t=32186
  80.         //System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyACM0");
  81.  
  82.         // Búsqueda del puerto de comunicación según una lista previamente dada "NOMBRES_DE_PUERTOS"
  83.         CommPortIdentifier cpID_puerto = null; // requiere: import gnu.io.CommPortIdentifier;
  84.         String str_puerto = "";
  85.         // conforma la lista de puertos encontrados, por ejp { "COM1", "COM2", ... }
  86.         Enumeration enum_listaDePuertos = CommPortIdentifier.getPortIdentifiers(); // requiere: import java.util.Enumeration;
  87.         if (!enum_listaDePuertos.hasMoreElements()) {
  88.             dlgBox_mostrarErrorYFinalizar("El sistema no tiene puertos de comunicación serial, por favor conecte una tarjeta");
  89.         }
  90.  
  91.         String str_listaDePuertos = "";
  92.         String str_listaDePuertosEncontrados = "";
  93.         Boolean bool_puertoEncontrado = false;
  94.         while (enum_listaDePuertos.hasMoreElements() && !bool_puertoEncontrado) { // Mientras tenga más elementos la lista o enumeración y no se haya encontrado el puerto
  95.             // Extrae cada elemento de la enumeración y lo almacena en cpID_actualPuertoID
  96.             CommPortIdentifier cpID_actualPuertoID = (CommPortIdentifier) enum_listaDePuertos.nextElement();
  97.             str_listaDePuertos = "";
  98.             str_listaDePuertosEncontrados = str_listaDePuertosEncontrados + cpID_actualPuertoID.getName() + ", ";
  99.             for (String str_portName : NOMBRES_DE_PUERTOS) {
  100.                 str_puerto = cpID_actualPuertoID.getName();
  101.                 str_listaDePuertos = str_listaDePuertos + str_portName + ",  ";
  102.  
  103.                 //Si la "enum_listaDePuertos" coincide con alguna cadena de "NOMBRES_DE_PUERTOS id" fija la bandera
  104.                 bool_puertoEncontrado = str_puerto.equals(str_portName);
  105.                 System.out.print("\n" + str_portName + " == " + str_puerto + ": " + bool_puertoEncontrado);
  106.  
  107.                 if (bool_puertoEncontrado == true) {
  108.                     // almacena en cpID_puerto
  109.                     cpID_puerto = cpID_actualPuertoID;
  110.                     break;
  111.                 }
  112.             }
  113.         }
  114.         if (cpID_puerto == null) {
  115.             dlgBox_mostrarErrorYFinalizar("Los puertos encontrados { " + str_listaDePuertosEncontrados + " }, ninguno coincide con la lista: { " + str_listaDePuertos + " }");
  116.         } else {
  117.             System.out.println("\nPuerto encontrado: " + str_puerto);
  118.         }
  119.         // Fin Búsqueda del puerto de comunicación
  120.  
  121.         // open serial port
  122.         try {
  123.             CommPort puerto = cpID_puerto.open(this.getClass().getName(), TIEMPO_MUERTO);
  124.             puertoSerial = (SerialPort) puerto;
  125.             // forma alternativa
  126.             //puertoSerial = (SerialPort) cpID_puerto.open(this.getClass().getName(), TIEMPO_MUERTO);
  127.  
  128.             // set port parameters
  129.             puertoSerial.setSerialPortParams(VELOCIDAD_DE_DATOS, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
  130.  
  131.             // open the streams
  132.             serialEntrada = new BufferedReader(new InputStreamReader(puertoSerial.getInputStream())); // import java.io.InputStreamReader;
  133.             // forma alternativa
  134.             //serialEntrada = puertoSerial.getInputStream();
  135.             //serialReader = new BufferedReader(new InputStreamReader(serialEntrada));
  136.  
  137.             serialSalida = puertoSerial.getOutputStream();
  138.  
  139.             // add event listeners
  140.             // evento para notificar la interrupción
  141.             puertoSerial.addEventListener((SerialPortEventListener) this); // import gnu.io.SerialPortEventListener;
  142.             puertoSerial.notifyOnDataAvailable(true);
  143.  
  144.         } catch (Exception e) {
  145.             dlgBox_mostrarError(e.getMessage());
  146.             System.exit(0);
  147.         }
  148.  
  149.         // end open serial port
  150.     }
  151.  
  152.     void enviarCaracteres(String char_caracteres) {
  153.         try {
  154.             // Escribir en el buffer la cadena de caracteres, cada elemento de la cadena se convierte a carácter
  155.             serialSalida.write(char_caracteres.getBytes());
  156.         } catch (Exception e) {
  157.             dlgBox_mostrarErrorYFinalizar("ERROR AL ENVIAR EL CARACTER" + char_caracteres);
  158.         }
  159.     }
  160.  
  161.     void enviarCaracter(char char_caracter) {
  162.         try {
  163.             // Escribir en el buffer el carácter
  164.             serialSalida.write(char_caracter);
  165.         } catch (Exception e) {
  166.             dlgBox_mostrarErrorYFinalizar("ERROR AL ENVIAR EL CARACTER" + char_caracter);
  167.         }
  168.     }
  169.  
  170.     private void dlgBox_mostrarError(String str_mensaje) {
  171.         JOptionPane.showMessageDialog(null, str_mensaje, "ERROR:", JOptionPane.ERROR_MESSAGE);
  172.     }
  173.  
  174.     private void dlgBox_mostrarErrorYFinalizar(String str_mensaje) {
  175.         JOptionPane.showMessageDialog(null, str_mensaje, "ERROR:", JOptionPane.ERROR_MESSAGE);
  176.         System.out.println("\nAplicación finalizada, por error en tiempo de ejecución\n");
  177.         System.exit(0);
  178.         // return;
  179.     }
  180.  
  181.     /**
  182.      * This should be called when you stop using the port. This will prevent
  183.      * port locking on platforms like Linux.
  184.      */
  185.     public synchronized void close_serialPort() {
  186.         //synchronized(Configuracion_JAVA_μControlador_RXTXlibrary.class){
  187.         if (puertoSerial != null) {
  188.             puertoSerial.removeEventListener();
  189.             puertoSerial.close();
  190.         }
  191.     }
  192.  
  193.     /**
  194.      * Handle an event on the serial port. Read the data and print it. Each info
  195.      * send by μControlador is taken here, evento para capturar datos enviados desde
  196.      * Arduino
  197.      */
  198.     @Override
  199.     public synchronized void serialEvent(SerialPortEvent oEvent) {
  200.         // si se ha terminado de recibir una cadena de caracteres
  201.         if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
  202.             try {
  203.                 String str_lineaDeEntrada = serialEntrada.readLine();
  204.                 //  Analice el dato enviado por μControlador
  205.                 parsingReceivedLine(str_lineaDeEntrada);
  206.             } catch (Exception e) {
  207.                 System.err.println(e.toString());
  208.             }
  209.         }
  210.         // Ignore all the other eventTypes, but you should consider the other ones.
  211.     }
  212.  
  213.     // Analizador sintáctico de la línea recibida
  214.     private void parsingReceivedLine(String str_lineaDeEntrada) {
  215.         //System.out.println(str_lineaDeEntrada.endsWith("\n"));
  216.         if (str_lineaDeEntrada.startsWith("ACmd:") && str_lineaDeEntrada.length() <= LONGITUD_DE_CADENA) {
  217.             // imprima el dato enviado del μControlador
  218.             System.out.println(str_lineaDeEntrada.substring(5, str_lineaDeEntrada.length()));
  219.         } else {
  220.             System.out.println(str_lineaDeEntrada);
  221.         }
  222.     }
  223.  
  224. }

Ejemplo #1, se desea prender y apagar 2 LEDs enviando comandos de control desde JAVA, comandos de 1 solo carácter y que despliegue información solo por consola, aunque también podría incorporar una GUI
'1' para LED1_ON, '2' para LED1_OFF,  '3' para LED2_ON,  '4' para LED2_OFF 

Solución:
Código: Java
  1. // Archivo JAVA: manejoDeLEDsDesdeJAVA
  2. /**
  3.  *
  4.  * @author compSystems
  5.  */
  6. public class manejoDeLEDsDesdeJAVA {
  7.  
  8.     public static void delay(int int_delay_ms) throws InterruptedException {
  9.         Thread.sleep(int_delay_ms);
  10.     }
  11.  
  12.     public static void main(String[] args) throws InterruptedException {
  13.         // TODO code application logic here
  14.         Configuracion_JAVA_uCtrol_RXTX_library SERIAL = new Configuracion_JAVA_uCtrol_RXTX_library();
  15.  
  16.         SERIAL.parametrosComunicacion(2000, 115200, "COM3", 20);
  17.         SERIAL.inicializarConexion();
  18.  
  19.         delay(1000);
  20.         SERIAL.enviarCaracteres("1"); // LED1_ON
  21.         delay(1500);
  22.         SERIAL.enviarCaracteres("0"); // LED1_OFF
  23.         delay(1500);
  24.         SERIAL.enviarCaracteres("2"); // LED2_ON
  25.         delay(1500);
  26.         SERIAL.enviarCaracteres("3"); // LED2_OFF
  27.         delay(1500);
  28.  
  29.         SERIAL.enviarCaracter('1'); // LED1_ON
  30.         delay(1500);
  31.         SERIAL.enviarCaracter('0');
  32.         delay(1500);
  33.         SERIAL.enviarCaracter('2');
  34.         delay(1500);
  35.         SERIAL.enviarCaracter('3');
  36.         delay(1500);
  37.        
  38.         SERIAL.close_serialPort();
  39.     }
  40. }

//
Código: C
  1. // Archivo ARDUINO: manejoDeLEDsDesdeJAVAver1.ino
  2. unsigned char uChar_entrada;  // para un solo caracter leido
  3.  
  4. #define LED1 22 // 13 LED incorporado en las ARDUINO BOARDs
  5. #define LED2 26
  6.  
  7. void setup() {
  8.   Serial.begin(115200);
  9.  
  10.   pinMode(LED1, OUTPUT); digitalWrite(LED1, LOW);
  11.   pinMode(LED2, OUTPUT); digitalWrite(LED2, LOW);
  12.    
  13.   Serial.print("inicio de conexion JAVA: <-> ARDUINO\n");
  14.   delay(250);
  15.  
  16.   Serial.print("prueba del led pin#20 y #26\n");
  17.   digitalWrite(LED1, LOW); delay(250); digitalWrite(LED1, HIGH); delay(250);  digitalWrite(LED1, LOW); delay(250);
  18.  
  19.   digitalWrite(LED2, LOW); delay(250); digitalWrite(LED2, HIGH); delay(250); digitalWrite(LED2, LOW); delay(250);
  20.   digitalWrite(LED1, LOW);
  21.  
  22.   Serial.print("ACmd:INICIO\n");
  23.   delay(1000);
  24. }
  25.  
  26. void loop() {
  27.   // Puerto serial disponible
  28.   if (Serial.available() >  0) {
  29.  
  30.     uChar_entrada = Serial.read();
  31.     // Eco a JAVA del dato leido
  32.     Serial.println((char) uChar_entrada); // (char) convierte de valor numerico a caracter
  33.     if (uChar_entrada == '1') {
  34.       Serial.println("ACmd:encender led1\n");
  35.       digitalWrite(LED1, HIGH);
  36.     }
  37.     else if (uChar_entrada == '0') {
  38.       Serial.println("ACmd:apagar led1\n");
  39.       digitalWrite(LED1, LOW);
  40.     }
  41.     if (uChar_entrada == '2') {
  42.       Serial.println("ACmd:encender led2\n");
  43.       digitalWrite(LED2, HIGH);
  44.     }
  45.     else if (uChar_entrada == '3') {
  46.       Serial.println("ACmd:apagar led2\n");
  47.       digitalWrite(LED2, LOW);
  48.     }
  49.  
  50.   }
  51.   else {
  52.     //Serial.println("ACmd:no disponible" );
  53.   }
  54.   delay(100);
  55. }
  56. //



Título: Re:Conexión μCtrol (ARDUINO, RASPBERRY- π, …) <-> JAVA(PC/LINUX/MAC)
Publicado por: CompSystems en 26 de Marzo de 2016, 13:33:15
Ejemplo #2 Igual al anterior, pero enviando ya no un carácter, sino un mensaje


//
Código: Java
  1. // Archivo: manejoDeLEDsDesdeJAVA con Mensajes de Control
  2. /**
  3.  *
  4.  * @author compSystems
  5.  */
  6. public class manejoDeLEDsDesdeJAVA {
  7.  
  8.     public static void delay(int int_delay_ms) throws InterruptedException {
  9.         Thread.sleep(int_delay_ms);
  10.     }
  11.  
  12.     public static void main(String[] args) throws InterruptedException {
  13.         // TODO code application logic here
  14.         Configuracion_JAVA_uCtrol_RXTX_library SERIAL = new Configuracion_JAVA_uCtrol_RXTX_library();
  15.  
  16.         SERIAL.parametrosComunicacion(2000, 115200, "COM3", 20);
  17.         SERIAL.inicializarConexion();
  18.  
  19.         delay(1500);
  20.         SERIAL.enviarCaracteres("LED1_ON\n");
  21.         delay(1500);
  22.         SERIAL.enviarCaracteres("LED1_OFF\n");
  23.         delay(1500);
  24.         SERIAL.enviarCaracteres("LED2_ON\n");
  25.         delay(1500);
  26.         SERIAL.enviarCaracteres("LED2_OFF\n");
  27.         delay(1500);
  28.  
  29.         SERIAL.close_serialPort();
  30.     }
  31. }
  32. //

//
Código: C
  1. // Archivo ARDUINO: manejoDeLEDsDesdeJAVAver2.ino
  2. #define LED1 22 // 13 LED incorporado en las ARDUINO BOARDs
  3. #define LED2 26
  4. unsigned char uChar_entrada = ' ';  // para un solo carácter leído (0, ... 256)
  5. String str_mensaje = "";  // para n caracteres leídos
  6. bool flag = false;
  7. void setup() {
  8.   Serial.begin(115200);
  9.  
  10.   pinMode(LED1, OUTPUT); digitalWrite(LED1, LOW);
  11.   pinMode(LED2, OUTPUT); digitalWrite(LED2, LOW);
  12.  
  13.   Serial.print("inicio de conexión JAVA: <-> ARDUINO\n");
  14.   delay(250);
  15.  
  16.   Serial.print("prueba del led pin#20 y #26\n");
  17.   digitalWrite(LED1, LOW); delay(250); digitalWrite(LED1, HIGH); delay(250);  digitalWrite(LED1, LOW); delay(250);
  18.  
  19.   digitalWrite(LED2, LOW); delay(250); digitalWrite(LED2, HIGH); delay(250); digitalWrite(LED2, LOW); delay(250);
  20.   digitalWrite(LED1, LOW);
  21.  
  22.   Serial.print("ACmd:INICIO\n");
  23.   delay(1000);
  24. }
  25.  
  26. void loop() {
  27.  
  28.   //if (Serial.available() > 0) {
  29.   //concatenar();
  30.   /* Se lee carácter por carácter por el puerto serie, mientras, se va
  31.     concatenando uno tras otro en una cadena. */
  32.   while (Serial.available() > 0) { // Puerto serial disponible
  33.     uChar_entrada = Serial.read();
  34.     str_mensaje.concat(uChar_entrada);
  35.     delay(1); // Este retardo muy corto es para no saturar el puerto
  36.     // serie y que la concatenación se haga de forma ordenada.
  37.   }
  38.  
  39.  
  40.   if (str_mensaje.equals("LED1_ON") == true) { // Si la cadena o str_mensaje es igual a "LED1_ON"
  41.     Serial.print("ACmd:LED1 ENCENDIDO\n"); // Envía mensaje
  42.     digitalWrite(LED1, HIGH); // El Led 1 se enciende
  43.     flag = true;
  44.   } else if (str_mensaje.equals("LED1_OFF") == true) {
  45.     Serial.print("ACmd:LED1 APAGADO\n");
  46.     digitalWrite(LED1, LOW); // El Led 1 se apaga
  47.     flag = true;
  48.   } else if (str_mensaje.equals("LED2_ON") == true) {
  49.     Serial.print("ACmd:LED2 ENCENDIDO\n");
  50.     digitalWrite(LED2, HIGH); // El Led 2 se enciende
  51.     flag = true;
  52.   } else if (str_mensaje.equals("LED2_OFF") == true) {
  53.     Serial.print("ACmd:LED2 APAGADO\n");
  54.     digitalWrite(LED2, LOW); // El Led 2 se apaga
  55.     flag = true;
  56.   } else flag = false;
  57.  
  58.   if (flag == true) {
  59.     // Limpiamos la cadena para volver a recibir el siguiente str_mensaje.
  60.     str_mensaje = "";
  61.   }
  62.  
  63. }
  64. //}
  65.  
  66. void concatenar() {
  67.   /* Se lee carácter por carácter por el puerto serie, mientras, se va
  68.     concatenando uno tras otro en una cadena. */
  69.   while (Serial.available() > 0) { // Puerto serial disponible
  70.     uChar_entrada = Serial.read();
  71.     str_mensaje.concat(uChar_entrada);
  72.     delay(10); // Este retardo muy corto es para no saturar el puerto
  73.     // serie y que la concatenación se haga de forma ordenada.
  74.   }
  75. }
  76. //

El código arduino de este segundo ejemplo tiene problemas,  :( no he logrado ponerlo a punto, es decir debo leer el buffer de los datos enviados desde JAVA y compararlos con una cadena de caracteres para poder luego activar o desactivar un LED, por favor revisan el código en ARDUINO y me comentan que estoy realizando mal

Gracias
Título: Re:Conexión μCtrol (ARDUINO, RASPBERRY- π, …) <-> JAVA(PC/LINUX/MAC)
Publicado por: CompSystems en 27 de Marzo de 2016, 13:38:21
un documento muy bien detallado JAVA-ARDUINO
https://drive.google.com/file/d/0B6HKwsbbpgrLa0VTT1JwdV96OUk/view

Fuente (BLOG):
http://electronica-pic.blogspot.com.co/2015/12/interfaz-java-y-arduino.html

Video
Título: Re:Conexión μCtrol (ARDUINO, RASPBERRY- π, …) <-> JAVA(PC/LINUX/MAC)
Publicado por: micro_pepe en 07 de Agosto de 2016, 18:08:00
Muy bueno el tuto, gracias, me ha servido de mucho.

Uso win7 de 64bits, necesité instalar la RXTX de 64bits.

Saludos!!!