Apéndice 4. Comunicar Arduino con otros sistemas

De CNB
Ir a la navegación Ir a la búsqueda
Busca en cnbGuatemala con Google

The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


Hoy en día la manera más común de comunicación entre dispositivos electrónicos es la comunicación serial y Arduino no es la excepción. A través de este tipo de comunicación podremos enviar datos a y desde nuestro Arduino a otros microcontroladores o a un computador corriendo alguna plataforma de medios (Processing, PD, Flash, Director, VVVV, etc.). En otras palabras conectar el comportamiento del sonido o el video a sensores o actuadores. Explicaré aquí brevemente los elementos básicos de esta técnica:

Funciones básicas

El mismo cable con el que programamos el Arduino desde un computador es un cable de comunicación serial. Para que su función se extienda a la comunicación durante el tiempo de ejecución, lo primero es abrir ese puerto serial en el programa que descargamos a Arduino. Para ello utilizamos la función

beginSerial(19200);

Ya que solo necesitamos correr esta orden una vez, normalmente iría en el bloque void setup(). El número que va entre paréntesis es la velocidad de transmisión y en comunicación serial este valor es muy importante ya que todos los dispositivos que van a comunicarse deben tener la misma velocidad para poder entenderse. 19200 es un valor estándar y es el que tienen por defecto Arduino al iniciar.

Una vez abierto el puerto lo más seguro es que luego queramos enviar al computador los datos que vamos a estar leyendo de uno o varios sensores. La función que envía un dato es

Serial.print(data);

Una mirada en la referencia de Arduino permitirá constatar que las funciones print y println (lo mismo que la anterior pero con salto de renglón) tienen opcionalmente un modificador que puede ser de varios tipos:

Serial.print(data, DEC); // decimal en ASCII

Serial.print(data, HEX); // hexadecimal en ASCII

Serial.print(data, OCT); // octal en ASCII

Serial.print(data, BIN); // binario en ASCII

Serial.print(data, BYTE); // un Byte

Como puede verse, prácticamente todos los modificadores, menos uno, envían mensajes en ASCII. Explicaré brevemente:

Series de pulsos

En el modo más sencillo y común de comunicación serial (asincrónica, 8 bits, más un bit de parada) siempre se está enviando un byte, es decir un tren de 8 pulsos de voltaje legible por la máquina como una serie de 8, 1s ó 0s: 

Serie de pulsos - diagrama

O sea que no importa cual modificador usemos siempre se están enviando bytes. La diferencia esta en lo que esos bytes van a representar y sólo hay dos opciones en el caso del Arduino: una serie de caracteres ASCII o un número.

Si Arduino lee en un sensor analógico un valor de 65, equivalente a la serie binaria 01000001 esta será enviada, según el modificador, como: 

Dato Modificador Envío (pulsos)
65 ---DEC---- (“6′′ y “5′′ ACIIs 54–55) 000110110–000110111
65 ---HEX---- (“4′′ Y “1′′ ACIIs 52–49) 000110100–000110001
65 ---OCT---- (“1′′, “0′′ y “1′′ ACIIs 49–48–49) 000110001– 000110000–000110001
65 ---BIN---- (“0′′,”1′′,”0′′,”0′′,”0′′,”0′′,”0′′y”1′′ ACIIs 49–48– 49–49–49–49–49–48) 000110000-...
65 ---BYTE--- 01000001 

No explicaremos conversiones entre los diferentes sistemas de representación numérica, ni la tabla ASCII (google), pero es evidente como el modificador BYTE permite el envío de información más económica (menos pulsos para la misma cantidad de información) lo que implica mayor velocidad en la comunicación. Y ya que esto es importante cuando se piensa en interacción en tiempo real es el modo que usaremos acá.

Un ejemplo sencillo

Enviar un sólo dato es realmente fácil. En el típico caso de un potenciómetro conectado al pin 24 del ATmega:

int potPin = 2;

int ledPin = 13;

int val = 0;

void setup()

{

Serial.begin(9600);

pinMode(ledPin, OUTPUT);

digitalWrite(ledPin, HIGH); //activamos el pin para saber cuando arranco

}

void loop()

val = analogRead(potPin); // lee el valor del Pot

Serial.println(val);

}

Si no utilizamos ningún modificador para el Serial.println es lo mismo que si utilizáramos el modificador DEC. Así que no estamos utilizando el modo más eficiente pero si el más fácil de leer en el mismo Arduino. Al correr este programa podremos inmediatamente abrir el monitor serial del software Arduino (último botón a la derecha) y aparecerá el dato leído en el potenciómetro tal como si usáramos el println en Processing.

Envío a Processing (versión ultra simple)

Para enviar este mismo dato a Processing si nos interesa utilizar el modo BYTE así que el programa en Arduino quedaría así:

int potPin = 2;

int ledPin = 13;

int val = 0;

void setup()

{

Serial.begin(9600);

pinMode(ledPin, OUTPUT);

digitalWrite(ledPin, HIGH); // activamos el pin para saber cuando arranco

}

void loop(){

; // lee el Pot y lo divide entre 4 para quedar entre 0-255

val = analogRead(potPin)/4

Serial.print(val, BYTE);

}

En Processing tenemos que crear un código que lea este dato y haga algo con él:

import processing.serial.*;

Serial puerto; // Variable para el puerto serial

byte pot;// valor entrante

int PosX;

void setup()

{

size(400, 256);

println(Serial.list()); // lista los puertos seriales disponibles

//abre el primero de esa lista con velocidad 9600 

port = new Serial(this, Serial.list()[0], 9600);

fill(255,255,0);

PosX = 0;

pot = 0;

}

void draw()

{

if (puerto.available() > 0) { // si hay algún dato disponible en el puerto

pot = puerto.read();// lo obtiene

println(pot);

}

ellipse(PosX, pot, 3, 3); // y lo usa

if (PosX < width)

{

PosX++;

}

else

{

fill(int(random(255)),int(random(255)),int(random(255)));

PosX = 0;

}

}

Si ya se animó a intentar usar más de un sensor notará que no es tan fácil como duplicar algunas líneas.