Proyecto con sensores capacitivos

PROGRAMACIÓN DEL DISPOSITIVO

 

Un aspecto importante a conocer es que la programación entre el arduino y el colorduino se hace a través de un protocolo llamado I2C. El estándar I2C (Inter-Integrated Circuit) fue desarrollado por Philips en 1982. Arduino dispone de soporte I2C por hardware vinculado físicamente a ciertos pines. Los pines a los que está asociado varían de un modelo a otro. Por ejemplo en el Arduino Uno los encontramos en las entradas analógicas A4 y A5; en el Arduino Mega están en los pines 20y 21. Más info en https://goo.gl/xAgrmO.

En primer lugar hay que programar el colorduino con un firmware para que posteriormente, desde el programa principal podamos mandar las instrucciones para encender o apagar leds, y configurar colores. Hay que programarlo con un arduino sin chip. En la parte superior de este artículo ya comentamos como hacer ese esquema de conexión entre un arduino sin chip y el colorduino. Una vez realizado el cableado y configurar la placa como Arduino Duemilanove – Diecimila y procesador Atmega328,  hay que instalar la librería colorduino.h

Entonces, ya podemos subir el siguiente código fuente a nuestro Colorduino para dejarlo listo para usar desde nuestro programa principal de Arduino:

#include <Wire.h>
#include<Colorduino.h>

#define DIR_I2C 0x05 //Direccion I2C esclavo

void setup() {
Colorduino.Init();
unsigned char whiteBalVal[3] = {33, 63, 63};
Colorduino.SetWhiteBal(whiteBalVal);

Wire.begin(DIR_I2C); //unirse al I2C con la direccion DIR_I2C
Wire.onReceive(receiveEvent); //funcion para recoger datos
}

void loop() {

}

void receiveEvent(int howMany) { // funcion para recibir datos por I2C

while (Wire.available()) {

byte control, rojo, verde, azul;
byte imagen[8];
int pixel;

rojo = Wire.read();
verde = Wire.read();
azul = Wire.read();

for (byte i = 0; i < 8; i++) {
imagen[i] = Wire.read();
for (byte j = 0; j < 8; j = j + 1) {
pixel = imagen[i] >> j;
pixel = pixel & 1;
Colorduino.SetPixel(j, 7 - i, pixel * rojo, pixel * verde, pixel * azul);
}
}
Colorduino.FlipPage();
}

}

A continuación tendremos que crear un programa desde Arduino para que se comunique con el colorduino y le envíe cosas para pintar. El arduino llevará toda la gestión de sensores capacitivos y del botón; también se encargará de la gestión de envío vía I2C las imágenes al colorduino. El código sería el siguiente:

#include <Wire.h> //librería para trabajar con el I2C
#include <CapacitiveSensor.h> //librería para trabajar con el colorduino

#define DIR_I2C 0x05 //DIR esclavo I2C

const int buttonPin = 13; // pin al que hemos conectado el botón 
int buttonState = 0; // variable que utilizamos para leer el estado del botón 

byte palabraRojo = 4; //sensor capacitivo de la palabra "ROJO" conectado a salida digital 4
byte palabraAzul = 6; //sensor capacitivo de la palabra "AZUL" conectado a salida digital 4
byte palabraVerde = 8; //sensor de la palabra "VERDE" conectado a salida digital 8
byte palabraBlanco = 10; //sensor capacitivo de la palabra "BLANCO" conectado a salida digital 4
byte palabraMorado = 12; //sensor capacitivo de la palabra "MORADO" conectado a salida digital 4
CapacitiveSensor sensorRojo = CapacitiveSensor(2, palabraRojo);
CapacitiveSensor sensorVerde = CapacitiveSensor(2, palabraVerde);
CapacitiveSensor sensorAzul = CapacitiveSensor(2, palabraAzul);
CapacitiveSensor sensorBlanco = CapacitiveSensor(2, palabraBlanco);
CapacitiveSensor sensorMorado = CapacitiveSensor(2, palabraMorado);

unsigned int rango = 150;
#define DIR_I2C 0x05 //DIR esclavo I2C

byte sonrisa[8] = {0, 102, 102, 0, 0, 66, 126, 60};
byte triste[8] = {0, 102, 102, 0, 0, 60, 126, 66};
byte escala[8] = {1, 3, 7, 15, 31, 63, 127, 255};
byte cuadro[8] = {255, 255, 255, 255, 255, 255, 255, 255};
byte mas[8] = {32,112,32,0,0,0,0,0};

byte* imagenes[4] = {sonrisa, triste, escala, cuadro};

byte rojo[3] = {255, 0, 0};
byte verde[3] = {0, 255, 0};
byte azul[3] = {0, 0, 255};
byte amarillo[3] = {200, 255, 0};
byte blanco[3] = {255, 255, 255};
byte negro[3] = {0, 0, 0};
byte morado[3] = {0, 255, 255};

byte* colores[7]={blanco,morado,azul,rojo,verde};

//byte* colores_polabra[7] = {rojo, verde, azul, morado, blanco, amarillo, negro};
//byte colores_numero[5] = {0,1,2,3,4};//0 rojo, 1 verde, 2 azul, 3 morado, 4 blanco -- para comparar con randomColor
byte randomColor;

void setup() {
Wire.begin(1);
Serial.begin(9600);

 

pinMode(buttonPin, INPUT);

sensorRojo.set_CS_AutocaL_Millis(0xFFFFFFFF);
sensorVerde.set_CS_AutocaL_Millis(0xFFFFFFFF);
sensorMorado.set_CS_AutocaL_Millis(0xFFFFFFFF);
sensorBlanco.set_CS_AutocaL_Millis(0xFFFFFFFF);
sensorAzul.set_CS_AutocaL_Millis(0xFFFFFFFF);

do{
buttonState = digitalRead(buttonPin);
}while (buttonState == LOW);

}

