¿Qué es este blog?

La idea de este blog nace para compartir los avances que se vayan realizando a lo largo de un estudio sobre cómo interconectar los distintos sensores que se pueden encontrar en el mercado, o fabricar de forma casera, con la plataforma Mindstorms de LEGO. Para ello se hará uso ARDUINO, un entorno de desarrollo abierto basado en microcontrolador.
Mostrando entradas con la etiqueta RS232. Mostrar todas las entradas
Mostrando entradas con la etiqueta RS232. Mostrar todas las entradas

domingo, 12 de junio de 2011

Conexión del GPS Venus con conector SMA con Arduino por puerto serie


Otro de los dispositivos cuya integración se ha probado con Arduino ha sido un receptor GPS de la marca Venus, que se puede apreciar en la siguiente imagen:

Figura Receptor GPS Venus con conector SMA
Se trata de un receptor de gran sensibilidad, que permite la conexión de una antena externa mediante un conector SMA. Se puede configurar para lograr una tasa de refresco de hasta 10 Hz., y permite obtener por el puerto serie cadenas del tipo NMEA-0183, que se explicarán en otro post del blog. La tasa por defecto a la que este dispositivo devuelve datos es de 9600 baudios, pero puede configurarse con una velocidad de hasta 115200 baudios.
El corazón de este GPS es el chip Venus634FLPx, que lleva incorporado un LNC, un reloj en tiempo real y un regulador de tensión. Las características más destacadas son las siguientes:
  • 51 canales de adquisición y 14 de tracking
  • Lleva un chipset SkyTrack
  • La frecuencia máxima de actualización es de 10 Hz. aunque viene configurada por defecto a 1 H.
  • Lleva LNA integrado
  • Se debe alimentar con una tensión de entre 2,7 y 3,3 V.
  • Su consumo es de unos 28 mA una vez conectado con los satélites.
  • Su sensibilidad es de -161 dBm
  • El margen de error al posicionarse es de menos de 2,5 metros
  • Si se arranca en frío puede tardar unos 29 segundos en localizarse, mientras que si se arranca en caliente este tiempo se reduce incluso hasta un segundo.
  • Soporta antenas tanto activas como pasivas, aunque en el caso de las primeras deberán alimentarse de forma externa.
  • Su tamaño es de 3,8x1,8 cm, con lo que es fácilmente integrable.


Conexiones realizadas

Las conexiones realizadas son similares a las que se hicieron en el caso del lector RFID, con la diferencia de que en este caso el circuito va alimentado a una tensión de 3,3 V. Por lo tanto:
  • Las tierras (pines GND) de dispositivo se conectan entre sí y con cualquiera de los pines de tierra de la placa de Arduino.
  • El pin TX se conecta con el pin RX0 de Arduino, que en el caso de Arduino Mega 2560 corresponde al pin 0.
  • El pin de alimentación de 3,3 V se conecta con el pin de 3,3 V de Arduino.

Código implementado

En el código que se incluye a continuación, simplemente se configura la velocidad a 9600 baudios y se van mostrando los datos que se vayan recibiendo a través del puerto serie:

char val = 0; //Para almacenar el valor que le llega

void setup() {
    Serial.begin(9600); // Conectamos al puerto serie
}

void loop () {

    char IDstring[13]; //Para almacenar el tag
    int  i;
  
    if (Serial.available() > 0 ) {
      //Serial.println("Datos --> ");
      val = Serial.read();    // Se busca el inicio del codigo
      Serial.print(val);
      if (val=='\r'){
        Serial.println(" ");
      }
    }
}



Arduino y la comunicación serie: librería Serial


Todas las placas de Arduino disponen de al menos un puerto serie, que permite la comunicación con un ordenador o con otros dispositivos haciendo uso de esta interfaz. Los pines que se usan para la comunicación por puerto serie vienen marcados en la placa con las siglas RX y TX, que corresponden al pin por el que se enviarán los datos, y al pin por el que se recibirán los datos respectivamente.
En el caso que nos ocupa, usaremos el puerto serie no para comunicarnos con un ordenador, sino para poder comunicarnos con determinados sensores. En este epígrafe se expondrán las funciones necesarias para establecer la comunicación e intercambiar datos, y en el capítulo cuarto se verán ejemplos de sensores conectados por el puerto serie.


