¿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 Wire(). Mostrar todas las entradas
Mostrando entradas con la etiqueta Wire(). Mostrar todas las entradas

domingo, 12 de junio de 2011

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.

--------------------------------------------------------------------------
Referencias: Arduino Serial library. http://arduino.cc/es/Reference/Serial



martes, 8 de marzo de 2011

Arduno y la comunicación I2C: Librería Wire()


En publicaciones anteriores del blog se comentaron las distintas herramientas de las que disponía el NXT para establecer la comunicación mediante I2C con dispositivos esclavos, e hicimos especial hincapié en el Sistema Operativo LejOs, que es con el que más estamos trabajando.

En el otro lado de la comunicación, y funcionando como esclavo, se va a encontrar nuestra placa de Arduino. En este epígrafe se va a describir el funcionamiento de la librería Wire(), que es aquella que nos va a permitir realizar esta comunicación, y se van a describir brevemente las funciones más interesantes de las que ésta dispone.

Principales funciones

Como se acaba de comentar, esta librería permite la comunicación de una placa Arduino con dispositivos I2C y TWI. En la mayoría de las placas Arduino, la línea de datos (SDA) se encuentra en el pin analógico 4, y la línea de reloj (SCL) se encuentra en el pin analógico 5. En el caso de la placa que nosotros usamos, Arduino Mega 2560, estas líneas están en los pines digitales 20 y 21 respectivamente.

Las principales funciones que nos ofrece esta librería son las siguientes:

- Wire.begin() y Wire.begin(dirección). Esta función inicializa la librería Wire y conecta Arduino al bus. Si no se especifica la dirección, Arduino se conectará al bus como maestro, mientras que si ésta se indica lo hará como esclavo y asumiendo la dirección que se la ha proporcionado. En ambos casos, esta función no devuelve ningún valor.

- Wire.requestFrom(dirección, cantidad). Solicita bytes desde otros dispositivos. Los bytes pueden ser recibidos con las funciones available() (que nos indica si hay datos disponibles para ser leídos en el bus) y receive() (que realiza la lectura de los datos). Esta función no devuelve nada.

  • El parámetro “dirección” es la dirección de 7 bits del dispositivo al que le queremos pedir los datos
  • El parámetro “cantidad” es el número de bytes a pedir.
- Wire.beginTransmission(dirección). Comienza una transmisión a un dispositivo I2C esclavo con la dirección que se especifique en el parámetro “dirección”. Posteriormente, prepara los bytes a transmitir con la función send() y los transmite llamando a la función endTransmision(). Esta función no devuelve nada.

  • El parámetro “dirección” es la dirección de 7 bits del dispositivo al que le queremos pedir los datos.
- Wire.endTransmission(). Finaliza una transmisión a un esclavo que fue empezada por beginTransmission(), y realmente lo que hace es transmitir los bytes que fueron preparados por send(). Esta función tampoco devuelve nada.

- Wire.Send(valor), Wire.Send(string) o Wire.Send(dato, cantidad). Envía datos desde un esclavo como respuesta a una petición de un maestro, o prepara los bytes para transmitir desde un maestro a un esclavo (entre llamadas a beginTransmission() y endTransmission()).

  • El parámetro “valor” es un byte que se desee enviar.
  • El parámetro “string” es una cadena de tipo (char *) que se desee enviar.
  • El parámetro “dato” es un vector de datos para enviar (byte *).
  • El parámetro “cantidad” es el número de bytes que se desea transmitir

- Wire.available(). Devuelve el número de bytes disponibles para recuperar con receive(). Debería ser llamada por un maestro después de llamar a requestFrom() o por un esclavo dentro de la función a ejecutar por onReceive(), que será lo que nosotros hagamos al recibir datos del NXT. Esta función devuelve el número de bytes disponibles para leer.

- Wire.receive(). Recupera un byte que fue transmitido desde un dispositivo esclavo a un maestro después de una llamada a requestFrom() o que fue transmitido desde un maestro a un esclavo. Devuelve el byte recibido.

- Wire.onReceive(handler). Registra una función que será llamada cuando un dispositivo esclavo reciba una transmisión desde un maestro. Esta función no devuelve nada.

  • El parámetro “handler” corresponde a la función que será llamada cuando el esclavo recibe datos. Esta función debería coger un único parámetro entero (el número de bytes recibidos desde un maestro) y no devolver nada, por ejemplo: void myManejador(int numBytes).
- Wire.onRequest(handler). Registra una función que será llamada por el dispositivo esclavo cuando un maestro solicite datos. No devuelve nada.

  • El parámetro “handler” es la función que tiene que ser llamada.
A modo de ejemplo se muestra a continuación el código de un maestro y de un esclavo que hacen uso de esta librería. El esclavo envía datos, y el maestro los recibe y los imprime por puerto serie, con lo que se pueden monitorizar desde el PC.


En primer lugar el código del maestro:





Y a continuación el del esclavo:





--------------------------------------------------------------------
REFERENCIAS:
- Ejemplo de comunicación I2C entre dos Arduinos: http://arduino.cc/en/Tutorial/MasterReader
- Arduino Wire: http://arduino.cc/es/Reference/Wire
- I2C bus. TWI bus: http://www.i2c-bus.org/twi-bus/