Introducción
Vamos a utilizar Serial para comunicar la placa Arduino con la computadora. En Processing tenemos que importar la librería Serial que viene incluida en el IDE.
Antes de comenzar, modificaremos la función void imprimir_Serial () en nuestro código de Arduino. Transmitimos en forma de Bytes, eliminamos la transmisión de Strings innecesarios y añadimos la impresión de '\n' al comienzo para evitar los datos erróneos que se transmiten al principio. Esto último lo explicaremos posteriormente. La función quedaría de la siguiente forma:
void imprimir_Serial (){
Serial.print ("\n");
int aux=decod[0];
Serial.print (aux, BYTE);
aux=decod[1];
Serial.print (aux, BYTE);
aux=decod[2]*0.25;
Serial.print (aux, BYTE);
aux=decod[3]*0.25;
Serial.print (aux, BYTE);
aux=decod[4]*0.25;
Serial.print (aux, BYTE);
aux=decod[5];
Serial.print (aux, BYTE);
aux=decod[6];
Serial.print (aux, BYTE);
}
Recepción de datos
Ahora ya en la programación de Processing, la parte básica de recepción de datos es la siguiente:
Serial puerto;
byte[] inBuffer=new byte[7];
void serialEvent(Serial puerto){
puerto.readBytes(inBuffer);
puerto.clear();
}
String portName = Serial.list()[1];
puerto = new Serial(this, portName, 9600);
puerto.bufferUntil('\n');
Con Serial puerto y String portName = Serial.list()[1] definimos el puerto Serial a utilizar. Serial.list() nos devuelve un vector de Strings con los puertos Serial de nuestra computadora. Estos puertos pueden variar, a mi me sirvió la posición [1], que traducido sería el puerto COM6.
Ahora tenemos que establecer la velocidad de transmisión. Esta velocidad debe coincidir con la que pusimos en el código de Arduino. Esto lo definimos mediante puerto = new Serial(this, portName, 9600), donde 9600 es la velocidad.
La última línea puerto.bufferUntil('\n') viene a decirnos que empiece a almacenar en el buffer cuando se lea el carácter '\n'. Y posteriormente se llamará a la función serialEvent().
En esta función anteriormente citada tenemos que volcar los datos del buffer en un vector. Entonces mediante puerto.readBytes(inBuffer) volcamos el contenido del buffer (un array de bytes) en un array declarado por nosotros anteriormente como byte[] inBuffer=new byte[7]. Y por último limpiamos el buffer de entrada con puerto.clear().
Normalización de datos
Por desgracia, la conversión de byte a entero no se realiza como quisieramos. Por ejemplo:
Si transmitimos desde Arduino el byte [01011111], la conversión con processing es correcta y nos lo almacenaría como 95. Ahora bien, ¿qué pasaría si el byte fuera [11010010]? Lo lógico es entender que lo almacenaría como 210, pero no es así. Por lo tanto debemos crear una función que nos resuelva este problema. Quedaría de la siguiente forma:
for (int i=0;i<7;i++)
{
if (inBuffer[i]<0)
{
datos[i]=inBuffer[i]+256;
}
else
{
datos[i]=inBuffer[i];
}
}
}
Si almacena un valor negativo, le sumamos 256. Con lo que nos quedaría el valor esperado.
Y otra aspecto que no me convencía era la forma en que nos llegaban los datos del stick. Vienen en el rango de [0, 255]. Pero es mucho más natural que la posición de equilibrio sea el 0, y a partir de ahí seguir un eje de coordenadas. Esto además facilita la representación gráfica de después. Entonces se ha creado la siguiente función:
void normalizarStick(){
if (datos[0]>132 || datos[0]<132)
{
datos[0]=datos[0]-132;
}
else
{
datos[0]=0;
}
if (datos[1]>119 || datos[1]<119)
{
datos[1]=datos[1]-119;
}
else
{
datos[1]=0;
}
}
Donde 132 y 119 es la posición de equilibrio de mi stick. Aunque esto puede cambiar según el dispositivo. Al restarle dicha posición, convertimos el equilibrio en 0 y los demás valores siguiendo un eje de coordenadas.
Apariencia
Una vez clara la parte más técnica, la apariencia depende de cada uno. Estos escritos no tienen como finalidad enseñar a programar en Processing, por lo tanto depende de cada uno como darle forma a la aplicación final.
En el siguiente post se expondrá una aplicación finalizada.