La información suministrada en este post es considerada por mi persona como obsoleta debido a que fue publicada antes de mi librería Arduino para Java. Recomiendo visitar el siguiente post donde se explica el uso de la misma y donde es muy fácil comunicar Arduino con Java y vice versa.
***
Hola amigos. En las últimas semanas he estado escribiendo mucho acerca de Arduino, de Java y de como podemos utilizar ambas plataformas para realizar grandes proyectos. Empecé escribiendo como establecer Comunicación Serial con Arduino. Luego escribí como enviar datos de Java a Arduino a través de los métodos ArduinoConnection() y EnviarDatos().
Ahora es tiempo de aprender como recibir datos en Java desde Arduino. Para ello utilizaremos un método similar a EnviarDatos(): RecibirDatos().
Para poder utilizar este método necesitamos modificar nuestra función ArduinoConnection() y declarar algunas variables.
Los datos que enviamos de Arduino a Java se envían a través de una variable OutputStream llamada Output. Ahora declararemos una variable del tipo InputStream llamada Input.
private InputStream Input;
Resumiendo, las variables que necesitamos utilizar para comunicar Arduino y Java, y vice versa, son las siguientes:
1 2 3 4 5 6 |
private OutputStream Output = null; private InputStream Input = null; SerialPort serialPort; private final String PORT_NAME = "COM3"; private static final int TIME_OUT = 2000; private static final int DATA_RATE = 9600; |
Ahora necesitamos inicializar la variable Input. Esto se hace en la función ArduinoConnection() donde ya existe una línea que inicializa la variable Output.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public void ArduinoConnection() { CommPortIdentifier portId = null; Enumeration portEnum = CommPortIdentifier.getPortIdentifiers(); while (portEnum.hasMoreElements()) { CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement(); if (PORT_NAME.equals(currPortId.getName())) { portId = currPortId; break; } } if (portId == null) { System.exit(ERROR); return; } try { serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT); serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); Output = serialPort.getOutputStream(); //Se prepara a Output //para enviar datos Input = serialPort.getInputStream(); //Se prepara input para //recibir datos serialPort.addEventListener(this); //Se agrega un Event //Listener serialPort.notifyOnDataAvailable(true); //Se indica que se //notifique al usuario cuando sea que halla datos disponibles en //el puerto serie } catch (Exception e) { System.exit(ERROR); } } |
Como vemos, se prepara a la variable Input de la misma manera que a la variable Output. Hemos agregado 2 líneas más a nuestra función ArduinoConnection():
1 2 |
serialPort.addEventListener(this); serialPort.notifyOnDataAvailable(true); |
Esto permite que se genere un evento cada vez que Arduino envíe datos a Java. Para poder que esto funcione es necesario que implementemos la interfaz SerialPortEventListener de la misma manera que implementamos la interfaz Runnable cuando utilizamos los Java Threads.
Por último necesitamos agregar un método en donde se establezca las acciones que se harán cuando ocurra un SerialPortEvent.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public synchronized void serialEvent(SerialPortEvent oEvent) { if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) { try { int datos; datos = RecibirDatos(); //Se invoca la función RecibirDatos() //Esta función devolverá un valor entero en formato ASCII. System.out.println((char)datos); //Se imprime en el mensaje //haciendo la conversión de ASCII a nuestro alfabeto. } catch (Exception e) { System.err.println(e.toString()); } } } |
Por último agregamos RecibirDatos():
1 2 3 4 5 |
private int RecibirDatos() throws IOException { int Output = 0; Output = Input.read(); return Output; } |
Con estas variables y estos métodos podemos lograr lo que queremos. Ahora es tiempo de probar si funciona o no.
Yo agregué los elementos necesarios al ejemplo Blink que ya hicimos:
Ahora vamos a Arduino y escribimos lo siguiente:
1 2 3 4 5 6 7 8 9 10 |
int count=0; void setup(){ Serial.begin(9600); } void loop(){ Serial.print(count); count++; delay(1000); } |
Con estos cambios estamos listos para ver como trabaja nuestro código. Lo que haremos es enviar el valor de una variable, en este caso, count, de Arduino a Java, con la salvedad de que cada segundo se aumentará el valor de count en 1 unidad.
Utilizamos Serial.print para enviar el mensaje. Si utilizamos println enviaremos el mensaje con un salto de renglón. Si utilizamos Serial.write, entonces no enviaremos el mensaje en ASCII sino como bits. El problema con esto es que es un bus de 8 bits, por lo que no podremos enviar valores más arriba del 255, ya que 2 elevado a la octava potencia es 256 y el bus solo admite 8 bits, del 0 al 255.
Aquí vemos la demostración:
Como podemos observar los datos se envían 1 a 1, es decir, caracter a caracter.
Espero sus comentarios. Saludos.
Disculpa no entra al EventListener
¿Podrías ser un poco más específico en cuanto al error que se está presentando?
interesante el aporte, probare el código, saludos
Gracias por comentar
Primero que nada muchas gracias por todos los tutoriales, han sido de muchisima ayuda…
una duda, al momento de implementar SerialPortEventListener, quitamos el Runnable y ahora ya no me sirven los hilos…
Que puedo hacer??
Puedes implementar Runnable y SerialPortEventListener al mismo tiempo. Solo tienes que agregarlo arriba y te dejará usar hilos. Si no me equivoco, colocas implements SerialPortEventListener, Runnable
Ya lo pude solucionar, todo funciono de maravilla!
Muchas gracias!!
A la orden
hola amigo!! primero que nada quiero agradecerte por este gran aporte!!!
y quisiera hacerte una pregunta, lo que pasa que estoy haciendo un programa en java y arduino, pero a la ora de enviar un numero como 10, 20 30 etc,
en java se muestra:
1
0
hay alguna forma de que me imprima el 10??
No. Necesitas hacer lectura dígito a dígito. Yo por ejemplo envío 3 dígitos y en Arduino los leo de la siguiente manera:
int c; int d; int u; int num;
c=Serial.read();
delay(10)
d=Serial.read()
delay(10)
u=Serial.read();
num=(100*c)+(100*d)+u;
Ahí está
Hola:
Tienes algún otr tutorial en el que se reciban datos de manera ininterrumpida desde arduino?. Por ejemplo con un botón de start y otro de parada para detener.
Te recomiendo utilizar mi librería Arduino para Java:
https://panamahitek.com/2013/03/08/libreria-arduino-para-java/
muchas gracias, aunque me gustaría resolver primero mi problema. Un saludo
Con la librería Arduino puedes hacer eso que necesitas hacer sin problemas. Revísala
Las imágenes son de gran ayuda para entender el proceso que se realizo, no se si están dañadas o es problema del pc pero no logro verlas. No entiendo muy bien la parte de los hilos, ¿estos son obligatorios?¿como van a funcionar en la aplicación? Le agradecería su colaboración. Gracias
Recomiendo visitar el siguiente post:
https://panamahitek.com/2013/03/08/libreria-arduino-para-java/
Ese tutorial ya lo he visto y me parece muy buena esa librería, ahorra trabajo.
Pude mandar valores constantes a Netbeans, igual que el vídeo pero en la aplicación que estoy trabajando son datos de un sensor de temperatura y humedad, si tengo float h = 5; lo envía a Netbeans pero al colocar float h = dht.readHumidity(), ya la aplicación no me funciona. Sera que tengo que meterle alguna otra librería a Netbeans? Y para mostrar los datos en un lbl tengo jLabel1.setText(Arduino.PrintMessage()); No se si sea la correcta! Agradecería tu ayuda!
Recomiendo el siguiente post:
https://panamahitek.com/2013/02/17/arduinojava-graficadora-de-datos-de-sensores/
https://panamahitek.com/2013/09/22/graficas-de-sensores-en-tiempo-real-con-arduino-java-y-jfreechart/
Disculpa amigo, no me funciona. serialPort.addEventListener(this); me lo marca como error. A qué se debe??Saludos.
podrias subir el codigo a algun servidor para descargarlo??
Recomiendo no utilizar este código sino la librería Arduino para Java, con la que he logrado hacer esto mucho más fácil y rápido:
https://panamahitek.com/libreria-arduino-para-java/
Me aparece un error cuando corro el programa «Arduino.arduino» a que se debe y como lo corrijo gracias.
Donde aparece este error?
Me aparece cuando intento enviar serial con TX después de haber iniciado la conexión. Inicio la conexión y luego intento inicializarla en otra parte y me aparece ese error.
hola muy buen aporte, estoy probando la libreria arduino y lo que intento es mostrar los datos leidos desde el arduino y en lugar de graficarlo me muestre el valor en un textField pero no logro hacerlo no se si tengas idea como puedo resolver esto
este es lo que hago:
jTextField1.setText(Arduino.PrintMessage());
y solo me muestra la leyenda que no hay datos disponibles pero si me grafica los datos
Lo que sucede es que al graficar estas enviando el valor de la variable a las gráficas y el textfield trata de leer el siguiente valor en la fila del puerto serie, el cual es un valor nulo. Lo que tienes que hacer es leer la variable, luego en un proceso separado graficar y enviar al jTextField. Una vez leido el valor que se recibe por medio de printMessage, el mismo no puede usarse para nada mas, a menos que uses una variable que lo contenga y a partir de la misma desencadenar los demás procesos.
Saludos.
amigo eso lo quiero hacer pero al reves que de java mande a arduino si puedes subir algun codigo te lo agradeceria
estoy usando su libreria y parte de codigo nuevo en netbeans y pongo 2 potencometros que se vea la cantida de giro o sensor de humedad en un jtexfile solo dos . en el siglo de este codigo
l void serialEvent(SerialPortEvent spe) {
if (Arduino.MessageAvailable()){
if(Slot== 1){
Slot= 2;
if (lectura > 1) {lectura++; pote1= Arduino.PrintMessage();}
} else if (Slot== 2){ Slot= 1;lectura++;pote2 = Arduino.PrintMessage();
txtarduinovalue = new txtarduino();
txtarduino.setText(pote1);
txtarduino1value = new txtarduino1();
txtarduino1.setText(pote2 );
pero no me acepta un tercero quiero poner en ese mismo siglo 6 en total . gracias por su ayuda
Revisa este post: https://panamahitek.com/arduino-java-facil-y-rapido/
Y lee sobre la clase MultiMessage
gracias yo resolvi antes de ver el pos no estaba tomando el contador en el tiempo de ejecucion
Hola, tengo una duda con respecto a como muestra los datos, al ejecutar el código java y mando datos para probarlo con una terminal, pero los datos que muestra no es el que mando, por ejemplo si le mando un 1 me muestra 49 y si es 2 muestra 50 y así con todos, incluso si le mando un 0 me muestra 48, alguna idea de porque pasa eso o hay algo de lo que no me entero o si alguien mas me podría ayudar se los agradecería. Saludos y gracias
Verifica la tabla de datos ASCII
Ya solucione esa parte, pero ahora el problema esta en los datos que se reciben de uno en uno; existe alguna forma de que los datos sean por cadena; osea que si se manda 10 sea 10 y no 1 y 0. O si es la palabra hola sea hola y no h,o,l,a.
Recibir datos en donde? Arduino o Java? Te recomiendo postear tu situación en el foro –> https://panamahitek.com/foro/
En java; al final del tutorial mencionan que «los datos se envían 1 a 1, es decir, caracter a caracter»; y efectivamente asi pasa, entonces mi duda es como hacer para que no sea de uno en uno, sino que se lea todo lo enviado; e visto que usan el buffer pero no me queda claro
Para eso existe el método printMessage y isMessageAvailable()
HOLA QUIERO HACER UNA CONEXION RS485 EN CON NEETBENS YA QUE NECESITO EL CODIGO DE LOS MODULOS DEL RS485. SI HAY COMO Y QUE CODIGO TENGO QUE OCUPAR.
Podrías ser un poco más específico en lo que deseas lograr?
Esta librería podría funcionar con cualquier micro-controlador con comunicación rxtx? por ejemplo los pics o atmel que no estén grabados.
Si. La he utilizado un par de veces con dispositivos que no son Arduino y funciona
Buenas tardes.
Necesito enviar información de un Arduino a Java Netbeans…
La programación el Arduino es mediante cadena serial.printl. Mi pregunta es:Que codigo puedo usar para recibir datos de un arduino serial.print a un Jframe en Netbeans? Te agradezco de corazón.
Mira este video: https://www.youtube.com/watch?v=atzUeKeNQ-A
No sirve, pues necesito es tomar información de un serial.printl en arduino que quede en JFrame en Java
No te sirve a ti, pero a mucha gente si le es útil
buena tarde Antony, de ante mano agradezco toda la informacion y las herramientas que haz podido facilitar usted y su equipo.
estoy en el desarrollo de un proyecto para automatización de invernaderos. la interfaz la estoy desarrollando en java, en mi sesión principal se despliega una grafica que me muestra todos los sensores conectados a mi arduino. y en la segunda ventana los despliega de manera individual, al abrir una ventana nueva me arrojaba un error multiplex conexiones abiertas, lo cual solucione con un killArduinoConnection, pero al retornar a la ventana principal los la grafica deja de tener actividad pero los datos siguen llegando desde el puerto serie. ¿desde su experiencia como podría dar solución?. es decir que la conexión no se interrumpa y que al conectar un arduino a la pc automáticamente comience la visualización de los datos.
Para evitar que te aparezca el error de múltiples conexiones abiertas tienes que usar una única instancia de la librería. Por ejemplo, si creas el objeto:
static PanamaHitek_Arduino ino = new PanamaHitekArduino();
Puedes hacer que cuando abres un JFrame le pases como parámetro el objeto ino y en el constructor se lo asignas a alguna variable privada dentro del JFrame. De esta manera no se necesita matar la conexión, pues es un solo objeto el que gestiona la comunicación.
No se si me explico…
Hola tengo este error
SEVERE: null
com.panamahitek.ArduinoException: Nomrbe del puerto – COM3; Nombre del método – arduinoRXTX(); Tipo de excepción – Puerto no abierto.
at com.panamahitek.PanamaHitek_Arduino.arduinoRXTX(PanamaHitek_Arduino.java:220)
at apiuno.Ultrasonico.(Ultrasonico.java:29)
at apiuno.ApiUno.main(ApiUno.java:7)
Alguien me puede ayudar ,Lo necesito para un proyecto.