void loop() {

randomColor = random(0, 5);
visualizar_pantalla_espera(colores[randomColor]);
comprobar_valores(randomColor);

delay(1000);
}

void visualizar_pantalla_espera(byte color[]){
envia(DIR_I2C, imagenes[3], color); //en la posición 3 podemos algún dibujo para modo espera
}

 

void comprobar_valores(byte color_pasado){

byte color_pulsado;

color_pulsado = 255;
while (color_pulsado >254) {

unsigned long valorRojo = sensorRojo.capacitiveSensor(30);
unsigned long valorVerde = sensorVerde.capacitiveSensor(30);
unsigned long valorAzul = sensorAzul.capacitiveSensor(30);
unsigned long valorMorado = sensorMorado.capacitiveSensor(30);
unsigned long valorBlanco = sensorBlanco.capacitiveSensor(30);

if (valorRojo > rango) {
color_pulsado = 1;
}
if (valorVerde > rango) {
color_pulsado = 0;
}
if (valorAzul > rango) {
color_pulsado = 2;
}
if (valorBlanco > rango) {
color_pulsado = 3;
}
if (valorMorado > rango) {
color_pulsado = 4;
}
}

if (color_pulsado == color_pasado) {
// Serial.println("CORRECTO: ");
envia(DIR_I2C, imagenes[ 0], colores[color_pasado]);
delay(2000);
}

else{
envia(DIR_I2C, imagenes[1], colores[color_pasado]); // en la posición 1 de imágenes podríamos poner alguna imagen que no fuera triste, por aquello del refuerzo positivo :-)
// Serial.println("FALLO: ");
delay(2000);
}

}

//Enviar datos por I2C
void envia(byte addr, byte im[], byte col[]) {

Wire.beginTransmission(addr);
for (byte c = 0; c < 3; c++) {
Wire.write(col[c]);
}
for (byte i = 0; i < 8; i++) {
Wire.write(im[i]);
}
Wire.endTransmission(addr);
}

Vamos a aclarar algunas de las instrucciones más complicadas del código para que puedan ser entendidas:

  • CapacitiveSensor sensorRojo = CapacitiveSensor(2,4); le decimos a Arduino que vamos a montar un sensor capacitado entre los pines 2 y 4, estos pines deben estar conectados con una resistencia gorda (varios MΩ) y el cable que conecta con el papel de aluminio sale del pin segundo (4) . Podemos usar como referencia el primer pin para todos los sensores (en este caso usamos el 2) pero podríamos usar pares diferentes 2,4,6,8 etc .. aunque gastaríamos muchos pines que igual no tenemos.
  • la instrucción unsigned long valorRojo = sensorRojo.capacitiveSensor(30); es la lectura de los pines del sensor para detectar si hay corriente. El valor de 30 en la instrucción tiene que ver con el tiempo que está analizando (30 milisegundos); si ponemos 5 sensores dedicará 150 milisegundos para los sensores y podrá hacer unos 6 chequeos por segundo.
  • Wire.begin(DIR_I2C) abrir comunicación en el bus y asignarse la dirección DIR_I2C
  • Wire.onReceive(receiveEvent) es una función (receiveEvent) que se llama cuando la placa recibe una interrupción de I2C (cuando recibe datos).
  • Wire.read es leer datos del buffer del BUS (un byte)
  • Colorduino.SetPixel (x,y,R,G,B)  activa el pixel x,y de la matriz 8×8 con la combinación de colores R (de 0 a 255 rojo) G (de 0 a 255 verde) y B )de 0 a 255 azul)
  • Colorduino.FlipPage();  cambia los pixeles iluminados que hay por la nueva definición hecha en SetPixel. Es decir, definimos el color de los 64 leds y luego los activamos todos en esa instrucción.
  • Colorduino.Init(); inicializa la librería colorduino.h
  • Wire.beginTransmission(addr); empieza la transmisión sobre I2C dirigida a addr (el colorduino)
  • wire.write escribe el byte
  • Wire.endTransmission(addr) termina la comunicación.

Como podréis ver en el programa de arduino las imágenes se crean con 8 bytes que son las 8 filas y cada byte traducido a bits son los leds que se encienden en cada fila. Aunque cada led se puede encender con cualquier color (esto supondría que una “pantalla” serían 64×3 = 192 bytes), proponemos un programa sencillo para la ocasión que envía 3 bytes para el color y 8 bytes de imagen (todos los bits del mismo color). Para conseguir estás imágenes ha hecho falta bastante tiempo de I+D.

La función comprobar_valores() va a ser la encargada de comprobar si alguno de los capacitivos está siendo pulsado. En nuestro caso, con el material utilizado, sabemos que está siendo pulsado si el valor es superior a 150, valor que hemos configurado en la variable rango.

Finalmente, la función envía() es la que se va a encargar de la transmisión vía I2C hacia el colorduino para pintar los leds que queramos, con el color que queramos, según hayamos decidido en la programación anterior.

Es el programa más complejo que hemos explicado hasta ahora, por lo que si alguien necesita de algún tipo de ayuda en especial, que no dude en contactar con nosotros a través de la web.

Nos gustaría agradecer especialmente la labor de mentorización que hizo Borja Pérez (Dpto Sistemas de Universidad de Zaragoza). Sin su soporte y paciencia, el proyecto difícilmente habría salido adelante.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *