Ejecutar jbuttons desde arduino al presionar botones físicos.
Recientemente desarrollé una aplicación utilizando arduino para manipular una interfaz gráfica a través de botones físicos conectados a arduino. La interfaz gráfica fue hecha en java, utilizando netbeans 8.0 en fedora 20.
Fue la primera vez que utilicé arduino, además también fue la primera vez que conecté arduino con java.
Cuando se usa linux, por lo general se complica lo suficiente al querer ejecutar un programa, la mayoría de las veces es por cuestiones de permisos de archivos o permisos de ejecución de archivos, así también como los permisos que tenga el directorio donde está almacenado dicho ejecutable.
Antes de comenzar es necesario que tengan instalado:
Tomaré en cuenta que ya tienen instalado los paquetes necesarios y continuaré con la explicación de la pequeña aplicación que he creado.
Se utilizó la tarjeta arduino uno.
Descripción del proyecto: crear una interfaz en java utilizando jframe con 4 botones, cada botón realizará un determinada acción. Realizar un pequeño tablero con 4 pushbuttons conectados a arduino. La idea es que cuando se presione un botón en el tablero se ejecute la acción de un botón en la interfaz desarrollada en java. De tal modo que el dispositivo de interacción sea el tablero con botones.
Realización:
Primero se creará la interfaz gráfica, lo dejaré a su criterio, es un jframe que debe de tener 4 botones.
Pueden crear una interfaz parecida a la imagen de arriba o hacer una que les convenga.
Los botones físicos que estarán conectados a arduino pueden diseñarlos o colocarlos en un protoboard.
El circuito es el siguiente:
El circuito es el siguiente:
El programa que estará codificado en arduino es el siguiente:
//se declaran los pines de entrada que se usaran
const int buttonPin = 2; //Se reserva el numero de pin de entrada
const int buttonPin2 = 3; //Se reserva el numero de pin de entrada
const int buttonPin3 = 4; //Se reserva el numero de pin de entrada
const int buttonPin4 = 5; //Se reserva el numero de pin de entrada
const int ledPin = 12; //Se reserva el numero de pin de entrada
const int ledPin2 = 11; //Se reserva el numero de pin de entrada
const int ledPin3 = 10; //Se reserva el numero de pin de entrada
const int ledPin4 = 9; //Se reserva el numero de pin de entrada
//variables que cambian de valor durante la ejecucion
int buttonState = 0; //variable que almacena el valor del estado del pin de entrada buttonPin
int buttonState2 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin2
int buttonState3 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin3
int buttonState4 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin4
int buttonStateFinal1 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin
int buttonStateFinal2 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin2
int buttonStateFinal3 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin3
int buttonStateFinal4 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin4
int sensorPin = A0; //entrada del sensor de ritmocardiaco se declara el pin que se usara
int sensorValue = 0; //variable en la que se almacena el valor leido del pin de entrada del sensor
int leerDatos=0; //variable para indicar si se continua leyendo o no;
void setup(){
//Serial.begin(115200); //Open the serial port
Serial.begin(9600); //se abre el puerto serial
//se inicializan los pines salida en caso de que se necesiten
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
//se inicializan los pines de entrada y que seran los que se tienen que leer
//para saber cual es estado de cada boton
pinMode(buttonPin, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(buttonPin4, INPUT);
}
void loop(){
//leerDatos = Serial.read();
//if(leerDatos=='1'){
// se leen los estados de cada uno de los pines de entrada
buttonState = digitalRead(buttonPin);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);
buttonState4 = digitalRead(buttonPin4);
//sensorValue = analogRead(sensorPin);
// verifica el valor leido de cada pin
// si el valor es 1 los leds se encienden, en caso contrario
// el led continua apagado
if(buttonState == HIGH){
digitalWrite(ledPin4, HIGH);
buttonStateFinal1=1;
}else{
digitalWrite(ledPin4, LOW);
buttonStateFinal1=0;
}
if(buttonState2 == HIGH){
digitalWrite(ledPin3, HIGH);
buttonStateFinal2=2;
}else{
digitalWrite(ledPin3, LOW);
buttonStateFinal2=0;
}
if(buttonState3 == HIGH){
digitalWrite(ledPin2, HIGH);
buttonStateFinal3=3;
}else{
digitalWrite(ledPin2, LOW);
buttonStateFinal3=0;
}
if(buttonState4 == HIGH){
digitalWrite(ledPin, HIGH);
buttonStateFinal4=4;
}else{
digitalWrite(ledPin, LOW);
buttonStateFinal4=0;
}
//se imprimen los valores leidos a pantalla, este proceso es necesario
//de aqui depende para que desde java se puedan leer dichos valores
Serial.println(buttonStateFinal1);
Serial.println(buttonStateFinal2);
Serial.println(buttonStateFinal3);
Serial.println(buttonStateFinal4);
//Serial.println(sensorValue);
//el programa se espera un tiempo de 100 milisegundos antes de volver
//a realizar una lectura, no es tan necesario el retardo, para
//para que java no se le haga pesado, es necesario un retardo
//}
delay(100); /*detiene el programa por 100 milisegundos antes de volver a leer los puerto*/
}
//se declaran los pines de entrada que se usaran
const int buttonPin = 2; //Se reserva el numero de pin de entrada
const int buttonPin2 = 3; //Se reserva el numero de pin de entrada
const int buttonPin3 = 4; //Se reserva el numero de pin de entrada
const int buttonPin4 = 5; //Se reserva el numero de pin de entrada
const int ledPin = 12; //Se reserva el numero de pin de entrada
const int ledPin2 = 11; //Se reserva el numero de pin de entrada
const int ledPin3 = 10; //Se reserva el numero de pin de entrada
const int ledPin4 = 9; //Se reserva el numero de pin de entrada
//variables que cambian de valor durante la ejecucion
int buttonState = 0; //variable que almacena el valor del estado del pin de entrada buttonPin
int buttonState2 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin2
int buttonState3 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin3
int buttonState4 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin4
int buttonStateFinal1 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin
int buttonStateFinal2 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin2
int buttonStateFinal3 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin3
int buttonStateFinal4 = 0; //variable que almacena el valor del estado del pin de entrada buttonPin4
int sensorPin = A0; //entrada del sensor de ritmocardiaco se declara el pin que se usara
int sensorValue = 0; //variable en la que se almacena el valor leido del pin de entrada del sensor
int leerDatos=0; //variable para indicar si se continua leyendo o no;
void setup(){
//Serial.begin(115200); //Open the serial port
Serial.begin(9600); //se abre el puerto serial
//se inicializan los pines salida en caso de que se necesiten
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
//se inicializan los pines de entrada y que seran los que se tienen que leer
//para saber cual es estado de cada boton
pinMode(buttonPin, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(buttonPin4, INPUT);
}
void loop(){
//leerDatos = Serial.read();
//if(leerDatos=='1'){
// se leen los estados de cada uno de los pines de entrada
buttonState = digitalRead(buttonPin);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);
buttonState4 = digitalRead(buttonPin4);
//sensorValue = analogRead(sensorPin);
// verifica el valor leido de cada pin
// si el valor es 1 los leds se encienden, en caso contrario
// el led continua apagado
if(buttonState == HIGH){
digitalWrite(ledPin4, HIGH);
buttonStateFinal1=1;
}else{
digitalWrite(ledPin4, LOW);
buttonStateFinal1=0;
}
if(buttonState2 == HIGH){
digitalWrite(ledPin3, HIGH);
buttonStateFinal2=2;
}else{
digitalWrite(ledPin3, LOW);
buttonStateFinal2=0;
}
if(buttonState3 == HIGH){
digitalWrite(ledPin2, HIGH);
buttonStateFinal3=3;
}else{
digitalWrite(ledPin2, LOW);
buttonStateFinal3=0;
}
if(buttonState4 == HIGH){
digitalWrite(ledPin, HIGH);
buttonStateFinal4=4;
}else{
digitalWrite(ledPin, LOW);
buttonStateFinal4=0;
}
//se imprimen los valores leidos a pantalla, este proceso es necesario
//de aqui depende para que desde java se puedan leer dichos valores
Serial.println(buttonStateFinal1);
Serial.println(buttonStateFinal2);
Serial.println(buttonStateFinal3);
Serial.println(buttonStateFinal4);
//Serial.println(sensorValue);
//el programa se espera un tiempo de 100 milisegundos antes de volver
//a realizar una lectura, no es tan necesario el retardo, para
//para que java no se le haga pesado, es necesario un retardo
//}
delay(100); /*detiene el programa por 100 milisegundos antes de volver a leer los puerto*/
}
El código de arduino parece mucho, pero las impresiones son más bien para saber qué está pasando en cada momento, así que descuiden, dependiendo de la necesidad que tengan, así pueden ir modificando dicho código.
Después de que su código ya esté codificado en la tarjeta, procedemos a crear la aplicación en java.
La clase principal, que se mostró en la primera imagen lleva el siguiente código. En realidad pueden crear sólo un jframe con 4 botones o los que consideren necesarios y listo.
/*
* La clase VentanaJuego que extiende jframe, contiene el juego principal,
es decir, ésta clase es donde se muesra en sí todo el proceso del juego.
*/
package ventanasScoop;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author neo Jesús Fernando Merino Merino
*/
public class VentanaJuego extends javax.swing.JFrame implements Runnable{
/**
* Se crea un objeto de tipo VentanaJuego para que reciba el objeto que le
* envian de la interfaz iniciarScoop, dicho objeto.
* Es aquí donde se crea el objeto que se usará para leer los datos desde arduino
*/
/*Objeto creado para manipular la interfaz del juego scoop*/
private VentanaJuego jugarJuego;
/*Se crea el objeto de tipo DatosJugador dicho objeto almacenará toda la
información necesari del jugador que inice sesión para jugar*/
private DatosJugador datosJugador;
/*variable que almacena la interfaz de inicio de sesión*/
private iniciarScoop inicioSesion;
/*variable que se usa para iniciar el sensado de la tarjeta arduino
básicamente es un hilo que se lanza, y que sólo se consultan los datos
almacenados en un vector declarado en dicha clase*/
//LecturaFromArduino lectArduino=new LecturaFromArduino();
private LecturaFromArduino lectArdReciv;
/*variable que debe de estar activada para poder realizar validaciones cuando
el usuario esté sobre esta ventana*/
private boolean permitBotArdVentJueg=true;
/*variable que almacena el hilo que se pone en ejecución para relizar la validadión
de los datos que se reciben al presionar un botón en el tapete*/
Thread obtDatArd;
public VentanaJuego() {
initComponents();
}
public VentanaJuego(VentanaJuego ventJuego,DatosJugador datJugador) {
initComponents();
}
public VentanaJuego(iniciarScoop inicio,DatosJugador datJugador) {
/*constructor que recibe el objeto de inicio de sesión y los datos del jugador*/
initComponents();
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setLocationRelativeTo(null);
setDatosJugador(datJugador);
setInicioSesion(inicio);
visulizarNomJugadorVentana();
}
public VentanaJuego(iniciarScoop inicio,DatosJugador datJugador, LecturaFromArduino lectArd) {
/*constructor que recibe el objeto de inicio de sesión, los datos del jugador
y el objeto que inicia la lectura desde arduino, para poder acceder al método
que retorna el arreglo de datos obtenidos desde arduino*/
initComponents();
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setLocationRelativeTo(null);
setDatosJugador(datJugador);
setInicioSesion(inicio);
visulizarNomJugadorVentana();
setLectArduReciv(lectArd);
iniciaValidBotArd();
}
public void ninioONinia(DatosJugador datosJugador){
/*método que valida si el usuario que a accedio es niño o niña, para modificar
el color de los íconos*/
}
public final void visulizarNomJugadorVentana(){
/*se establece el nombre del jugador en el jlabel*/
jlDatosJugador.setText("Bienvenido: "+datosJugador.getNomJugador());
}
/*inicia declaración de métodos de set y get de los atributos de esta interfaz*/
public void setVentanaJugador(VentanaJuego ventana){
jugarJuego=ventana;
}
public final void setDatosJugador(DatosJugador datos){
datosJugador=datos;
}
public final void setInicioSesion(iniciarScoop inicio){
inicioSesion=inicio;
}
public void setPermitBotArdVentJue(boolean permitir){
permitBotArdVentJueg=permitir;
}
public final void setLectArduReciv(LecturaFromArduino let){
/*inicializa el objeto recibido del sensado desde arudino*/
lectArdReciv=let;
}
public boolean getPermitBotArdVentJue(){
return permitBotArdVentJueg;
}
/*finaliza declaración de métodos de set y get de los atributos de esta interfaz*/
public void detenerValidBotVentJuego(boolean estado){
/*detiene o reanuda la valición de los resultados que se obtienen de los
hilos, dependiendo si el usuario se encuentra en la ventanaJuego*/
permitBotArdVentJueg=estado;
}
public final void iniciaValidBotArd(){
obtDatArd=new Thread(this);
obtDatArd.start();
}
private void jbSalirActionPerformed(java.awt.event.ActionEvent evt) {
new SalirJuego(this, true,datosJugador,inicioSesion,lectArdReciv).setVisible(true);
}
// Variables declaration - do not modify
private javax.swing.JButton jbAyuda;
private javax.swing.JButton jbIniciar;
private javax.swing.JButton jbRanking;
private javax.swing.JButton jbSalir;
private javax.swing.JLabel jlDatosJugador;
private javax.swing.JLabel jlTutorial;
private javax.swing.JPanel jpBackJuego;
// End of variables declaration
@Override
public void run() {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
/*método que ejecuta acciones en la ventana de menú del jugador, de acuerdo
a los datos que se reciben de los botones que se presionan desde el tapete*/
String [] datosArd;
while (permitBotArdVentJueg) {
datosArd = lectArdReciv.getDatRecArduino();
//System.out.println("Datos de arduino: "+datosArd[0]+" "+datosArd[1]+" "+datosArd[2]+" "+datosArd[3]);
System.out.println("Datos de arduino: "+datosArd[0]);
/*proceso de validar qué número de botón se ha presionado*/
switch(datosArd[0]){
case "1":
jbIniciar.doClick();
break;
case "2":
jbRanking.doClick();
break;
case "3":
jbAyuda.doClick();
break;
case "4":
jbSalir.doClick();
break;
default:
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(VentanaJuego.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Básicamente las funciones que están de azul, son las más importantes.
En primera se inicia un un hilo que crea un objeto de tipo zyncronized, el cual lee constantemente desde el puerto que esté conectado arduino, luego valida qué botón fue el que se pulsó, de acuerdo al número que se recibe de arduino.
Y lo que se hace es, que se ejecuta el doclic() del botón que se necesario. Y listo.
La clase de arduino es la siguiente:
package ventanasScoop;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import static java.awt.image.ImageObserver.ERROR;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;
/**
*
* @author neo Jesus Fernando Merino
*/
public class LecturaFromArduino implements SerialPortEventListener{
private OutputStream Output = null;
private BufferedReader Input = null;
private SerialPort serialPort;
private String[] inputLine;
private final String PORT_NAME = "/dev/ttyUSB0";
private static final int TIME_OUT = 110;
private static final int DATA_RATE = 9600;
int cont=0;
public LecturaFromArduino() {
this.inputLine = new String[5];
}
public String[] getDatRecArduino(){
/*retorna el arreglo que contien los datos que se reciben desde Arduino*/
return inputLine;
}
@Override
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE){
try{
inputLine[0]=Input.readLine();
//inputLine[1]=Input.readLine();
//inputLine[2]=Input.readLine();
//inputLine[3]=Input.readLine();
//System.out.println("Datos recibidos: "+inputLine[0]+" : "+inputLine[1]+" : "+inputLine[2]+" : "+inputLine[3]);
}catch (IOException e){
System.err.println("Erorr función serialEvent: "+e.getMessage());
}
}
}
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.STOPBITS_1*/
SerialPort.PARITY_NONE);
Output = serialPort.getOutputStream();
Input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (PortInUseException | UnsupportedCommOperationException | IOException | TooManyListenersException e) {
System.err.println("Error ArduinoConnection: "+e.getMessage());
}
}
private void EnviarDatos(String data) {
try {
Output.write(data.getBytes());
} catch (IOException e) {
System.exit(ERROR);
}
}
private void RecibirDatos() throws IOException {
int Output1;
Output1 = Integer.parseInt(Input.readLine());
cont= Integer.parseInt(Input.readLine());
System.out.println("Ouput1: "+Output1 +" valor recibido: "+cont);
}
}
Ojo, necesitarán la librería librxtxSerial.so, también el jar RXTXcomm.jar, y lo colocan en la carpeta lib de su proyecto, y pues claro importan los jar para que funcione.
Además en la pestaña propiedades de su proyecto deben especificar la ruta en donde se encuentra la librería librxtxSerial.so en la sección run en la descripción VM options: de preferencia muevan la librería librxtxSerial.so a la carptea lib de su proyecto, y coloquen la siguiente ruta.
-Djava.library.path="../scoopControlButtons/lib/"
Ejecutan su proyecto y deberá funcionar, en caso de que no, por favor envíenme un msj para aclarar dudas.
Buen dia, queria saber si no me podrias proporcionar el proyecto. Estoy teniendo un poco de dificultades para la realizacion de este.
ResponderBorrarPuedes pasarme el proyecto? Estoy teniendo problemas.. en la realizacion
ResponderBorrarGracias de antemano
Cuál es el problema que estás teniendo??? A lo mejor te puedo ayudar. Ya que este proyecto lo desarrollé en el 2014 y ya no lo tengo. Pero si me dices cuál es el problema, tal vez pueda orientart-
BorrarInterfaz Java y Arduino.
ResponderBorrarTutorial diseño de interfaz con Java bajo NetBeans para controlar Arduino desde el puerto serie / USB, odrás encender y apagar un Led, recibir mensajes de textos o comandos desde Arduino.
Ver tutorial.
http://www.slideshare.net/Metaconta2/interfaz-java-y-arduino
Saludos.
Gracias, estaré revisando tu link.
BorrarDe nada.
Borrar