En esta aplicación se muestra el uso de la tarjeta LilyPad de Arduino para la creación de un dispositivo estilo wearable computing, específicamente, la construcción de una gorra que permite mantener despierto a un usuario. El tutorial describe como se usa la tarjeta LilyPad y el manejo de algunos dispositivos (acelerómetro, salida serial a través del USB, led, buzzer, parlante) conectados a ella.
Un buen lugar para comenzar a explorar el uso de la tarjeta LilyPad de Arduino, es el sitio de Leah Buechley: http://web.media.mit.edu/~leah/LilyPad/index.html. Este sitio provee información útil como: forma de conectar la tarjeta al computador, instrucciones de seguridad para uso de la tarjeta en la creación de prototipos, uso de leds, speakers y sensores. Si buscas un lugar para comprar los dispositivos de LilyPad usados en este tutorial, la siguiente página puede ser de utilidad: http://www.sparkfun.com/categories/135
Antes de comenzar con este tutorial, es necesario tener el entorno de desarrollo de Arduino instalado, para ello se debe bajar el software desde: http://arduino.cc/en/Main/Software . LilyPad solo funciona en la versión 10.0 o una versión superior. Después de descargado el instalador, se debe descomprimirlo en alguna carpeta del sistema. En aquella carpeta se debe ejecutar el archivo arduino.exe que muestra el entorno de programación el cual debe lucir similar al mostrado a continuación:
Al conectar por primera vez la tarjeta LilyPad al computador, se debe esperar a que el sistema realice la instalación del dispositivo (Windows 7). El sitio de Leah Buechley, contiene instrucciones de instalación para Windows XP y Mac OS X.
Antes de empezar a programar, es necesario seleccionar la board adecuada en el entorno de desarrollo, eso se hace como se muestra en la siguiente gráfica:
Al momento de escribir este tutorial, existen dos tipos de tarjeta LilyPad, para asegurarte de seleccionar la versión adecuada puedes mirar el chip principal de tu tarjeta y de acuerdo con ello seleccionar la versión adecuada en la interfaz (ATmega328 o ATmega168).
Si se piensa construir la aplicación como prototipo usando caimanes, es buena idea construir un elemento de protección para evitar que los caimanes se resbalen, para ello puedes seguir las instrucciones de: http://web.media.mit.edu/~leah/LilyPad/coaster.html
La distribución de los puertos de la tarjeta para esta aplicación se muestra a continuación:
Las siguientes gráficas indican donde se debe conectar los conectores de los dispositivos:
Si se desea construir el demo sobre una gorra, este es el momento en el cual se deben coser los dispositivos como se indica en las imágenes anteriores, si se desea hacer un prototipo las uniones se pueden realizar mediante la utilización de caimanes para las conexiones.
Configuración de los pines: Se deben definir algunas variables que se van a utilizar para poder configurar los pines. En el método setup(), se debe inicializar los puertos de LilyPad que se van a utilizar en el proyecto. En este caso inicializamos los puertos para el led externo, el led interno, el speaker y los buzzer.
// DEFINICION DE PINES const int xPin = 2; //acelerometro en X const int yPin = 3; //acelerometro en Y const int zPin = 5; //acelerometro en Z const int ledPin = 13; //pin del led (board) const int ledPinExt = 6; //pin del led externo const int speakerPin = 9; //pin del speaker const int buzzerPin = 10; //pin del buzzer const int buzzerPin1 = 11; //pin del buzzer //Configuración de la board void setup(){ pinMode(ledPin, OUTPUT); //configurar el pin para el led como salida pinMode(ledPinExt, OUTPUT); //configurar el pin para el led como salida pinMode(speakerPin, OUTPUT); //configurar el pin para el speaker como salida pinMode(buzzerPin, OUTPUT); //configurar el pin para el buzzer como salida pinMode(buzzerPin1, OUTPUT); //configurar el pin para el buzzer como salida Serial.begin(9600); //configurar la salida del puerto serial a 9600bps }
Generación de sonidos y vibración: El LilyPad speaker funciona de la misma manera que cualquier parlante, cuando se le da un voltaje alto el speaker se ubica en una posición, y cuando se le da un voltaje bajo en una posición diferente. Para producir sonido, es necesario crear vibraciones en el aire a frecuencias determinadas. La función desarrollada permite generar sonido a través del speakerPin, a la frecuencia dada (frecuencyInHertz), durante el tiempo determinado (timeInMilliseconds).
void beep (unsigned char speakerPin, int frequencyInHertz, long timeInMilliseconds) { int x1; long delayAmount = (long)(1000000/frequencyInHertz); long loopTime = (long)((timeInMilliseconds*1000)/(delayAmount*2)); for (x1=0;x1<loopTime;x1++){ digitalWrite(speakerPin,HIGH); digitalWrite(buzzerPin,HIGH); delayMicroseconds(delayAmount); digitalWrite(speakerPin,LOW); digitalWrite(buzzerPin,LOW); delayMicroseconds(delayAmount); } }
Lectura del acelerómetro: El acelerómetro provee una medida análoga a través de sus pines que representa la fuerza a la que esta sometida el objeto. Para información más detallada sobre acelerómetros y gyros consulte http://arduino.cc/forum/index.php/topic,58048.0.html, http://bildr.org/2011/04/sensing-orientation-with-the-adxl335-arduino/.
Para reducir el ruido de las lecturas obtenidas del acelerómetro, se utiliza un filtro pasabajo mediante una media móvil de longitud 50.
//FILTRO LECTURAS const int filterSize = 50; int xFilter[filterSize]; int yFilter[filterSize]; int zFilter[filterSize]; boolean filterInitialized = false; //LECTURAS DEL ACELEROMETRO void leerAcelerometro() { int xRead = analogRead(xPin); int yRead = analogRead(yPin); int zRead = analogRead(zPin); if(filterInitialized == false) { for(int i = 0; i < filterSize; i++) { xFilter[i] = xRead; yFilter[i] = yRead; zFilter[i] = zRead; } }else{ int xtmp; int ytmp; int ztmp; for(int i = 0; i < filterSize; i++) { int tmp1; if(i==0) { //xread.... xtmp = xFilter[0]; xFilter[0] = xRead; //yread.... ytmp = yFilter[0]; yFilter[0] = yRead; //zread... ztmp = zFilter[0]; zFilter[0] = zRead; }else{ //xread... tmp1 = xFilter[i]; xFilter[i]=xtmp; xtmp = tmp1; //yread... tmp1 = yFilter[i]; yFilter[i]=ytmp; ytmp = tmp1; //zread... tmp1 = zFilter[i]; zFilter[i]=ztmp; ztmp = tmp1; } } } } int leerX() { int suma = 0; for(int i = 0; i < filterSize; i++) { suma += xFilter[i]; } return suma / filterSize; } int leerY() { int suma = 0; for(int i = 0; i < filterSize; i++) { suma += yFilter[i]; } return suma / filterSize; } int leerZ() { int suma = 0; for(int i = 0; i < filterSize; i++) { suma += zFilter[i]; } return suma / filterSize; }
El código cíclico a ejecutar en el microcontrolador: El código que se ejecuta constantemente en la aplicación permite realizar las siguientes acciones:
//Ciclo que se ejecuta constantemente void loop(){ //leer los valores analogos de los sensores leerAcelerometro(); int xRead = leerX(); int yRead = leerY(); int zRead = leerZ(); //Convertir los valores para que puedan ser calculados en el atan2 int xAng = map(xRead, minVal, maxVal, -90, 90); int yAng = map(yRead, minVal, maxVal, -90, 90); int zAng = map(zRead, minVal, maxVal, -90, 90); //Calcula la orientación a 360° x = RAD_TO_DEG * (atan2(-yAng, -zAng) + PI); y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI); z = RAD_TO_DEG * (atan2(-yAng, -xAng) + PI); //Enviar la orientación por puerto serial Serial.print("Ang;"); Serial.print(x); Serial.print(";"); Serial.print(y); Serial.print(";"); Serial.println(z); //Evaluar la orientación de la cabeza para ver si está despistado.... if( (x>340 || x < 20) && (y>340 || y < 20) ) { digitalWrite(ledPin, LOW); //apagar el pin digitalWrite(ledPinExt, LOW); //apagar el pin contSleep = 0; } else { if(contSleep > limLed) { digitalWrite(ledPin, HIGH); //encender el pin digitalWrite(ledPinExt, HIGH); //encender el pin } if(contSleep > limSleep) { // si lleva más de determinado tiempo reproducir sonido... beep(speakerPin,3520,100); //Do durante 100ms } else { contSleep ++; } } }
En el siguiente link se encuentra el vídeo demostrativo de la aplicación:
http://www.youtube.com/watch?v=j3RxAxeGoEA&feature=youtu.be
El código completo de la aplicación de Arduino y la interfaz hecha en Unity se pueden descargar aquí: proyecto.zip