lunes, 7 de enero de 2008

Proyecto Arduino: Cambia el color mediante un sonido

Este es el primer proyecto que desarrollamos con la plataforma "Arduino".

Consiste en una bola (como de ping-pong) que se ilumina con tonalidades aleatorias de color al percibir un sonido (una palmada, por ejemplo). El color emergente permanece al menos durante un segundo; luego, cualquier otro sonido o chasquido puede cambiar su color de nuevo. En caso de permanecer en silencio, el último color se mantiene unos segundos para, seguidamente, comenzar a apagarse progresivamente. El ingenio funciona con una pila y no posee interruptor, sino un sensor de inclinación para el encendido y apagado.

¿Qué necesitamos para desarrollar el proyecto? Tan solo unos pocos componentes electrónicos de muy bajo coste y un microcontrolador Atmega 168, el mismo que usa la placa Arduino Diecimila que sirve de programador.

Hemos basado el proyecto en la más sencilla plataforma para experimentar con microcontroladores: Arduino. Me decido a unirme al importante movimiento internacional que impulsa Open Source como actitud. Arduino posee una placa "open hardware" de muy bajo coste para dar soporte a los desarrollos; y también una aplicación "open software" que, en una sola ventana puedes editar el programa, compilarlo y cargarlo en la placa a través de conexión USB. El lenguaje Arduino, basado en Wiring (otra famosa placa freeware), tiene sus raíces en Processing: un lenguaje de programación extraordinariamente simple enfocado a ser usado por artistas y creativos. Arduino ( y Processing) usan la estructura de C (o Java) para, con muy pocas funciones incorporadas, realizar lecturas del voltaje de las patillas del microcontrolador (6 entradas analógicas), poner en alto o bajo el voltaje de otras patillas (14 entradas/salidas digitales), realizar pausas de tiempo leer y escribir caracteres por la conexión serie con el ordenador.

Vamos a ver por categorías los componentes discretos que usaremos en nuestro desarrollo.

En primer lugar usaremos, como soporte de experimentación, una "protoboard" o placa de prototipos que nos evite las soldaduras con estaño. La fuente de alimentación puede consistir en una simple pila de 9 voltios. Los componentes serán interconectados con hilo esmaltado o con delgados cables eléctricos que podemos comprar ya preparados.

La placa Arduino, en su versión "Diecimila", será usada para transferir el programa (muy pocas líneas de código C) hasta el microcontrolador aprovechando su conexión USB.

En la imagen siguiente podemos distinguir los siguientes componentes: Un led RGB que puede lucir en rojo, verde y azul independientemente y que equivale a tres leds de los citados colores. Mediante patillas de salidas analógicas (Arduino simplifica así la técnica de modulación de anchura de pulso) podemos controlar la mezcla de tonos rojos, verdes y azules que sintetizará el resto de la gama de colores. El ingenio dispondrá de un interruptor interno (sensor de inclinación) para la puesta en marcha y apagado, simplemente depositando el aparato en una u otra posición. Una cápsula microfónica de tipo "electret" captará el sonido ambiente, ante cuyas fluctuaciones reaccionará el ingenio cambiando la coloración del led. Un cristal de cuarzo oscilando a 16 megahercios impondrá el ritmo al microcontrolador. Este deberá estar alimentado con una tensión de 5 voltios, que serán obtenidos del regulador LM7805 interpuesto con la pila de 9 voltios.

A parte de éstos, tan solo necesitamos cinco componentes pasivos:
Resistencias: dos de 10 K y una de 330 ohmios.
Condensadores: dos de 0,1 microfaradios (100 KpF) para el regulador de voltaje. Y otros dos de 22 picofaradios para el cristal de cuarzo oscilado
r. Añadiremos, por precaución, un diodo al ánodo de la pila para prevenir que ésta pudiera ser puesta con la polaridad invertida.

Consideramos el detalle de cubrir el led con un poco de papel blanco translúcido (como papel de cocina) para ayudar la difusión y mezcla de colores del led; todo ello será introducido en una esfera hueca rígida (como una pelota de ping-pong) a la cual hemos practicado un orificio.

Por fin llega el momento de ensamblarlo todo junto sobre la placa de prototipos.

Y añadiendo el difusor de papel con la pelotita de ping-pong.


