RC5 de philips decodificación y control

Bueno antes que nada hola a todos !! (y)
En esta ocación les traigo un proyecto que realizé esta tarde como respuesta a un proyecto más grande que tengo en mente...:rolleyes:

Se trata de la decodificación del código RC5 de philips. Este código es el más usado en la actualidad por los experimentadores y desarrolladores debido a que es el más difundido y es ya un standar dentro de la industria.
Veamos algunas de sus características:
- Dirección de 5 bits y comando de 6 bits (7 bits de comando para RC-5X)
- Codificación de doble fase o bi-fase (Bi-phase, también llamada código Manchester)
- Frecuencia de portadora de 36 kHz
- Tiempo de bit constante de 1,778 ms (64 ciclos de 36 kHz)
Módulación:
El protocolo está basado en una modulación Manchester de doble fase sobre una portadora de 36 kHz. En esta codificación, todos los bits tienen la misma longitud, de 1,778 ms. La mitad del bit es un tren de pulsos de la portadora de 36 kHz, y en la otra mitad la señal está plana.
El cero lógico es representado por un tren de pulsos en la primera mitad del tiempo que corresponde el bit. El uno lógico es representado por un tren de pulsos en la segunda mitad de este tiempo. La relación entre pulso y pausa en la portadora de 36 kHz es de 1/3 o 1/4, lo que reduce el consumo de energía.
Veamos en un gráfico lo anteriormente dicho:
Comunicacion_modulacionRC5.gif

Protocolo:
Comunicacion_trenRC5.gif

Bueno este es un tren de pulsos correspondientes a un trama RC5. Como vemos son 14 bits en total de los cuales tenemos 2 bits de start + 1 de togle. Antes de que empieze la trama transcurre medio bit antes de que el receptor pueda detectarla. Luego de los bits de start comienza el bit de togle , este bit cambia de estado cada vez que nosotros presionamos un botón en el control remoto y soltamos la tecla. Su función es detectar cuando presionamos continuamente una tecla o cuando la presionamos varias veces de forma alternada.


Luego de este bit comienza el bit más significativo de la dirección del comando y se extiende 5 bits. A continuación comienza el bit más significativo del comando que se extiende 6 bits.


Haciendo la sumatoria nos dá : 2 bits de start + bit togle + 5 bits de dirección + 6 bits de datos = 14 bits que conforman una trama con una duración total de la trama de 25ms.


Mientras se mantenga presionada la tecla, el mensaje se repite cada 114 ms. El bit de conmutación mantendrá el mismo nivel lógico durante la repetición de un mensaje. Esto se hace así para que el programa de interpretación del receptor pueda detectar esta autorrepetición y no la confunda con sucesivas pulsaciones de una tecla.


Comandos predefinidos:
Acá se muestran algunos comandos predifinidos en la mayoría de los controles remotos.

comandos.gif



Ya teniendo explicado esto podemos pasar a desarrollar un programa de control básico para usar en nuestros proyectos de control.


Para mis prácticas yo usé el siguiente control remoto pero pueden usar cualquiera que cumpla con la norma RC5:
control.jpg

En el siguiente video les muestro la aplicación básica implementada en un PIC16F88 y un sensor IRM8601.

El código fuente del programa es el siguiente:
Código:
// Programa que recibe tramas RC5 del sensor IRM8601 - S las decodifica
// y muestra el comando y la dirección por un display LCD 2 x 16.
// El microcontrolador utilizado es un PIC16F88.
// Programador: Moyano Jonathan.
// Año: 2010.

#include <16f88.h>              // Definiciones de registros internos del micro.     
#fuses HS,NOWDT,NOPROTECT,PUT   // Fuses del programador.
#use delay (clock=20000000)     // Utilizamos un cristal de 20Mhz.
#use fast_io(b)

// Definiciones de hardware.
#define IR_RECEPTOR PIN_B0              // Pin donde estará conectado el receptor IR.
#define INDICADOR_TRAMA_RECIBIDA PIN_B1 // Led que indica cuando se recibe una trama RC5.

// Constantes del programa.
const int16    cuartodebit=440;   // tiempo [µs] de 1/4 bit
const int16    mediobit=880;      // tiempo [µs] de 1/2 bit

// Librerías de hardware externo:
#include <74HC595.c>            // Expansor de 8 salidas.

int16 decodifica_RC5();          // Declaramos la variable.

// Interrupción por RB0 en la que recibimos los datos del sensor.
#int_EXT
EXT_isr() {
  decodifica_RC5(); // Llama a la función de decodificación de trama de datos RC5.
  output_high(INDICADOR_TRAMA_RECIBIDA);
}

