Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PDF PDF
PDF PDF
Philips RC-5
A menudo en la etapa de desarrollo de algn proyecto pensamos en que sera til la utilizacin de un
control a distancia. El control de este tipo ms comnmente utilizado es el control remoto mediante
infrarrojos, como el usado en cualquier televisor o equipo de audio.
Este documento contiene la informacin necesaria para que podamos decodificar los mensajes
enviados por estos controles remotos en nuestros proyectos.
> Caractersticas:
Las caractersticas ms sobresalientes de este protocolo estn resumidas en las siguientes lneas:
> El protocolo:
El protocolo consiste en un tren de pulsos cuadrados de 36Khz (la denominada "portadora"). Cada "1"
esta codificado como 889 microsegundos de pulsos, y 889 microsegundos de "silencio". El "0" se
codifica como 889 microsegundos de "silencio" y 889 microsegundos de pulsos. La longitud total del
"0" y del "1" es idntica, y son 1778 microsegundos (o 1,778 milisegundos). El grafico siguiente ilustra
claramente esto:
Dentro de un bit "caben" exactamente 64 pulsos, si la portadora es de 36KHz. Es decir, el periodo de
una seal de 36KHz es de 1/36.000 = 27.78125... s, que multiplicado por 64 da exactamente 1778
s. Este es un buen dato para tener en cuenta el diseo del software de nuestro receptor.
Para que el receptor sepa que le est "diciendo" el emisor remoto, debe poder interpretar las "tramas"
de ceros y unos que este le enva. Cada trama es un comando, y est compuesto por 14 bits (15 en el
caso del RC5X). De esos 14 bits, los primeros 2 bits son de "start" (arranque): siempre son "1". El
tercer bit se invierte cada vez que una tecla se pulsa y se suelta nuevamente, para poder distinguir si
una tecla permanece presionada o se ha presionado ms de una vez. Los siguientes 5 bits
corresponden a la direccin del dispositivo receptor, y los ltimos 6 al comando trasmitido. Esto
permite utilizar un mismo control remoto para comandar diferentes equipos, simplemente asignando a
cada uno un cdigo de direccin diferente.
Hay una variacin del cdigo RC5 llamada RC5X que dispone de 7 bits para determinar el comando (lo
que permite 128 comandos diferentes vs. los 64 comandos del RC5 tradicional). La forma de la trama
es la misma, pero el segundo bit de start (S2) es utilizado como el bit 7 del comando.
Tanto en la direccin como en el comando, primero se transmite el bit mas significativo (MSB) y por
ultimo el menos significativo (LSB)
En ese caso, deberamos consultar las siguientes tablas para saber cuales son los comandos
predefinidos por Philips:
Direcciones. Las que figuran en blanco no estn Lista de comandos asignados para TV y VCR por
asignadas, y es buena idea Philips.
utilizarlas para nuestros proyectos.
Partimos de esta parte terica para programar la recepcin de un mando y el envo con protocolo RC-5
TRAMA RC5
1 1 0 0 0 1 0 1 0 0 0 0 0 1
Segundo bit Bit de inicio de RC5 (a 1). En RC5X se usa como 7 bit de comando.
Tercer bit Se invierte su valor cada vez que se pulsa una tecla. (0 1 0 1 )
9, 10, 11, 12, 13 y 14 (6 bits) Comando. En este caso 000001 = 1 HEX Tecla 1
1 1 0 0 0 0 0 0 1 0 0 0 0 1
Si pulso otra vez la tecla PROG+ 0x3821 11 1000 0010 0001 (En azul bit que cambia)
1 1 1 0 0 0 0 0 1 0 0 0 0 1
Si mantenemos pulsada una tecla se emite la misma trama a intervalos de unos 114 microsegundos.
Conectamos:
GND Resistencia de 220 Ohmios Ctodo Diodo infrarrojos Anodo pin 5 PWM.
Pulsador de la derecha (pin 11) Manda una rfaga para bajar un canal (prog-)
FUNDAMENTO
Subir o bajar canal al pulsar un botn u otro, enviando la informacin mediante el LED de infrarrojos emisor.
La mayor dificultad es mandar una rfaga (trama) de informacin, con protocolo RC5, para que un TV o VCR, lo
interprete correctamente.
Vamos a crear una funcin llamada pulsos para generar los 32 ciclos de impulsos. Cada impulso tiene unos 18.52
microsegundos de nivel alto y unos 9.26 microsegundos de nivel bajo.
OJO: Cada instruccin del programa tarda sobre unos 8 microsegundos en ejecutarse, por lo que habr que tenerlo
en cuenta a la hora de hacer nuestra funcin.
void pulsos()
{
// long tiempo = micros();
}
// tiempo = micros() - tiempo; // mide el tiempo en s que tarda en ejecutarse el bucle.
//Serial.println(tiempo);
El texto en rojo, usado para depurar, nos saca en pantalla el tiempo total de los 32 impulsos, que debe dar
aproximadamente unos 889 s.
Cuando se usa para la trama hay que volver a poner los // de comentario, para evitar prdida de tiempo. Esto hara
que la trama en vez de 25 ms pase a ser mayor, lo que implica que el receptor no lo interpretara bien.
Los retardos de 11 y 3 los consegu midiendo el tiempo de nivel alto y de nivel bajo (con el texto en rojo, pero entre
las dos lneas de cada nivel).
A continuacin va el programa comentado. Est programado para un TV. Subir y bajar de canal.
long tiempo_trama = micros(); // Vamos a medir la trama, que debe ser de unos 25 ms (25000 s)
// Se podra QUITAR
// long tpo2 = micros(); // tpo2 mide el tiempo de envio de los 2 bits de inicio (1,5 en realidad)
// MANDO los 2 bits de inicio (La 1 parte seria mandar un cero durante 889 s. No hara nada (no hace falta))
pulsos(); // 2 parte del primer bit de inicio. Tren de impulsos 889 s
espacio(); // 1 parte 2 bit de inicio. Nivel bajo 889 microsegundos
pulsos(); // 2 parte del 2 bit de inicio. Fin envio dos bits de inicio. Tren de impulsos 889 s
// tpo2 = micros() - tpo2;
// Serial.println(tpo2); // Resultado 889+889+889 = 2667 aproximadamente.
void loop()
{
if (digitalRead(pulsador1))
{
if (conmuta)
{
//dato_uno();
enviarDato(0x3020); // 0x3160 prog+ VCR
conmuta = 0; // 0x3020 prog+ TV
}
else
{
enviarDato(0x3820); // 0x3960 prog+ 2 pulsacion VCR
conmuta = 1; // 0x3820 prog+ 2 pul TV
}
delay(100);
}
if (digitalRead(pulsador2))
{
if (conmuta)
{
//dato_uno();
enviarDato(0x3021); // 0x3161 prog- VCR
conmuta = 0; // 0x3021 prog+ TV
}
else
{
enviarDato(0x3821); // 0x3961 prog- 2 pulsacion VCR
conmuta = 1; // 0x3821 prog+ 2 puls TV
}
delay(100);
}
}
// tiempo = micros() - tiempo;
//Serial.println(tiempo);
void espacio()
{
digitalWrite(pinIRSalida,LOW); // Pone el pin 5 a nivel bajo. No enva datos.
delayMicroseconds(870); // Retardo de 889 s = 870 + tiempo instruccin
}
Necesitamos un diodo RECEPTOR de infrarrojos, que trabaje bien sobre los 36KHz.
GND nodo del receptor de infrarrojos Ctodo Resistencia de unos 300K Vcc (5v)
Del ctodo sacamos una conexin al pin 2 PWM Corresponde con la interrupcin 0 del Arduino.
Interrupcin 0 en el pin 2.
Interrupcin 1 en el pin 3.
El Arduino MEGA tiene 4 mas: interrupcin 2 (pin 21), 3 (pin 20), 4 (pin 19) y 5 (pin 18).
RISING se dispara cuando el pin pasa desde nivel bajo a alto (LOW HIGH)
FALLING se dispara cuando el pin pasa desde nivel alto a bajo (HIGH LOW)
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE); // Ejecuta la funcin blink cuando cambia el
// nivel en el pin 2
}
void loop()
{
digitalWrite(pin, state); // se ejecuta continuamente, pero solo cambia cuando se
// produce un cambio de nivel en el pin 2 (interrupcin 0)
}
detachInterrupt(interrupcin)
El uso de las interrupciones es muy bueno para controlar datos de entrada que no deben esperar en el bucle
loop y ejecutar una funcin que no est en el loop.
En nuestro caso la funcin de decodificar una seal de un mando solo se ejecutar cuando se haya
producido la interrupcin, que provoca la llegada de un nivel alto en el pin 2 (interrupcin 0).
A continuacin el programa para recibir los datos de un mando con protocolo RC5 (Philips).
(Leemos datos cada 100 microsegundos aproximadamente, cuando se produce una interrupcin en el pin2)
El programa va comentado y en pantalla saca los datos recibidos de tal forma que vayamos entendiendo las
lneas de cdigo). Nombre del programa: recibir_datos_infrarrojos_arduino.pde
void setup()
{
Serial.begin(9600);
pinMode(pulsador1, INPUT);
// INTERRUPCIN. Ejecuta la funcin "recibir" cuando el pin 2 pase a nivel HIGH
attachInterrupt(0, recibir, HIGH);
}
void loop()
{
// Cuando se activa el pulsador1 sacamos el resultado en pantalla
if (digitalRead(pulsador1) == HIGH)
{
Serial.print(" PULSADO ");
// Veces pulsadas
Serial.println(contador);
Serial.print(" RESULTADO = ");
Serial.println(resultado, HEX);
contador++;
// Se mantiene en este bucle hasta que se suelta el pulsador1
while (digitalRead(pulsador1) == HIGH)
{
}
delay(300);
}
void recibir()
{
long tiempos[28];
boolean desbordamiento = 0;
boolean error = 0;
int nb = 2;
int nbtotal = 0;
boolean cambia_nivel = 1;
// Inicializo los tiempos a cero.
for (int i=0; i < 28; i++)
{
tiempos[i] = 0;
}
// Cuando recibamos un impulso positivo
if (!digitalRead(2))
{
// Hasta que un dato sea mayor que 25, indica un nivel bajo 0000000...
// Vamos guardando tiempo bajo, alto, bajo, alto, etc
while (!desbordamiento)
{
while(digitalRead(2)==cambia_nivel)
{
tiempos[nb]++;
delayMicroseconds(100);
}
if (tiempos[nb] < 6) { desbordamiento = 1; error = 1; nb = 2; }
if (tiempos[nb] > 25) { desbordamiento = 1; nbtotal = nb - 1; }
cambia_nivel = !cambia_nivel;
nb++;
/*
while(!digitalRead(2)) { tiempos[nb]++; delayMicroseconds(100); }
nb++;
if (tiempos[nb] > 25) { desbordamiento = 1; nbtotal = nb - 1;}
*/
}
}
if (nb < 14) { error = 1; } // No se han recibido la trama completa
// Si no ha habido ms errores guardamos los datos en res[i]
//
if (!error)
{
// tiempos[1] sobre 7 indica nivel alto
// tiempos pares indican nivel bajo sobre 7,8,9 "0" y 15,16,17,18 "00"
// tpos impares indican nivel alto sobre 7,8,9 "1" y 15,16,17,18 "11"
cambia_nivel = 1;
int res[50];
int bit_totales = 0;
for (int i=2; i < nb; i++)
{
Serial.print(i);
Serial.print(" ");
Serial.println(tiempos[i]);
res[bit_totales] = cambia_nivel;
bit_totales++;
if (tiempos[i] > 12)
{
res[bit_totales] = cambia_nivel;
bit_totales++;
}
cambia_nivel = !cambia_nivel;
}
//Serial.println(bit_totales);
// Tomamos los bits pares que guardamos en el resultado (variable global)
resultado = 1;
for (int i = 0; i < bit_totales-1; i++)
{
Serial.print(res[i]);
if (i % 2)
{
if (res[i] == 1)
{
resultado = resultado <<= 1;
}
else { resultado = (resultado <<=1) | 1; }
}
}
// Comprobamos que el resultado es el deseado en pantalla.
Serial.println(" Resultado obtenido ");
Serial.println(resultado, BIN);
Serial.println(resultado, HEX);
char data_word = resultado & 0x3F; // Nos quedamos con los 6 ultimos bits (comando)
Serial.println(data_word, HEX);
}
}
}
Se puede hacer de varias formas, probadas, pero creo que esta est mejor depurada.
Aconsejo que probis con otras posibilidades que se os ocurran. Objetivo: poder hacer los emisores y
detectores de otros protocolos como el RC6, NEC, SONY, NOKIA, etc
27
3 10
46
5 19
66
7 10
8 15
9 18
10 15
11 18
12 6
13 10
14 7
15 10
16 6
17 10
18 6
19 10
20 15
21 10
22 834
101001011001100101010101101 Resultado obtenido
11100101000001
3941
1
El 22 vale 834 *100 = 83400, que corresponde con el tiempo de reposo entre rfaga y rfaga.
1 Canal pulsado.