Claro que, para que el microcomputador haga su trabajo, deberemos cargar el programita en su memoria de tipo flash. La carga del programa podría hacerse colocando el chip microcontrolador en su zócalo sobre la placa arduino. Estos micros también aceptan programación "in-circuit", pero mediante un programador más caro (aunque mucho más versatil). Hemos, sin embargo, optado por una tercera vía: usar las patitas de transmisión serie (TX y RX) del microcontrolador conectadas a las correspondientes de la placa arduino, además de la alimentación (+5V y GND) también del arduino, y añadiendo una quinta conexión: la señal de RESET. Con estos cinco hilos convertimos la placa arduino en una "nodriza" que comunica nuestro ordenador con el microcontrolador para programarlo pero, a su vez, permite que el micro permanezca en su tarjeta de prototipos rodeado de su periferia (micro y led), en su propio circuito.


Una vez comprobado que el prototipo funciona según nuestras espectativas, procederemos a soldarlo (aunque así quedaba ya muy majo) para reducir su volumen y aumentar su compacidad. De esta manera podemos regalar el invento a algún sobrinillo y disfrutar observando cuán admirado interactúa con ello (o contra ello). Para ahorrar material y espacio decidimos soldar las conexiones directamente sobre el zócalo donde se insertará posteriormente el micro. Obtenemos así esta belleza de esqueletismo electrónico.

Lo contemplamos una vez más, para reconocer que ha resultado tan sencillo como reinventar, digamos, la pólvora.

Como toque final, había pensado en incrustarlo en una bonita caja. Podría ser del tamaño de una caja de cerillas, pero ello obligaría a usar pilas de tipo botón, que duran muy poco. Así pues, lo vamos a introducir en una caja de plástico. Y todo quedará compactado mediante un poco de cola termofusible.

Et voilà:


Por si acaso el lector quiera desarrolar un artilugio inspirado en éste, voy a exponer los esquemas eléctricos que he realizado con la herramienta gratuita "Eagle", así como el código fuente del programa. Luego indicaré enlaces de interés; y también me atreveré a proporcionar algunos consejos para conseguir fácilmente el material.

Algunos esquemas son los s
iguientes:




En cuanto al código del programa, mínimamente comentado, aquí lo expongo:

/*
VozCambiaColor
07/01/2008
Carlos Grasa Lambea
*/

int lapso=50; // tiempo corto de espera en cada ciclo en ms
int permanencia=200; // ciclos que permanece encendido
int sensibilidad=1; // variación tolerada en entrada analógica
int lapsoInactivo=1000; // tiempo de espera en ms tras detección

int pinEntrada=5; // patilla de entrada analógica

int pinSalidaRojo=9; // patilla hacia led rojo
int pinSalidaVerde=11; // patilla hacia led verde
int pinSalidaAzul=10; // patilla hacia led azul

int entrada; // último valor de entrada analógica
int entradaAnterior; // penúltimo valor de entrada analógica
int rojo; // intensidad de rojo
int verde; // intensidad de verde
int azul; // intensidad de azul
int color=-1; // último valor aleatorio para el color
int colorAnterior=-1; // penúltimo valor aleatorio para el color
int permaneciendo=0; // ciclos que aún debe permanecer color actual
int difRojo; // decremento de valor rojo
int difVerde; // decremento de valor verde
int difAzul; // decremento de valor azul
boolean apagando=false; // estado de apagado progresivo

void setup() { // configuración preparatoria
pinMode(pinEntrada,INPUT); // entrada analógica
pinMode(pinSalidaRojo,OUTPUT); // salida modulada para rojo
pinMode(pinSalidaVerde,OUTPUT); // salida modulada para verde
pinMode(pinSalidaAzul,OUTPUT); // salisa modulada para azul

entradaAnterior=analogRead(pinEntrada); // almacena entrada analógica
return;
}