// Función de decodificación de RC5:
int16 decodifica_RC5()
{ 
   int16 D0=0, D1=65535; // Variables que contienen los datos.
   int i;                // Auxiliar.
      while (input(IR_RECEPTOR)); // Espera la transición 1 a 0 para empezar e leer.  
      delay_us(cuartodebit);   // Espera el bit de start de 440uS.  
      for(i=0;i<13;i++)       // Recoje los 13 bits de datos y los guarda...
      {
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D1=D1*2+input(IR_RECEPTOR);   // lee los datos...
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D0=D0*2+input(IR_RECEPTOR);   // lee los datos pero invertidos...
         
      }
      if ((D0^D1)==65535) return (D1 & 0x3FFF); else return (0);
      // Acá chequea que el valor que devuelva la función OR_EXCLUSIVA entre 
      // D1 (código original) ^ D0 (código invertido) sea igual a 3FFF (por ser 
      // valores coindidentes pero invertidos) ...si ese es el caso entonces devuelve
      // el valor de D1 ( datos originales ) para ser procesados...caso contrario retorna
      // 0.
}

void main() {
  set_tris_b(0x01);           // RB0 como entrada , las demás como salidas.
  output_low(INDICADOR_TRAMA_RECIBIDA); // Limpiamos el indicador de trama recibida.
  enable_interrupts(int_ext); // Habilitamos la interrupción externa por RB0.
  ext_int_edge(H_TO_L);  // Activa la interrupción por flanco de bajada.
  enable_interrupts(global);  // Habilitamos las interrupciones globales.
  output_74HC595(0x00); // Limpiamos las salidas.
  

   while(1)   // Bucle infinito.
   {
      long data;
      data=decodifica_RC5();        // Leemos los datos RC5.
      data=data & 0x007F;     // Limpiamos los bits de start y el de togle.
      // Determinamos cual es el comando recibido y actuamos en consecuencia.
      if (data==1) output_74HC595(0x01); 
      if (data==2) output_74HC595(0x02);
      if (data==3) output_74HC595(0x04);
      if (data==4) output_74HC595(0x08); 
      if (data==5) output_74HC595(0x10);
      if (data==6) output_74HC595(0x20);
      if (data==7) output_74HC595(0x40);
      if (data==8) output_74HC595(0x80);
      if (data==12)                
      {
       output_74HC595(0x00); // Limpiamos las salidas.         
      }
       output_low(INDICADOR_TRAMA_RECIBIDA); // Limpiamos el indicador de trama recibida.
   }

}
Y el código del expansor de salidas con 74HC595:
Código:
// Librería de control para el expansor de 8 salidas con 74HC595.
// Programador: Moyano Jonathan
// Versión: 1.0
// Fecha: 10/08/10
// Funciones:
// output_74HC595(valor); Muestra un valor de 0 a 255 en el puerto.


// Pines intercambiables según necesidades del usuario.

#define relog  PIN_A3
#define datos  PIN_A4
#define enable PIN_A2

void output_74HC595(int valor); // Definimos la función.

void output_74HC595(int valor) {

int contador; // Contador para escribir los datos al registro de desplazamiento.

  output_low(relog);
  output_low(enable);
  output_low(datos);
  
    for(contador=0;contador!=8;contador++) {  
     output_bit(datos,bit_test(valor,contador));
      output_high(relog);
       delay_cycles(1);
        output_low(relog);
  }
 
      output_high(enable);
      output_low(enable);
      delay_ms(1);
}
 

Adjuntos

  • Decodificando RC5 con PIC.zip
    270.4 KB · Visitas: 266
Última edición:
Hola Moyano Jonathan.

Gracias por el aporte,ya podre dar alguna utilidad a la pila de mandos que tengo por hay creando polvo,había echo algo con el protocolo nec,pero el rc5 es de los mas extendidos,como dices.

Gracias por la excelente explicación y por compartirlo.

Saludos!!
Javi.
 
Hola, gracias por compartir, estuve probando el código en un pic 16F648A y funciona bien, pude distinguir cada comando, y el bit de toggle, pero no logro hacerlo con los de dirección (device address), cada vez que oprimo una tecla del control, es diferente por lo que seguramente lo estoy haciendo mal.

Recien estoy empezando desde cero, en esto de la programación, y de la electrónica, tengo apenas un par de meses ( por si les parece muy obvio lo que pregunto ).

Mi duda es esa, como puedo separar los bits de toggle, dirección, y comando, ya que veo esta linea en el código:

PHP:
data=data & 0x007F;     // Limpiamos los bits de start y el de togle.

pero aunque he estado viendo para que sirve ese operador, (&) no logro entender como lo hace.

Saludos y gracias por cualquier consejo.
 
El operador "&" significa AND de datos.

Si vos tenés un dato que mide 14 bits en hexadecimal es 3FFF ese es la longitud incluyendo los bits de start y toggle.

