Desde la versión 3.0.0, la librería PanamaHitek_Arduino cuenta con una clase especial para facilitar la tabulación y exportación de datos a una hoja de cálculo de Excel. Esta clase, llamada PanamaHitek_DataBuffer, permite almacenar datos, crear una interfaz gráfica con un JTable que tabula la información recibida y permite exportar los datos almacenados a Excel.
En el siguiente artículo voy a tratar de explicar, paso por paso, como crear una sencilla interfaz que permita tabular los datos recibidos desde Arduino, con la posibilidad de exportar los datos a Excel al presionar un botón.
Creación de proyecto e importación de librería en Netbeans
Para el ejemplo que voy a mostrar en este post voy a crear un proyecto al que voy a llamar excel_test. Será un proyecto Maven, al que voy a agregar las dependencias de la librería PanamaHitek_Arduino, tal como se explica en este post.
Recordemos que para poder utilizar la librería, es necesario agregar lo siguiente al fichero pom.xml (generado por defecto a la hora de crear el proyecto en Netbeans):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<repositories> <repository> <id>jitpack.io</id> <url>http://jitpack.io</url> </repository> </repositories> <dependencies> <dependency> <groupId>com.github.PanamaHitek</groupId> <artifactId>PanamaHitek_Arduino</artifactId> <version>3.0.0</version> </dependency> </dependencies> |
Luego de agregar las dependencias, al hacer clic derecho sobre el proyecto y seleccionar «Clean and Build» se descargaron todas las dependencias de manera automática. También haciendo clic en Dependencies/Download Declared Dependencies se descarga todo lo necesario para el uso de la librería.
Las instrucciones sobre este proceso se muestran en este video.
Creación de la interfaz gráfica
La interfaz gráfica que utilizará para este ejemplo será muy sencilla. Se trata de un JFrame, con un JPanel y un botón, tal como se muestra en la siguiente imagen.
La clase PanamaHitek_DataBuffer utiliza un JPanel para visualizar la tabla en la cual se van a recibir los datos.
Código en Arduino
Para poder probar que nuestra aplicación funciona, será necesario escribir un pequeño código en Arduino y estar seguros de qué es lo que hace este código. En base a esto es que en Java se configura el comportamiento de la aplicación.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int t = 0; int h = 0; void setup() { Serial.begin(9600); } void loop() { t = random(20,40); h = t + 50; Serial.println(t); Serial.println(h); delay(3000); } |
Lo que hace este código es, básicamente, generar datos de temperatura de manera aleatoria. Al número generado se le agregan 50 unidades para producir un dato de humedad. Luego los dos números se imprimen en el monitor serie de dos en dos.
Es muy importante tomar en cuenta que los datos deben ser impresos utilizando Serial.println y en el mismo orden en el que se espera recibirlos en Java.
Programación en Java
La programación en Java requiere de la declaración de instancias de 4 clases:
- PanamaHitek_Arduino, para la gestión de la conexión con Arduino y para recibir los datos en Java
- PanamaHitek_MultiMessage, para discriminar los datos recibidos cuando se trata de múltiples envíos de manera simultánea.
- PanamaHitek_DataBuffer, para almacenar los datos recibidos en la memoria dinámica. Esta clase también permite renderizar un JTable en el que se insertan los datos de manera dinámica. También es la clase encargada de exportar los datos a Excel a voluntad del usuario.
- SerialPortEventListener, para gestionar los eventos de recepción de datos y la inserción de la información en el DataBuffer.
Toda la programación que se necesita para darle funcionalidad a esta interfaz estará ubicada en el constructor de la clase, es decir, en void JFrameWindow().
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
//Objeto para la gestion de la conexion con Arduino PanamaHitek_Arduino ino = new PanamaHitek_Arduino(); //Objeto para la gestion de multiples mensajes recibidos desde Arduino PanamaHitek_MultiMessage multi = new PanamaHitek_MultiMessage(2, ino); //Objeto para la gestion y almacenamiento de datos recibidos PanamaHitek_DataBuffer buffer = new PanamaHitek_DataBuffer(); public JFrameWindow() { initComponents(); /** * Se crea la tabla de datos, agregando 3 columnas. Se especifica la * posicion de la columna (0 es la más a la izquierda), el nombre de la * columna y el tipo de datos */ buffer.addTimeColumn(0, "Tiempo"); buffer.addColumn(1, "Temperatura", Double.class); buffer.addColumn(2, "Humedad", Double.class); //Se inserta la tabla en un panel para poder verla en la interfaz buffer.insertToPanel(jPanel1); /** * Con este objeto se gestiona la recepcion de datos. El evento * serialEvent se "disparara" cada vez que se reciba un dato desde * Arduino enviado a traves del puerto serie */ SerialPortEventListener listener = new SerialPortEventListener() { @Override public void serialEvent(SerialPortEvent serialPortEvent) { try { /** * Este metodo indica cuando se haya terminado de recibir * los datos de los DOS sensores especificados en la * creacion del objeto "multi" */ if (multi.dataReceptionCompleted()) { /** * Se agregan los valores al buffer, especificando el * Ãndice de la columna y el valor. Se utiliza el objeto * "multi" para separar los datos recibidos desde * Arduino, especificando el indice. */ buffer.addValue(1, Double.parseDouble(multi.getMessage(0))); buffer.addValue(2, Double.parseDouble(multi.getMessage(1))); buffer.addValue(3, 27); //Se salta un "renglon" en el buffer de datos buffer.printRow(); /** * Se le indica al objeto multi que se ha terminado de * imprimir los datos recibidos desde el Arduino y que * puede prepararse para recibir un nuevo par de datos */ multi.flushBuffer(); } } catch (ArduinoException ex) { Logger.getLogger(JFrameWindow.class.getName()).log(Level.SEVERE, null, ex); } catch (SerialPortException ex) { Logger.getLogger(JFrameWindow.class.getName()).log(Level.SEVERE, null, ex); } catch (Exception ex) { Logger.getLogger(JFrameWindow.class.getName()).log(Level.SEVERE, null, ex); } } }; try { //Se inicia la conexion con el puerto COM21 a 9600 baudios ino.arduinoRX("COM15", 9600, listener); } catch (ArduinoException | SerialPortException ex) { Logger.getLogger(JFrameWindow.class.getName()).log(Level.SEVERE, null, ex); } } |
Es un código relativamente sencillo, en el que se inicia una conexión con el Arduino a través del puerto COM15. El buffer tendrá 3 columnas (tiempo, temperatura y humedad), pero se le podrán agregar más si se desea.
Con la instrucción buffer.insertToPanel(jPanel1) nos aseguramos que los datos del buffer sean mostrados en una tabla en el jPanel1, tal como se muestra en la siguiente imagen.
Los datos serán insertados en la tabla cada vez que se utilice el método buffer.printRow(), mientras que para insertar la información en cada columna se debe utilizará buffer.addValue(2, 15) (esto permitirá insertar el valor 15 en la columna 2. Debemos recordar que las columnas se enumeran a partir de 0, por lo que la columna 2 será la tercera).
Para exportar los datos almacenados en el DataBuffer a Excel, se utiliza la instrucción buffer.exportExcelFile(), la cual abrirá una ventana que permitirá escoger la ruta en la que se desea almacenar el fichero. Esta instrucción debe colocarse en el botón de exportar.
A continuación presento para ustedes un video en el cual se resume todo lo explicado en este post. El video inicia en el minuto 7:00, donde ya se muestra el resultado de la ejecución del código:
El código utilizado en este artículo se encuentra completo en nuestro repositorio de Github, específicamente en este enlace.
Debo recordar a todos nuestros lectores que esta compilación de código ha sido diseñada para facilitar las tareas de interacción entre Arduino y Java para todas aquellas personas que con pocos conocimientos de programación podrán lograr cosas interesantes y sacar sus proyectos e ideas adelante.
Buena noche, Sera posible enviar los datos almacenados en una SD en vez de la lectura en tiempo real?
Si logras leer los datos y enviarlos por el puerto serie, si es posible
Buenos dias seria posible hacer esto pero con una conexión por Bluethooth?
Sí es posible
Saludos Ingeniero Antony, muchísimas gracias por sus aportes.
Tengo una inquietud que puede se errada, es con relación a la librería PanamaHitek_Arduino-3.0.1 la cual en su clase PanamaHitek_DataBuffer hace referencia a las clases
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
las cuales generan error ya no se encuentran en poi.3.17 sino en poi 3.7
Al realizar el ejemplo con la versión PanamaHitek_Arduino-3.0 genra errores.
Gracias por su aclaración.
Por ultimo, todavía esta disponible la librería par el manejo del sensor HCSR04.
Gracias
Hola. No entiendo el problema… para qué estas usando POI? Y cuál versión estás usando?
Saludos ingeniero, la librería PanamaHitek 3.1 hace uso de poi 3.17 en la clase PanamaHitek_DataBuffer, y se generan los siguientes errores
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
Al descargar de Maven, el pom hace referencia al poi 3.17 y las clases anteriores aparecen pero en la versión 3.7
He lanzado la versión 3.0.1, ahora con Apache POI 4.1.0
Verifica, por favor, si se ha corregido el error. Gracias.
Ingeniero ¿Ya no esta disponible la librería par el manejo del sensor HCSR04?
Ya la resubí
Gracias Ingeniero, eres genial!!!
Gracias Antony, eres genial!!!
Gracias a ti por visitarme y comentar
Hola Ingeniero quiero utilizar la libreria pero no quiero hacerlo con maven sino crear un programa java normal. Es decir descargue la libreria y la coloque en las librerias del proyecto, pero la clase PanamaHitek_DataBuffer da errores de complicación aunque las reconoce en el codigo como que si las hubiera importado.
El error empieza como sigue:
Exception in thread «AWT-EventQueue-0» java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Row
at ExcelExport.(ExcelExport.java:62)
Las clases PanamaHitek_Arduino y PanamaHitek_MultiMessage si corren bien y es lo que me extraña porque probe el programa sin usar el objeto buffer
Creo que tienes que importar la librería POI a tu proyecto. Maven lo hace automáticamente, pero en tu caso creo que debe hacerse manualmente
Buenos días estoy intentando utilizar la libreria, pero la verdad no se mucho de java ni de base de datos pero hice todo lo del video pero corro la aplicacion de excel y me aparece la ventana pero no me captura datos y reviso y el arduino si esta enviando datos, no se si ademas del netbeans se debe estar corriendo otro programa
com.panamahitek.ArduinoException: Nomrbe del puerto – COM9; Nombre del método – arduinoRX(); Tipo de excepción – Puerto no abierto.
at com.panamahitek.PanamaHitek_Arduino.arduinoRX(PanamaHitek_Arduino.java:260)
at examples.excel.ExcelExport.(ExcelExport.java:128)
at examples.excel.ExcelExport$3.run(ExcelExport.java:242)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Seguramente estás tratando de abrir el programa en Java con el Monitor Serie del Arduino abierto
Ingeniero buenas tardes, estoy intentando agregar el buffer a un scroll para correr los datos, es posible o el buffer ya viene con su scroll
y como hago para guardar esos datos en la base de datos?
Saludos ingeniero, mi duda es la siguiente:
Estoy tratando de utilizar este mismo ejemplo, solo que en vez de mostrar los datos en una tabla, quiero dividirlos en JLabels, mis preguntas son: ¿Es posible hacerlo? Si es posible, ¿Como podría hacerlo?, ya que lo he intentado pero no me es posible. Le agradecería mucho su ayuda.
Saludos cordiales desde México.
Es algo fácil de hacer. Comparte tu código en el foro y vemos como te podemos ayudar
Buenas Ingeniero estoy tratando de almacenar los datos enviados por 4 acelerometros, en total envia 8 datos, a una jtable
Como lo hago?
Mira estos videos:
https://www.youtube.com/watch?v=atzUeKeNQ-A
https://www.youtube.com/watch?v=wo4ts0osZV8
Ok Muchas gracias!
El Buffer necesita de alguna otra libreria para funcionar?
No
Hola tengo un problema, cuando ejecuto en netBeans sin conectar el arduino se ejecuta el codigo y muestra la interfaz, pero cuando tengo conectado el arduino enviando datos se produce un fallo de ejecucion.
A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000007110b5db, pid=11040, tid=19924
#
Podrias decirme que error puedo haber cometido. Puedo enviarte el .log si lo deseas.
Muchas gracias, un Saludo.
Donde te aparece ese error?
Hola ingeniero Antony. Tengo un problema cn la programación; al momento de correr el «ExcelExport» descarga un par de cosas y finaliza instantáneamente, aparece el mensaje de «Build Success», en ningún momento se muestra la ventana cn los datos ni mucho menos me deja finalizarla.
Cuál puede ser el problema?
Muchas gracias
Comparte tu código en el foro
Buenas ingeniero segui los pasos como dicta el tutorial pero me salta este error en la caja de salida, sabe que puede ser?
Cannot run program «cmd» (in directory «C:\Users\Usuario\Documents\xavier\arduino\PanamaHitek_Arduino»): Malformed argument has embedded quote: «C:\Program Files\NetBeans 8.0.1\java\maven\bin\mvn.bat» -Dexec.args=»-classpath %classpath examples.excel.ExcelExport» -Dexec.executable=»C:\Program Files\Java\jdk1.8.0_231\bin\java.exe» -Dexec.classpathScope=test -Dmaven.ext.class.path=»C:\Program Files\NetBeans 8.0.1\java\maven-nblib\netbeans-eventspy.jar» -Dfile.encoding=UTF-8 process-test-classes org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
Eso parece estar asociado a la versión del SDK que estás utilizando. La librería está hecha para trabajar en Java 1.8 y posiblemente tu proyecto esté utilizando Java 11 o Java 12
Muchas gracias por la respuesta, disculpa la molestia se debes estar ocupado. Borre y volví a instalar todo fijando bien sea java 1,8 y aun asi tira el mismo error. Nose si estoy entendiendo bien que java deberia bajar. Se que es muchas molestia lo que te digo pero te adjunto el link de donde lo baje a ver si podras decirme rapidamente y es o no lo que deberia bajar.
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
Gracias
No se trata de instalar el SDK, sino de escoger el compilador y la versión del código en el IDE que estés utilizando, sea Netbeans, Eclipse u otro
Hola Ing.
me aparece este error
Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:exec (default-cli) on project PanamaHitek_Arduino: Command execution failed.: Process exited with an error: 1 (Exit value: 1) -> [Help 1]
To see the full stack trace of the errors, re-run Maven with the -e switch.
Re-run Maven using the -X switch to enable full debug logging.
For more information about the errors and possible solutions, please read the following articles:
[Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
Eso parece como un problema de Maven. Trata de compilar el proyecto primero antes de ejecutarlo, para que Maven descargue las dependencias