Conexiones
Como se ha comentado en la introducción de este epígrafe, se van a usar los pines TX y RX de la placa de Arduino. En las pruebas realizadas se ha usado la placa “Arduino Mega 2560”, la cual dispone de 8 pines destinados para ello, en lugar de los 2 de los que disponen el resto de placas. Estos pines vienen marcados en la placa y son las siguientes parejas (0,1), (14,15), (16,17), (18,19) y (20,21).
Para un correcto funcionamiento, se debe conectar el pin de recepción de la placa (RX) al pin de transmisión del dispositivo externo, y el pin de transmisión de la placa (TX) al pin de recepción de dicho dispositivo. Además, para comunicar el sistema de desarrollo con un dispositivo TTL es necesario conectar las tierras entre ellas.

Principales funciones
Las principales funciones usadas en la comunicación por puerto serie vienen incluidas en la librería Serial() y  son las siguientes:
  • Serial.begin(velocidad). Establece la velocidad en bits por segundo (baudios) para la transmisión de datos en serie.
  • El parámetro velocidad se puede configurar con el valor que se desee para comunicarse con un dispositivo externo (hasta un máximo de 115200 baudios), sin embargo si la comunicación por puerto serie va a ser con un ordenador, se deberá elegir una de las siguientes: 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 o 115200.
  • Serial.end(). Desactiva la comunicación serie, permitiendo que los pines de recepción y transmisión puedan ser usados como pines de entrada / salida digitales. Si se desee reanudar la comunicación serie, se deberá invocar nuevamente Serial.begin().
  • Serial.available(). Devuelve, ecomo entero, el número de bytes (caracteres) disponibles para ser leídos por el puerto serie. Se refiere a datos ya recibidos y disponibles en el buffer de recepción del puerto, cuya capacidad es de 128 bytes. En el caso de Arduino Mega, existen además las funciones Serial1.available(), Serial2.available() y Serial3.available().
  • Serial.read(). Lee los datos entrantes al puerto serie. Devuelve como entero el primer byte disponible recibido por el puerto serie, o -1 si no hay datos disponibles. Al igual que en el caso anterior, para la placa Arduino Mega existen también las funciones Serial1.read(), Serial2.read() y Serial3.read().
  • Serial.flush(). Vacía el buffer de la entrada de datos serie. Esto quiere decir que si se llama a la función Serial.read() o Serial.available(), estas sólo devolverán los datos recibidos después de que se haya realizado esta llamada. No requiere parámetros ni devuelve nada. Para la placa Arduino Mega existen disponibles las llamadas Serial1.flush(), Serial2.flush() y Serial3.flush() además de la principal.
  • Serial.print(valor, formato). Esta función imprime los datos al puerto serie como texto ASCII. El primer parámetro, valor, es el propio valor que se desea imprimir. Esto se podrá realizar de distintas formas:
    • Los números son impresos mediante un juego de caracteres ASCII para cada dígito.
    • Los valores de tipo flotante (float) se imprimen en forma de dígitos ASCII con 2 decimales por defecto, es decir, si ejecutamos Serial.print(1.23456) se imprimirá “1.23”.
    • Los valores de tipo “byte” se enviarán como un único carácter.
    • Los caracteres y las cadenas se enviarán tal cual.
  • Además, existe el segundo parámetro es opcional y permite especificar el formato que se desea usar. Así, este parámetro puede tomar el valor BYTE, BIN (valores binarios, en base 2), DEC (valores decimales, en base 10), HEX (valores hexadecimales, en base 16). Si lo que se está imprimiendo son números con coma flotante, este parámetro especificará el número de decimales a usar.
  • Serial.println(valor, formato). Imprime los datos al puerto serie como texto ASCII seguido de un retorno de carro(ASCII 13 o ‘\r’) y un carácter de avance de línea (ASCII 10 o ‘\n’). Por lo demás, este comando tiene la misma forma y los mismos parámetros que Serial.print() descrito anteriormente.
  •  Serial.write(). Esta función escribe datos binarios en el puerto serie. Estos se enviarán como un byte o como una serie de bytes. Si lo que se desea es envíar los caracteres que representan los números, es mejor usar la función Serial.print() en su lugar. Puede tomar distintos parámetros:
    • Serial.write(valor) enviará un solo byte.
    • Serial.write(str) enviará una cadena como una serie de bytes.
    • Serial.write(buf, len) enviará un array como una serie de bytes. El tamaño del array se indicará en el segundo parámetro.