void loop() { // ciclo de funcionamiento repetido
entrada=analogRead(pinEntrada); // lee valor actual de entrada analógica
if (abs(entrada-entradaAnterior)>sensibilidad) { // si la variación de entrada analógica supera el umbral de sensibilidad
cambiaColor(); // busca otra tonalidad de color
pinta(); // modula salidas con nuevo color
delay(lapsoInactivo); // desactiva lectura analógica por un tiempo
permaneciendo=permanencia; // establece cuenta atrás del estado de permanencia
apagando=false; // fuera del estado de apagado progresivo
}
if (permaneciendo>0) { // si quedan ciclos por mantener el color
permaneciendo--; // sigue la cuenta atrás
if (permaneciendo==0) // si fin de la cuenta atrás
apagando=true; // dentro del estado de apagado progresivo
}
if (apagando) { // si en estado de apagado progresivo
rojo-=difRojo; // disminuye intensidad de rojo
if (rojo<0)
rojo=0; // anula valor de rojo
verde-=difVerde; // disminuye intensidad de verde
if (verde<0)>verde=0; // anula valor de verde
azul-=difAzul; // disminuye intensidad de azul
if (azul<0)>azul=0; // anula valor de azul
}
entradaAnterior=analogRead(pinEntrada); // recuerda valor de entrada analógica
pinta(); // modula salidas con el color actual
delay(lapso); // espera en el ciclo por un tiempo
return;
}

void cambiaColor() { // seleccionar un color aleatoriamente distinto del actual
randomSeed(millis()); // inicializa el generador de azar según el tiempo de funcionamiento
while (color==colorAnterior) // mientras el nuevo color sea el mismo que el actual
color=random(13); // selecciona al azar uno de entre 13 valores
colorAnterior=color; // recuerda el color anterior
switch (color) { // establece proporciones de rojo, verde y azul según color
case 0:
rojo=2;
verde=0;
azul=0;
break;
case 1: // caso explicado como ejemplo
rojo=2; // intensidad alta de rojo
verde=1; // intensidad media de verde
azul=0; // intensidad nula de azul
break;
case 2:
rojo=2;
verde=2;
azul=0;
break;
case 3:
rojo=2;
verde=0;
azul=1;
break;
case 4:
rojo=2;
verde=0;
azul=2;
break;
case 5:
rojo=0;
verde=2;
azul=0;
break;
case 6:
rojo=1;
verde=2;
azul=0;
break;
case 7:
rojo=0;
verde=2;
azul=1;
break;
case 8:
rojo=0;
verde=2;
azul=2;
break;
case 9:
rojo=0;
verde=0;
azul=2;
break;
case 10:
rojo=1;
verde=0;
azul=2;
break;
case 11:
rojo=0;
verde=1;
azul=2;
break;
case 12:
rojo=2;
verde=2;
azul=2;
break;
}
difRojo=rojo; // establece decremento de rojo en apagado progresivo
difVerde=verde; // establece decremento de verde en apagado progresivo
difAzul=azul; // establece decremento de azul en apagado progresivo
switch (difRojo) { // calcula modulación de rojo
case 0:
rojo=0; // intensidad nula
break;
case 1:
rojo=128; // intensidad media
break;
case 3:
rojo=255; // intensidad máxima
break;
}
switch (difVerde) { // calcula modulación de verde
case 0:
verde=0; // intensidad nula
break;
case 1:
verde=128; // intensidad media
break;
case 3:
verde=255; // intensidad máxima
break;
}
switch (difAzul) { // calcula modulación de azul
case 0:
azul=0; // intensidad nula
break;
case 1:
azulo=128; // intensidad media
break;
case 3:
azul=255; // intensidad máxima
break;
}
return;
}

void pinta() { // modular salidas hacia los leds con las intensidades actuales
analogWrite(pinSalidaRojo,rojo); // modula intensidad de rojo
analogWrite(pinSalidaVerde,verde); // modula intensidad de verde
analogWrite(pinSalidaAzul,azul); // modula intensidad de azul
return;
}


¿Dónde encontrar información? Básicamente en la página de Arduino:

www.arduino.cc/es

o también:

www.arduino.cc

Los componentes electrónicos pueden adquirirse en cualquier comercio de componentes electrónicos. Yo me he surtido en "Electrónica Goya", en Zaragoza. También en AESA, en la calle Menéndez Pelayo, 34.

La placa "Arduino Diecimila" puedes encontrarla, junto a otros productos curiosos, en Libelium, junto a la Facultad de Ingenieros de Zaragoza:


www.libelium.com

Pero si quieres hacer varios proyectos y necesitas varios microcontroladores Atmega 168-20PU con "bootloader" o programa cargador de arduino incluido, entonces Libelium no los suministra sueltos actualmente. Yo los he encontrado muy baratos a través de internet en NKC Electronics:

www.NKCelectronics.com
Muy fácil, rápido y recomendable.


Recibiré con gusto cualquier comentario y aportación sobre el tema Arduino.

Gracias.