Mostrando las entradas con la etiqueta arduino. Mostrar todas las entradas
Mostrando las entradas con la etiqueta arduino. Mostrar todas las entradas

lunes, 14 de julio de 2014

Instalación de processing en fedora

Instalando Arduino

Instalando Arduino en nuevas versiones de Fedora es fácil basta con ejecutar, esto es opción, en caso de que ya lo tengan instalado, pues omitanlo:
sudo yum install arduino
También hay una herramienta comiler/uploader de línea de comandos que también es bastante util:
sudo yum install ino picocom
Asegurar de agregar nuestro usuario a lo siguientes grupos:
sudo gpasswd add $USER dialout lock

Instalación de Processing

Puesto que solo hay compatibilidad para 32 bits, entonces se tienen que instalar de la siguiente manera.

32 bit

Descargar el último paquete de Processing sitio web y extraer el  archivo en alguna parte.
Si estás ejecutando 64 bits de Linux tendrá que instalar los siguientes paquetes para garantizar compatibilidad.
sudo yum install redhat-lsb-desktop.i686
Si va a usar OpenGL también necesitará el controlador de gráficos de 32 bit propietario (intel por ejemplo):
sudo yum install mesa-dri-drivers.i686

64 bits

Para el de 64 bits, es necesario descargar el paquete y descomprimirlo en alguna parte de sus sistema de ficheros, por ejemplo /opt/

Configuración para un buen funcionamiento

32 bit

Processing al igual que arduino necesita permisos para poder modificar archivos de los directorios de /run/lock/ /var/lock para asegurar ese permiso, realizar los siguiente.
sudo chown root:lock /run/lock
sudo chmod 0775 /run/lock
Para no tener que dar permisos cada vez que vayas a utilizar dichos programas, puedes hacerlo permanente con la siguiente línea de comandos.
sudo cp /usr/lib/tmpfiles.d/legacy.conf /etc/tmpfiles.d/
Ahora editar el archivo /etc/tmpfiles.d/legacy.conf y cambie la línea:
d /run/lock 0755 root root -
a esto:
d /run/lock 0775 root lock -

Por último

Realizar lo siguiente:
Mover la carpeta descomprimida del archivo que descargaron de processing, cambiarle el nombre a processing y moverla a /opt/ pueden hacerlo abriendo en la terminal un gestor de archivos en modo superusuario o desde consola:
Abriendo un gestor de archivos desde terminal en modo superusuario:

sudo nautilus
Luego de ejecutar el comando anterior, abrirá nautilus en modo superusuario, mover la carpeta manualmente a /opt, es la manera más fácil.
Mover la carpeta desde consola:
sudo su -c "mv /tmp/processing* /opt/processing"
Después ejecutar el siguiente comando:
sudo su -c "ln -s /opt/processing/processing /usr/local/bin/processing"
Y eso es todo,  a usarlo ahora:
Para ejecutar processing realizar desde consola el siguiente comando:
cd /opt/processing
./processing

viernes, 11 de julio de 2014

Punteros en programas arduino

Recientemente realicé un proyecto con arduino. Necesitaba que al tener presionado un botón desde el protoboard conectado a un pin de arduino se encendiera un led, pero que únicamente validara el primer pulso sobre el botón.
Un programa en arduino se ejecuta en loop, es decir en un ciclo infinito, para detener un proceso se usan retardos, esto con la función delay(100), el parámetro que recibe son el total de milisengundos que se retardará le programa.
El problema que tuve en primer lugar es cómo validar únicamente el primer pulso, e ignorar los demás pulsos, lo que ocurre es que arduino sensa los pines cada 100 milisegundos, al menos ese es el tiempo que yo le dí, entonces cada 100 ms realizaba la misma acción, algo que no quería.
EL segundo problema fue usar apuntadores.
La solución quedó de la siguiente manera:
Primero vea el circuito y el material que usé para esta parte:

Ahí pueden ver los materiales usados, así como la conexión de cada componente. La idea es que cuando se presione un botón se encienda el led de salida, solo tomando en cueta el primer pulso, es decir, tanto en pantalla como en el resultado solo mostrará un uno sólo una vez.
El código es el siguiente:

const int buttonPinEntrada1 = 2;
const int buttonPinEntrada2 = 3;
const int ledPinSalida1 =  8;
const int ledPinSalida2 =  9;
int buttonState1 = 0;
int buttonState2 = 0;
int bBoton1=0;
int bBoton2=0;
int *band;

void setup(){
  Serial.begin(9600);
  pinMode(ledPinSalida1, OUTPUT);
  pinMode(ledPinSalida2, OUTPUT);
  pinMode(buttonPinEntrada1, INPUT);
  pinMode(buttonPinEntrada2, INPUT);
}

void loop(){
  /*boton 1*/
  buttonState1 = digitalRead(buttonPinEntrada1);
  band=&bBoton1;
  validarUnicoPulsoBoton(ledPinSalida1,band,buttonState1);
  /*boton 2*/
  buttonState2 = digitalRead(buttonPinEntrada2);
  band=&bBoton2;
  validarUnicoPulsoBoton(ledPinSalida2,band,buttonState2);
  delay(100);
}

/*procedimiento que se usa para validar una sola pulsacion de un boton*/
void validarUnicoPulsoBoton(int ledPinSalida,int *band,int buttonState){
  /*se verifica si el estado del buton es igual a uno, es decir, si esta presionado, de tal forma que si el boton se mantiene presionado
  por mucho tiempo, pasara la siguiente condicion, esto evita que se realize la misma accion muchas veces*/
  if(buttonState == 1){
    /*se veirifica si la bandera de ese boton esta desactivada, lo que significa que no se ha realizado ninguna accion
    tras a ver pulsado dicho boton*/
    if(*band == 0){
      /*se realiza la accion, en este caso se enciende un led*/
      digitalWrite(ledPinSalida, HIGH);
      /*se actualiza la bandera para indicar que la accion ya se ha realizado al menos una vez*/
      *band=1;
      /*se imprime en pantalla el valor de la bandera, solo para asegurar en que estado se encuentra (opcional)*/
      Serial.println(*band);
    }
  }
  /*se verifica si el estado del boton es igual a cero, esto indicara que el boton ha cambiado de valor, presionado a no presionado*/
  if(buttonState == 0){
    /*se valida que la bandera sea igual a 1, indica que la accion que se realiza cuando es presionado el boton se ha realizado al menos
    una vez*/
    if(*band == 1){
      /*sin la bandera esta activada, en este caso se encendio el led, entonces es necesario apagarlo*/
      digitalWrite(ledPinSalida, LOW);
      /*se actuliza el valor de la bandera, para indicar que el  estado del boton ha sido actualizado*/
      *band=0;
      /*opcional se imprime el nuevo valor de la bandera*/
      Serial.println(*band);
    }
  }
}

Y eso es todo, buena suerte.

domingo, 22 de junio de 2014

Recibir datos desde arduino utilizando una interfaz en java

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:

  • Java
  • Arduino
  • Librerias de arduino
  • Netbeans 7.4 O superior


  • 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 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*/

    }

    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.