--------------------------------------------------------------------------
ReferenciasArduino Serial library. http://arduino.cc/es/Reference/Serial



Lector RFID ID-20 y su conexión con Arduino y el NXT


El segundo sensor con el que se han realizado pruebas ha sido el lector de tarjetas RFID ID-20 de la empresa ID Innovations. Se trata de un pequeño módulo con antena incorporada, que detecta cuando se le acerca un tag RFID y devuelve a través del puerto serie su código de identificación. Las principales características de este dispositivo, que podemos ver en la figura de abajo, se listan a continuación:
-       Alimentación de 5 V
-       Frecuencia de lectura: 125 KHz
-       Permite conexiones en serie a 9600 baudios y con puertos de tipo RS-232
-       Es capaz de leer los tags RFID a una distancia de 200 mm aproximadamente
-       El tamaño del dispositivo es de 38x70x7 mm.

Figura  Lector RFID ID-20
Para facilitar la integración de este lector con Arduino, y para poder hacer pruebas pinchándolo directamente sobre una placa de prototipos, se ha usado también una base con conector USB como la que se ve en la figura siguiente:

Figura Lector RFID USB
Como se aprecia en la figura anterior, esta placa tiene un zócalo que permite insertar el lector ID-20. Además de permitir la transferencia de datos mediante el puerto USB, esta placa sigue permitiendo la transmisión de datos vía serie con la misma configuración antes mencionada. Además, la placa consta de un pequeño zumbador para avisar de que ha leído un tag RFID, así como de un led que se encenderá cuando ésta se encuentre alimentada.

Conexiones entre el dispositivo y Arduino

Las conexiones que se han realizado han sido las siguientes: 

  •      El dispositivo necesita para funcionar una tensión de alimentación de 5 V, por lo que en el caso de querer alimentarlo exclusivamente con la placa de Arduino, se deberá conectar el pin de 5 V del mismo con  el pin VCC de la placa RFID USB.
  •        Los pines de tierra de la placa USB se conectarán a cualquiera de las tierras que ofrece Arduino.
  •        El pin TX de la placa USB es aquel por el que se enviarán los datos que posteriormente Arduino recibirá y procesará. Dicho pin deberá conectarse con el pin RX0 de Arduino, que en el caso de Arduino Mega 2560 es el pin 0.
  •        El resto de pines no es necesario conectarlos, aunque si se quisiera un mayor alcance de recepción de datos podría incorporarse una antena al pin AN1 o al AN2 de la placa.

Código cargado en Arduino

La función que realiza el código que se muestra a continuación es, tras configurar la conexión por puerto serie a una velocidad de 9600 baudios, esperar a que el dispositivo le devuelva un identificador RFID válido. Esto ocurre cuando se acerca un tag válido al lector.
Para identificar que el valor recibido es correcto, se ha tenido en cuenta que los tags se reciben como una cadena de caracteres que siempre empieza con el valor “02” y termina con el valor “03”. Todo lo que se reciba entre estos dos valores forma parte del identificador.

Además, este código recibido se almacena en el array denominado “buffersalida” que será enviado al NXT. El procedimiento para prepararlo y enviarlo es similar al que ya se vio en el caso del IMU presentado en el apartado 5.1, sólo que en esta ocasión los datos se transmiten como bytes.
El código implementado es el siguiente:



#include <Wire.h> //Para gestionar las comunicaciones

