En este proyecto haremos un mando a distancia por infrarrojos, controlado desde el teclado de un PC.
En mi caso se trata de una TV Philips. Una vez terminado, desde el monitor serie pulsando los números del 1 al 9 cambiaremos de canal y con las teclas Q y A controlamos el volumen del televisor.
Como en proyectos anteriores, lo primero es decodificar los diferentes códigos del mando a distancia del dispositivo que deseamos controlar.
Para ello montamos el circuito que se muestra más abajo. Podemos conectar a la vez el receptor y el emisor de infrarrojos y dependiendo del código que subamos al Arduino utilizaremos el circuito para capturar los códigos o para enviarlos.
El sketch para mostrar los códigos en formato raw lo he obtenido de as3breeze.com.
/*
* IRremote: IRrecvDump - dump details of IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
* http://as3breeze.com/arduino-sending-samsung-ir-codes/
*/
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
// decode_results *results = (decode_results *)v
void dump(decode_results *results) {
int count = results->rawlen;
if (results->decode_type == UNKNOWN) {
Serial.print("Unknown encoding: ");
}
else if (results->decode_type == NEC) {
Serial.print("Decoded NEC: ");
}
else if (results->decode_type == SONY) {
Serial.print("Decoded SONY: ");
}
else if (results->decode_type == RC5) {
Serial.print("Decoded RC5: ");
}
else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: ");
}
else if (results->decode_type == PANASONIC) {
Serial.print("Decoded PANASONIC: ");
}
else if (results->decode_type == JVC) {
Serial.print("Decoded JVC: ");
}
else if (results->decode_type == SAMSUNG) {
Serial.print("Decoded SAMSUNG: ");
}
int val1 = results->value;
Serial.print(val1, HEX);
Serial.print(" (");
int valbits = results->bits;
Serial.print(valbits, DEC);
Serial.println(" bits)");
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 0; i < count; i++) {
if ((i % 2) == 1) {
int valen = results->rawbuf[i]*USECPERTICK;
Serial.print(valen, DEC);
}
else {
int negvalen =-(int)results->rawbuf[i]*USECPERTICK;
Serial.print(negvalen, DEC);
}
Serial.print(", ");
}
Serial.println("");
}
void loop() {
if (irrecv.decode(&results)) {
int hexen = results.value;
Serial.println(hexen, HEX);
dump(&results);
irrecv.resume(); // Receive the next value
}
}
La forma de proceder es la habitual, subimos el sketch, abrimos el monitor serie y comenzamos a pulsar botones en el mando a distancia. Automáticamente se muestran los códigos en el monitor serie en formato raw.
La forma de presentar los códigos y la longitud en bits, puede variar dependiendo del fabricante del mando a distancia; cada uno implementa su propio protocolo.
Hay que hacer una pequeña modificación a cada uno de los códigos antes de poder utilizarlos en Arduino.
Para ello copiamos los códigos en el notepad
En primer lugar borramos la primera cifra, en el ejemplo de la imagen 30096, y a continuación borramos todos los signos negativos, es decir ponemos todos los números en positivo. Ahora ya es un código válido para enviar mediante Arduino.
Repetimos el proceso para cada uno de los códigos que queramos utilizar.
En este proyecto veremos como cambiar de canal pulsando los números del 1 al 9 en el teclado de nuestro ordenador, para ello necesitamos saber qué número tiene asignado cada botón del teclado.
Mediante un sencillo sketch se muestra en el monitor serie el número correspondiente a cada botón del teclado.
Subir el siguiente sketch al Arduino, abrir el monitor serie y pulsar las teclas correspondientes.
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
Una vez sabemos a que número corresponde cada tecla, mediante un sencillo código switch-case asignamos a cada pulsación la función correspondiente a cada canal.
En el sketch que se muestra a continuación, es donde hay que pegar el código raw que hemos modificado, para poder ser enviado por Arduino.
Si el código raw que habéis obtenido tiene una longitud diferente, hay que indicarlo así en el sketch al definir cada array de datos unsigned int canal1[42] donde 42 es la longitud.
La función irsend.sendRaw(canal1,42,38) tiene tres parámetros, el primero es el código raw, el segundo es la longitud, y el tercero -38- es la frecuencia del diodo emisor, normalmente 38kHz
#include <IRremote.h> // use the library
IRsend irsend;
unsigned int canal1[42] = {2650, 850, 450, 900, 450, 400, 500, 400, 500, 800, 950, 350, 500, 400, 500, 400, 450, 450, 450, 400, 450, 450, 450, 400, 450, 400, 500, 400, 500, 350, 500, 400, 500, 400, 450, 400, 500, 400, 450, 450, 900};
unsigned int canal2[40] = {2700, 850, 450, 850, 500, 400, 450, 400, 1400, 1250, 500, 350, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 350, 500, 400, 500, 400, 450, 400, 950, 800, 500};
unsigned int canal3[42] = {2650, 850, 450, 850, 450, 450, 450, 400, 450, 900, 900, 400, 500, 350, 450, 450, 450, 450, 450, 400, 450, 450, 500, 350, 500, 400, 500, 350, 500, 400, 500, 350, 500, 400, 500, 400, 450, 400, 950, 350, 500};
unsigned int canal4[40] = {2700, 850, 450, 850, 450, 450, 450, 400, 1350, 1300, 450, 400, 450, 450, 450, 400, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 350, 950, 850, 450, 400, 500};
unsigned int canal5[40] = {2700, 800, 500, 850, 450, 400, 500, 400, 450, 850, 950, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 350, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 950, 800, 950};
unsigned int canal6[40] = {2650, 850, 500, 850, 450, 400, 450, 450, 1350, 1250, 450, 450, 500, 350, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 900, 400, 500, 850, 450};
unsigned int canal7[42] = {2700, 850, 450, 850, 500, 400, 450, 400, 500, 850, 900, 400, 450, 400, 500, 400, 500, 350, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 350, 950, 400, 450, 400, 500};
unsigned int canal8[40] = {2700, 850, 450, 850, 450, 450, 450, 400, 1350, 1300, 450, 400, 500, 400, 500, 350, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 350, 500, 400, 900, 850, 500, 400, 450, 400, 500};
unsigned int canal9[40] = {2650, 850, 500, 800, 500, 400, 450, 400, 500, 850, 900, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 350, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 950, 800, 500, 400, 900};
unsigned int canal0[42] = {2650, 850, 450, 850, 500, 400, 450, 450, 1350, 1250, 450, 450, 450, 400, 450, 450, 450, 400, 500, 400, 450, 450, 450, 400, 450, 450, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 400, 450};
unsigned int volumeUp[42] = {2650, 850, 450, 850, 500, 400, 450, 400, 500, 850, 900, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 450, 450, 400, 500, 350, 500, 400, 500, 400, 900, 850, 450, 400, 500, 400, 450, 400, 500};
unsigned int volumeDown[38] = {2650, 850, 450, 900, 450, 400, 450, 450, 1350, 1250, 500, 400, 450, 450, 450, 400, 450, 450, 450, 400, 450, 450, 450, 400, 500, 400, 450, 400, 500, 400, 900, 850, 500, 400, 450, 400, 950};
unsigned int tvOnOff[40] = {2650, 850, 500, 850, 450, 400, 500, 400, 1350, 1250, 500, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 450, 400, 500, 400, 500, 350, 500, 400, 500, 400, 900, 400, 500, 800, 500, 400, 500};
int canal = 0;
void setup()
{
Serial.begin(9600);
}
void canalUno()
{
irsend.sendRaw(canal1,42,38);
delay(100);
}
void canalDos()
{
irsend.sendRaw(canal2,40,38);
delay(100);
}
void canalTres()
{
irsend.sendRaw(canal3,42,38);
delay(100);
}
void canalCuatro()
{
irsend.sendRaw(canal4,40,38);
delay(100);
}
void canalCinco()
{
irsend.sendRaw(canal5,40,38);
delay(100);
}
void canalSeis()
{
irsend.sendRaw(canal6,40,38);
delay(100);
}
void canalSiete()
{
irsend.sendRaw(canal7,42,38);
delay(100);
}
void canalOcho()
{
irsend.sendRaw(canal8,40,38);
delay(100);
}
void canalNueve()
{
irsend.sendRaw(canal9,40,38);
delay(100);
}
void canalCero()
{
irsend.sendRaw(canal0,42,38);
delay(100);
}
void subirVolumen()
{
irsend.sendRaw(volumeUp,42,38);
delay(100);
}
void bajarVolumen()
{
irsend.sendRaw(volumeDown,38,38);
delay(100);
}
void onoffTV()
{
irsend.sendRaw(tvOnOff,22,38);
delay(100);
}
void loop() {
// @param1 Raw data
// @param2 length
// @param3 frequency, (most devices use 38khz)
if (Serial.available() > 0)
{
canal = Serial.read();
switch(canal)
{
case 49: // tecla 1
canalUno();
break;
case 50: // tecla 2
canalDos();
break;
case 51: // tecla 3
canalTres();
break;
case 52: // tecla 4
canalCuatro();
break;
case 53: // tecla 5
canalCinco();
break;
case 54: // tecla 6
canalSeis();
break;
case 55: // tecla 7
canalSiete();
break;
case 56: // tecla 8
canalOcho();
break;
case 57: // tecla 9
canalNueve();
break;
case 111: //tecla 0
canalCero();
break;
case 113: //tecla Q
subirVolumen();
break;
case 97: //tecla A
bajarVolumen();
break;
case 119: //tecla W
onoffTV();
break;
}
}
}
Subir el sketch, abrir el monitor serie y comenzar a pulsar los botones, si todo va bien veréis como cambian los canales de vuestra tele o lo que halláis programado.
Tened en cuenta que los diodos infrarrojos tiene un alcance limitado, tal vez tengáis que acercar el Arduino al dispositivo en cuestión ;-)