Pensando ideas para poder domotizar la habitación de mi casa, he pensado en hacer un prototipo para controlar las luces (quien dice luces dice cualquier cosa) mediante un mando a distancia que emplea el protocolo NEC, creo que uno de los más extendidos, por lo menos todos los mandos que he encontrado por casa tienen este protocolo. Para ello dispongo en mi taller de un sensor infrarrojo TSOP1838 que me compré por ebay, y los siguientes mandos para probar el circuito, aparte de probar mi nueva prototype shield para el arduino:
Estos mandos los he probado y funcionan los 3 perfecto, el único fallo es con el más pequeño de todos que algunas teclas no me las reconoce pero el resto funcionan perfectamente, el 1º de ellos es de mi tarjeta de televisión Avermedeia TV203, el 2º es el del TDT que tengo en la tele de la habitación y el último (con el que he realizado el programa) es de un disco duro, que se me estropeo, Iomega Screenplay HD Multimedia.
Os cuento un poco de que trata el protocolo NEC de los mandos a distancia:
- Longitud de 8 bits de dirección y 8 bits de comando.
- Tanto la dirección como el comando son envíados dos veces a modo de CRC.
- La primera vez envía los bits originales y la segunda los mismos pero negados.
- Los pulsos son por modulación de amplitud.
- La frecuencia portadora es de 38kHz (detectable por el TSOP1838).
- La frecuencia de un bit ‘0’ es de 1.12ms y la de un bit ‘1’ es de 2.25ms.
- En total se transmiten un bit de Start de 9ms+4.5ms=13.5ms mas 32 bits de datos.
Aquí está la conexión del sensor infrarrojo TSOP1838 según su datasheet y el patillaje del mismo (aunque yo solo conecto una resistencia de 470 ohmios que son las que uso para los leds conectada a Vcc y a la patilla 1 del TSOP1838):
Para el programa en Arduino he utilizado la libreria IRremote.h de Ken Shirriff, que simplifica mucho el uso de los mandos a distancia en nuestros programas. Os dejo a continuación un video del funcionamiento del programa así como el código del programa de dos maneras distintas, una empleando sentencias if y otra empleado switch case en su lugar:
Este es el código con sentencias if (ocupa más memoria de programa como se puede ver en la imagen de abajo que con la sentencia switch case):
/*Programa realizado por Regata 04/09/2011*/ /*Programa para control de luces (en este caso leds) mediante un mando con protocolo NEC, ademas de encender y apagar tambien podemos controlar dos led mediante PWM para ver como funciona*/ #include <IRremote.h> //Añadimos la libreria para el control del TSOP1838 que usamos /*En este programa trabajo con el mando del disco duro IOMEGA SCREENPLAY HD MULTIMEDIA Los datos de los codigos de las teclas de este mando y del mando de AVERMEDIA TV203 estan abajo del programa*/ #define RECV_PIN 12 //indicamos el pin por el que recibimos los datos del sensor TSOP1838 int i; //Variable para salidas boolean encendido[8]; //Matriz donde guardamos el estado de las sariables de control de los leds int brillo1=0; //Cuanto alumbra el led rojo int brillo2=0; //Cuanto alumbra el led verde //Iniciamos la libreria para el control del sensor TSOP indicando el pin de lectura IRrecv irrecv(RECV_PIN); decode_results results; void setup() { //Configuramos comunicacion serie para depuracion y poder ver los codigos de las teclas Serial.begin(9600); //Indicamos como salidas los pines del 2 al 9 for(i=2;i<12;i++) { pinMode(i,OUTPUT); } for(i=0;i<8;i++) { encendido[i]=0; } irrecv.enableIRIn(); // Iniciamos la recepcion } void loop() { //Si tenemos datos de lectura debido a que se pulsa una tecla en el mando if (irrecv.decode(&results)) { //Mostramos por puerte serie dicho codigo en Hexadecimal(para depuracion) Serial.print("Codigo: 0x") ; Serial.println(results.value,HEX) ; //Comprobamos si es la TECLA 1 if(results.value==0x2FC827D) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[0]==1) { digitalWrite(2,LOW); encendido[0]=0; } //si no, lo encendemos else { digitalWrite(2,HIGH); encendido[0]=1; } } //Comprobamos si es la TECLA 2 if(results.value==0x2FCB24D) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[1]==1) { digitalWrite(3,LOW); encendido[1]=0; } //si no, lo encendemos else { digitalWrite(3,HIGH); encendido[1]=1; } } //Comprobamos si es la TECLA 3 if(results.value==0x2FCA25D) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[2]==1) { digitalWrite(4,LOW); encendido[2]=0; } //si no, lo encendemos else { digitalWrite(4,HIGH); encendido[2]=1; } } //Comprobamos si es la TECLA 4 if(results.value==0x2FC42BD) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[3]==1) { digitalWrite(5,LOW); encendido[3]=0; } //si no, lo encendemos else { digitalWrite(5,HIGH); encendido[3]=1; } } //Comprobamos si es la TECLA 5 if(results.value==0x2FC728D) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[4]==1) { digitalWrite(6,LOW); encendido[4]=0; } //si no, lo encendemos else { digitalWrite(6,HIGH); encendido[4]=1; } } //Comprobamos si es la TECLA 6 if(results.value==0x2FC629D) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[5]==1) { digitalWrite(7,LOW); encendido[5]=0; } //si no, lo encendemos else { digitalWrite(7,HIGH); encendido[5]=1; } } //Comprobamos si es la TECLA 7 if(results.value==0x2FCC23D) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[6]==1) { digitalWrite(8,LOW); encendido[6]=0; } //si no, lo encendemos else { digitalWrite(8,HIGH); encendido[6]=1; } } //Comprobamos si es la TECLA 8 if(results.value==0x2FCF20D) { //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[7]==1) { digitalWrite(9,LOW); encendido[7]=0; } //si no, lo encendemos else { digitalWrite(9,HIGH); encendido[7]=1; } } //Comprobamos si es la TECLA STOP if(results.value==0x2FC20DF) { //Apagamos todos los leds for(i=2;i<12;i++) { digitalWrite(i,LOW); if(i<10) //Comprobamos el limite de los leds de la barra de leds //y ponemos a 0 la variable de control de cada led { encendido[i-2]=0; } brillo1=0; brillo2=0; } } //Comprobamos si es la TECLA PLAY if(results.value==0x2FCE817) { //Encendemos todos los leds for(i=2;i<12;i++) { digitalWrite(i,HIGH); if(i<10) //Comprobamos el limite de los leds de la barra de leds //y ponemos a 1 la variable de control de cada led { encendido[i-2]=1; } brillo1=255; brillo2=255; } } //Comprobamos si es la tecla VOL+, aumentamos el brillo del led rojo if(results.value==0x2FCB04F) { //Si el brillo es menor de 255 aumentamos 1 paso de 5 su brillo if(brillo1<255) { brillo1=brillo1+51; analogWrite(10,brillo1); } } //Comprobamos si es la tecla VOL-, disminuimos el brillo del led rojo if(results.value==0x2FCC837) { //Si el brillo es mayor de 0 disminuimos 1 paso de 5 su brillo if(brillo1>0) { brillo1=brillo1-51; analogWrite(10,brillo1); } } //Comprobamos si es la tecla >>, aumentamos el brillo del led verde if(results.value==0x2FC28D7) { //Si el brillo es menor de 255 aumentamos 1 paso de 5 su brillo if(brillo2<255) { brillo2=brillo2+51; analogWrite(11,brillo2); } } //Comprobamos si es la tecla <<, disminuimos el brillo del led rojo if(results.value==0x2FC38C7) { //Si el brillo es mayor de 0 disminuimos 1 paso de 5 su brillo if(brillo2>0) { brillo2=brillo2-51; analogWrite(11,brillo2); } } delay(50); //retardo de 250 ms para evitar que el codigo se lea dos veces en una pulsacion irrecv.resume(); // Recibimos el siguiente valor del sensor } } /*Datos Mando IOMEGA SCREENPLAY HD MULTIMEDIA TECLA 1 Codigo: 0x2FC827D TECLA 2 Codigo: 0x2FCB24D TECLA 3 Codigo: 0x2FCA25D TECLA 4 Codigo: 0x2FC42BD TECLA 5 Codigo: 0x2FC728D TECLA 6 Codigo: 0x2FC629D TECLA 7 Codigo: 0x2FCC23D TECLA 8 Codigo: 0x2FCF20D TECLA 9 Codigo: 0x2FCE21D TECLA 0 Codigo: 0x2FC18E7 TECLA VOL+ Codigo: 0x2FCB04F TECLA VOL- Codigo: 0x2FCC837 TECLA SETUP Codigo: 0x2FC12ED TECLA MENU Codigo: 0x2FC6897 TECLA << Codigo: 0x2FC38C7 TECLA >> Codigo: 0x2FC28D7 TECLA AUDIO Codigo: 0x2FC926D TECLA ANGLE Codigo: 0x2FC52AD TECLA SUBTITLE Codigo: 0x2FCD22D TECLA FLECHA ARRIBA Codigo: 0x2FC807F TECLA FLECHA IZQUIERDA Codigo: 0x2FC9867 TECLA FLECHA ABAJO Codigo: 0x2FC906F TECLA PLAY Codigo: 0x2FCE817 TECLA DISPLAY Codigo: 0x2FCD827 TECLA SEARCH Codigo: 0x2FCD02F TECLA STOP Codigo: 0x2FC20DF TECLA PAUSE Codigo: 0x2FCE01F TECLA A-B Codigo: 0x2FC40BF TECLA REPEAT Codigo: 0x2FCC03F TECLA SLOW Codigo: 0x2FC50AF TECLAS QUE NO ENVIAN NINGUN CODIGO: TECLA POWER, TECLA TITEL, TECLA |<<, TECLA >>|, TECLA FLECHA DERECHA, TECLA SLOW */ /*Datos mando AVERMEDIA TV203 TECLA TV/FM Codigo: 0x40BF807F TECLA CD Codigo: 0x40BF40BF TECLA TELETEXT Codigo: 0x40BFC03F TECLA POWER Codigo: 0x40BF00FF TECLA 1 Codigo: 0x40BFA05F TECLA 2 Codigo: 0x40BF609F TECLA 3 Codigo: 0x40BFE01F TECLA 4 Codigo: 0x40BF906F TECLA 5 Codigo: 0x40BF50AF TECLA 6 Codigo: 0x40BFD02F TECLA 7 Codigo: 0x40BFB04F TECLA 8 Codigo: 0x40BF708F TECLA 9 Codigo: 0x40BFF00F TECLA 0 Codigo: 0x40BF8877 TECLA VIDEO Codigo: 0x40BF20DF TECLA AUDIO Codigo: 0x40BF10EF TECLA FULL SCREEN Codigo: 0x40BF30CF TECLA DISPLAY Codigo: 0x40BF48B7 TECLA LOOP Codigo: 0x40BFC837 TECLA PREVIEW Codigo: 0x40BF08F7 TECLA AUTOSCAN Codigo: 0x40BFA857 TECLA FREEZE Codigo: 0x40BF6897 TECLA CAPTURE Codigo: 0x40BFE817 TECLA MUTE Codigo: 0x40BF28D7 TECLA RECORD Codigo: 0x40BF9867 TECLA PAUSE Codigo: 0x40BF58A7 TECLA STOP Codigo: 0x40BFD827 TECLA PLAY Codigo: 0x40BF18E7 TECLA CIRCULO ROJO Codigo: 0x40BFB847 TECLA VOL- Codigo: 0x40BF7887 TECLA VOL+ Codigo: 0x40BFF807 TECLA CIRCULO AMARILLO Codigo: 0x40BF38C7 TECLA CIRCULO VERDE Codigo: 0xC03F807F TECLA CHANNEL- Codigo: 0xC03F40BF TECLA CHANNEL+ Codigo: 0xC03FC03F TECLA CIRCULO AZUL Codigo: 0xC03F00FF EN ESTE MANDO SE VISUALIZAN TODOS LOS CODIGOS DE LAS TECLAS */
Aquí está el código con la sentencia switch case en lugar de con las sentencias if:
/*Programa realizado por Regata 04/09/2011*/ /*Programa para control de luces (en este caso leds) mediante un mando con protocolo NEC, ademas de encender y apagar tambien podemos controlar dos led mediante PWM para ver como funciona*/ #include <IRremote.h> //Añadimos la libreria para el control del TSOP1838 que usamos /*En este programa trabajo con el mando del disco duro IOMEGA SCREENPLAY HD MULTIMEDIA Los datos de los codigos de las teclas de este mando y del mando de AVERMEDIA TV203 estan abajo del programa*/ #define RECV_PIN 12 //indicamos el pin por el que recibimos los datos del sensor TSOP1838 int i; //Variable para salidas boolean encendido[8]; //Matriz donde guardamos el estado de las sariables de control de los leds int brillo1=0; //Cuanto alumbra el led rojo int brillo2=0; //Cuanto alumbra el led verde //Iniciamos la libreria para el control del sensor TSOP indicando el pin de lectura IRrecv irrecv(RECV_PIN); decode_results results; void setup() { //Configuramos comunicacion serie para depuracion y poder ver los codigos de las teclas Serial.begin(9600); //Indicamos como salidas los pines del 2 al 9 for(i=2;i<12;i++) { pinMode(i,OUTPUT); } for(i=0;i<8;i++) { encendido[i]=0; } irrecv.enableIRIn(); // Iniciamos la recepcion } void loop() { //Si tenemos datos de lectura debido a que se pulsa una tecla en el mando if (irrecv.decode(&results)) { //Mostramos por puerte serie dicho codigo en Hexadecimal(para depuracion) Serial.print("Codigo: 0x") ; Serial.println(results.value,HEX) ; //Comprobamos si es la TECLA 1 switch(results.value) { case 0x2FC827D: //Comprobamos si es la TECLA 1 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[0]==1) { digitalWrite(2,LOW); encendido[0]=0; } //si no, lo encendemos else { digitalWrite(2,HIGH); encendido[0]=1; } break; case 0x2FCB24D: //Comprobamos si es la TECLA 2 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[1]==1) { digitalWrite(3,LOW); encendido[1]=0; } //si no, lo encendemos else { digitalWrite(3,HIGH); encendido[1]=1; } break; case 0x2FCA25D: //Comprobamos si es la TECLA 3 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[2]==1) { digitalWrite(4,LOW); encendido[2]=0; } //si no, lo encendemos else { digitalWrite(4,HIGH); encendido[2]=1; } break; case 0x2FC42BD: //Comprobamos si es la TECLA 4 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[3]==1) { digitalWrite(5,LOW); encendido[3]=0; } //si no, lo encendemos else { digitalWrite(5,HIGH); encendido[3]=1; } break; case 0x2FC728D: //Comprobamos si es la TECLA 5 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[4]==1) { digitalWrite(6,LOW); encendido[4]=0; } //si no, lo encendemos else { digitalWrite(6,HIGH); encendido[4]=1; } break; case 0x2FC629D: //Comprobamos si es la TECLA 6 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[5]==1) { digitalWrite(7,LOW); encendido[5]=0; } //si no, lo encendemos else { digitalWrite(7,HIGH); encendido[5]=1; } break; case 0x2FCC23D: //Comprobamos si es la TECLA 7 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[6]==1) { digitalWrite(8,LOW); encendido[6]=0; } //si no, lo encendemos else { digitalWrite(8,HIGH); encendido[6]=1; } break; case 0x2FCF20D: //Comprobamos si es la TECLA 8 //Comprobamos si esta encendido el led, si lo esta lo apagamos if(encendido[7]==1) { digitalWrite(9,LOW); encendido[7]=0; } //si no, lo encendemos else { digitalWrite(9,HIGH); encendido[7]=1; } break; case 0x2FC20DF: //Comprobamos si es la TECLA STOP //Apagamos todos los leds for(i=2;i<12;i++) { digitalWrite(i,LOW); if(i<10) //Comprobamos el limite de los leds de la barra de leds //y ponemos a 0 la variable de control de cada led { encendido[i-2]=0; } brillo1=0; brillo2=0; } break; case 0x2FCE817: //Comprobamos si es la TECLA PLAY //Encendemos todos los leds for(i=2;i<12;i++) { digitalWrite(i,HIGH); if(i<10) //Comprobamos el limite de los leds de la barra de leds //y ponemos a 1 la variable de control de cada led { encendido[i-2]=1; } brillo1=255; brillo2=255; } break; case 0x2FCB04F: //Comprobamos si es la tecla VOL+, aumentamos el brillo del led rojo //Si el brillo es menor de 255 aumentamos 1 paso de 5 su brillo if(brillo1<255) { brillo1=brillo1+51; analogWrite(10,brillo1); } break; case 0x2FCC837: //Comprobamos si es la tecla VOL-, disminuimos el brillo del led rojo //Si el brillo es mayor de 0 disminuimos 1 paso de 5 su brillo if(brillo1>0) { brillo1=brillo1-51; analogWrite(10,brillo1); } break; case 0x2FC28D7: //Comprobamos si es la tecla >>, aumentamos el brillo del led verde //Si el brillo es menor de 255 aumentamos 1 paso de 5 su brillo if(brillo2<255) { brillo2=brillo2+51; analogWrite(11,brillo2); } break; case 0x2FC38C7: //Comprobamos si es la tecla <<, disminuimos el brillo del led rojo //Si el brillo es mayor de 0 disminuimos 1 paso de 5 su brillo if(brillo2>0) { brillo2=brillo2-51; analogWrite(11,brillo2); } break; } delay(50); //retardo de 250 ms para evitar que el codigo se lea dos veces en una pulsacion irrecv.resume(); // Recibimos el siguiente valor del sensor } } /*Datos Mando IOMEGA SCREENPLAY HD MULTIMEDIA TECLA 1 Codigo: 0x2FC827D TECLA 2 Codigo: 0x2FCB24D TECLA 3 Codigo: 0x2FCA25D TECLA 4 Codigo: 0x2FC42BD TECLA 5 Codigo: 0x2FC728D TECLA 6 Codigo: 0x2FC629D TECLA 7 Codigo: 0x2FCC23D TECLA 8 Codigo: 0x2FCF20D TECLA 9 Codigo: 0x2FCE21D TECLA 0 Codigo: 0x2FC18E7 TECLA VOL+ Codigo: 0x2FCB04F TECLA VOL- Codigo: 0x2FCC837 TECLA SETUP Codigo: 0x2FC12ED TECLA MENU Codigo: 0x2FC6897 TECLA << Codigo: 0x2FC38C7 TECLA >> Codigo: 0x2FC28D7 TECLA AUDIO Codigo: 0x2FC926D TECLA ANGLE Codigo: 0x2FC52AD TECLA SUBTITLE Codigo: 0x2FCD22D TECLA FLECHA ARRIBA Codigo: 0x2FC807F TECLA FLECHA IZQUIERDA Codigo: 0x2FC9867 TECLA FLECHA ABAJO Codigo: 0x2FC906F TECLA PLAY Codigo: 0x2FCE817 TECLA DISPLAY Codigo: 0x2FCD827 TECLA SEARCH Codigo: 0x2FCD02F TECLA STOP Codigo: 0x2FC20DF TECLA PAUSE Codigo: 0x2FCE01F TECLA A-B Codigo: 0x2FC40BF TECLA REPEAT Codigo: 0x2FCC03F TECLA SLOW Codigo: 0x2FC50AF TECLAS QUE NO ENVIAN NINGUN CODIGO: TECLA POWER, TECLA TITEL, TECLA |<<, TECLA >>|, TECLA FLECHA DERECHA, TECLA SLOW */ /*Datos mando AVERMEDIA TV203 TECLA TV/FM Codigo: 0x40BF807F TECLA CD Codigo: 0x40BF40BF TECLA TELETEXT Codigo: 0x40BFC03F TECLA POWER Codigo: 0x40BF00FF TECLA 1 Codigo: 0x40BFA05F TECLA 2 Codigo: 0x40BF609F TECLA 3 Codigo: 0x40BFE01F TECLA 4 Codigo: 0x40BF906F TECLA 5 Codigo: 0x40BF50AF TECLA 6 Codigo: 0x40BFD02F TECLA 7 Codigo: 0x40BFB04F TECLA 8 Codigo: 0x40BF708F TECLA 9 Codigo: 0x40BFF00F TECLA 0 Codigo: 0x40BF8877 TECLA VIDEO Codigo: 0x40BF20DF TECLA AUDIO Codigo: 0x40BF10EF TECLA FULL SCREEN Codigo: 0x40BF30CF TECLA DISPLAY Codigo: 0x40BF48B7 TECLA LOOP Codigo: 0x40BFC837 TECLA PREVIEW Codigo: 0x40BF08F7 TECLA AUTOSCAN Codigo: 0x40BFA857 TECLA FREEZE Codigo: 0x40BF6897 TECLA CAPTURE Codigo: 0x40BFE817 TECLA MUTE Codigo: 0x40BF28D7 TECLA RECORD Codigo: 0x40BF9867 TECLA PAUSE Codigo: 0x40BF58A7 TECLA STOP Codigo: 0x40BFD827 TECLA PLAY Codigo: 0x40BF18E7 TECLA CIRCULO ROJO Codigo: 0x40BFB847 TECLA VOL- Codigo: 0x40BF7887 TECLA VOL+ Codigo: 0x40BFF807 TECLA CIRCULO AMARILLO Codigo: 0x40BF38C7 TECLA CIRCULO VERDE Codigo: 0xC03F807F TECLA CHANNEL- Codigo: 0xC03F40BF TECLA CHANNEL+ Codigo: 0xC03FC03F TECLA CIRCULO AZUL Codigo: 0xC03F00FF EN ESTE MANDO SE VISUALIZAN TODOS LOS CODIGOS DE LAS TECLAS */
Espero que os sirva de ayuda para vuestros proyectos.
Si te ha servido de ayuda esta entrada, puedes realizar un donativo para agradecer el tiempo que dedico al blog y ayudar a hacer más entradas.
Hola, buen tutorial, tengo casi acabado un proyecto y se me resiste, mi pregunta es, como puedo poner dos leds con el mismo código del mando para que cada vez que presione ese código del mando se enciendan esas dos leds y cuando lo suelte….se apaguen??