//Definiciones y variables globales
uint8_t SensorVersion[9] = " V0.1   ";
uint8_t SensorName[9] =    "RFIDReadr";
uint8_t SensorType[9] =    "RFID    ";
byte buffersalida[] = { 0, 0, 0, 0, 0, 0}; //Para enviar al RCX
byte buffrfid[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Para el tag
//uint8_t buffrfid[13];

int val = 0;                    //Datos que se leeran del acelerometro o giroscopo
unsigned long timer=0;          //timer
unsigned long  delta_t;         //delta o tiempo entre muestras

byte rec;

void setup(){
 
  Serial.begin(9600);
  Wire.begin(1); //Nos unimos como esclavos con dir. 1
  Wire.onRequest(requestEvent); //Rutinas para cuando llegue algo
  Wire.onReceive(receiveEvent);
}


void loop(){
  char IDstring[13]; //Para almacenar el tag
    int  i;
  
    if (Serial.available() > 0 ) {
      Serial.println("Tarjeta detectada");
      if ( (val = Serial.read()) == 02 ) {    // Se busca el inicio del codigo
        Serial.print("[SOT] ");
                                              // Se lee hasta llegar al final
        for ( i = 0; (val = Serial.read()) != 03 ; i++) {
          Serial.print(val, HEX);
          Serial.print(" ");
          IDstring[i] = val;
          buffrfid[i] = val;
        }
        Serial.println("[EOT]");
        Serial.println();
        Serial.print("  IDString[");
        IDstring[10] = 0x00;  
        Serial.print(IDstring);
        Serial.println("] ");
        Serial.println();
}
    }
 } 
void receiveEvent(int len){ //Devuelve el nº de bytes recibidos
  while (0 < Wire.available() ) {
    rec = Wire.receive();
  } //While
}
void requestEvent(){

  Serial.print(rec, BYTE);
  if (rec == 0x00){ //Version del sensor
    Wire.send(SensorVersion, 8);
  } else if (rec == 0x08){ //Nombre del sensor
    Wire.send(SensorName, 8);
  } else if (rec == 0x10){ //Tipo del sensor
    Wire.send(SensorType, 8);
  } else if (rec == 0x05) { // Lectura del tag
      Wire.send(buffrfid, 14);
  } else {
    buffersalida[0] = 0;
    buffersalida[1] = 0;
    Wire.send(buffersalida, 2);
  }
}



Código cargado en el NXT




A continuación se muestra el código que se ha cargado en el NXT. Este código, similar al usado para recibir los datos del IMU que se conectaba a Arduino. Al igual que entonces, en primer lugar se procede a obtener los datos del sensor (versión, tipo e identificador), y a continuación se obtienen los tags que se vayan leyendo desde el lector. Para que la información de la lectura de los tags se muestre en hexadecimal, se hace la conversión de los bytes que vayan llegando usando las función toHexString propia de los tipos enteros. El código completo es el siguiente:

import lejos.nxt.*;

public class ArduCom {

            public static void main(String[] args) throws Exception{
                       byte [] dato = new byte[15];
                       String Tipo = "";
                       String ID ="";
                       String Ver="";
                       String cad="";
                       int err = 0;
                      
                       for (int i=0;i<dato.length;i++){
                                   dato[i] = 0;
                       }
                      
                       I2CSensor Arduino = new I2CSensor(SensorPort.S1);
                       Arduino.setAddress(1);
                       Ver = Arduino.getVersion();
                       System.out.println("Ver: "+Ver);
                       Tipo = Arduino.getSensorType();
                       System.out.println("Tipo: "+Tipo);
                       ID = Arduino.getProductID();
                       System.out.println("ID: "+ID);
                       Thread.sleep(1000);
                       while (!Button.ESCAPE.isPressed()) {
                                   err = Arduino.getData(5, dato, 15);

                                               System.out.print("Tag: ");
                                               for(int i=0; i<14;i++) {
                                                          int num = (int)dato[i];
                                                          cad = Integer.toHexString(num);
                                                          System.out.print(cad+" ");
                                               }
                                               Thread.sleep(1000);
                                               System.out.println();
                       } //Fin del while
            }         
}