Si los 2 bits de start + toggle son eliminados queda la direccion (5 bits) + datos (6 bits)

por lo tanto para eliminar start + togle + direccion tenemos que eliminar 6 bits del principio de la trama
o mejor dicho enmascararlos por lo tanto aplicamos & 0x7F y nos queda el comando.

Si queremos eliminar en cambio start + togle + comando aplicamos & 0x83F y nos queda la direccion.

Fijate si te funciona en caso de que no lo volvemos a ver.

saludos !
 
Hola, no funciona, al hacer esto:

PHP:
while(1)
{
    long data;
    long comando;
    long direccion;

    data = decodifica_RC5();

    comando = data;
    direccion = data;

    comando = comando & 0x007F;
    
    direccion = direccion & 0x83F;
}

tanto, en comando, como en direccion, obtengo lo mismo, el comando, código de la tecla pulsada del control.
 
Hola, gracias por contestar, lo estoy haciendo asi, solo para probar e intentar sacar un solo dato a la vez, como te dije estoy intentando entender lo que hacia la linea que te menciono en mi primer mensaje.

En si, el tema de que funcione el código esta resuelto, ahora tengo tanto, el bit de toggle, como los de direccion y comando, probado con tres controles distintos, y todos los códigos corresponden, tal vez no sea la mejor forma de hacerlo, pero como te dije, mi objetivo era enteder como se hacia y estoy en eso.

Código:
            data = decodifica_RC5();

            toggle = data & 0x0800;
            toggle = toggle >> 11;
            
            direccion = data & 0x07C0;
            direccion = direccion >> 6;
            
            comando = data & 0x003F;

La verdad me da pena hacer preguntas que para la mayoria seran tontas, asi que procurare no hacerlo hasta leer y tratar de comprender las cosas un poco.

Gracias por tu tiempo.
 
Última edición:
No hay drama hay mil formas de hacer lo que necesitas pero todo depende del conocimiento de programación que tengas. Ahora tu forma de hacerlo es muy elegante pero quizas se pueda hacer más en menos lineas de código....como te dije es cuestion de ver como a uno le es mas facil hacer las cosas.
 
hola me gustaria saber si pudieron mejorar el codigo para que decodificara la trama que recibe del control, tengo un proyecto que es controlado por el control remoto, pero no he podido hacer que el pic responda al enviar la señal desde el control, talves me puedan ayudar, desde ya muchas gracias, espero su pronta respuesta
 
Primero que nada el control que tenés que usar para poder armar este proyecto es del tipo RC5, esclusivamente funciona con ese formato. Ahora lo que estoy viendo es de un código de aprendizaje para que funcione con otros controles remotos ...pero no está entre mis planes inmediatos.
 
Hola, te hago una pregunta...
estuve mirando tu codigo y queria saber si sabias como puedo comenzar mi programa pero para hacerlo con un micro jl3 de motorola. la idea es controlar el volumen y el encendido de un amplificador de sonido.
Ya estuve midiendo la señal que envia el control, y la señal que recepciona el receptor que estoy usando. aparentemente es la enbolvente de el codigo manchester y hasta ahora, lo que he hecho del programa es crear un retardo en los dos primeros bits para no leerlos ya que siempre son iguales y ahora lo que pienso hacer es leer el estado de cada bit una vez. El problema es que no se como arrancar a escribir el software... si me podrias ayudar te lo agradeceria mucho. saludos!
 
el codigo manchester es el que rige en la norma rc5, por eso te preguntaba como habias iniciado tu programa... leyendo la señal embolvente o como? eso es lo que te queria preguntar!
 
El programa lo hice filtrando la trama ...es decir fui mirando bit por bit pero para no hacerlo de manera continua puse este código:
Código:
for(i=0;i<13;i++)       // Recoje los 13 bits de datos y los guarda...
      {
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D1=D1*2+input(IR_RECEPTOR);   // lee los datos...
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D0=D0*2+input(IR_RECEPTOR);   // lee los datos pero invertidos...
         
      }

Entonces leo la trama completa ....luego leo la trama invertida....luego hago la operacion XOR para comparar igualdad y por ultimo con multiples operaciones AND voy filtrando los datos....no me base en el protocolo manchester.
 
amigo te hago una pregunta porque no estoy muy familiarizado con el codewarrior. de donde tomas los datos que van del receptor al micro?
yo pensaba tomarlos desde algun puerto, y de ahi comenzar todo el ciclo de comandos para leer el dato y despues voy a interpretarlo. seria asi:

include 'jl3regs.inc'
org direccion
org comando

brclr 3,pta,borra 11
bra salta 11
brset 3,pta, comando
 
hola Moyano gracias por compartir la informacion la checare para ver si me sale algun proyectillo no he manejado controles de tv con pic Me viene de perlas tu aporte. (y)
 
Atrás
Arriba