<< Hackeando un control remoto infrarrojo >>



Hace unos días me llego este control infrarrojo, y les enseñaré a usarlo.
Antes deben de saber que cada control remoto trabaja en una frecuencia de portadora distinta, las frecuencias estándares son: 30 kHz, 33 kHz, 36 kHz, 38 kHz, 40 kHz, y 56 kHz. Ademas hay distintos tipos de codificación, como también diferente numero de bits, con diferentes longitudes, etc.
Este control remoto trabaja a una frecuencia de portadora igual a 38 kHz y utiliza el codigo NEC, y la trama de este código está compuesto de la siguiente forma:
Hay que tener en cuenta que el sensor infrarrojo por defecto tiene una señal de salida igual a un "1" Lógico, entonces la señal que le llega al microcontrolador es la señal conmutada de la imagen de arriba.
PD: Address code con una raya encima significa que son los mismos bits de Address code con la diferencia que está todo negado, o sea, si Address code es: 11001100, entonces Address code negado será: 00110011

Para diferenciar si el dato que me ha llegado es un "1" o "0":
En este protocolo el LSB se transmite el primero. Un mensaje se inicia con un pulso de 9 ms que va seguido de un espacio de 4.5 ms y, tras estos 13.5 ms, se transmite el mensaje.

Mas información: Aquí

Usaré un dsPIC30F3014 para este ejemplo, y lo programaré en MPLAB IDE v8.87




A continuación el código:

#include "p30fxxxx.h"
#include "LCD.h"
#include "libpic30.h"
#include "UART.h"

//Macros para la configuración de los fusibles
   _FOSC(CSW_FSCM_OFF & XT_PLL4);
   _FWDT(WDT_OFF);              
   _FBORPOR(PBOR_OFF & PWRT_16 & MCLR_EN);                          
   _FGS(CODE_PROT_OFF);        

#define LIMEN_1_12MS 1250 //1.00ms/0.8us
#define LIMAS_1_12MS 1625 //1.30ms/0.8us
#define LIMEN_2_25MS 2500 //2.00ms/0.8us
#define LIMAS_2_25MS 3000 //2.40ms/0.8us

unsigned char listo = 0;
typedef union{
   struct{
      unsigned char bit0: 1;
      unsigned char bit1: 1;
      unsigned char bit2: 1;
      unsigned char bit3: 1;
      unsigned char bit4: 1;
      unsigned char bit5: 1;
      unsigned char bit6: 1;
      unsigned char bit7: 1;
   }_Bits;
   unsigned char dato_TV;
}SONY;
SONY dato_rx, cod_error;
unsigned int val_cap,aux;
unsigned char vez = 0;   

void main()
{
   PORTD = 0;
   PORTB = 0;
   TRISD = 0x0100;   //RD8 entrada
   TRISB = 0x0000;
   IPC0  = IPC0 | 0x0010; //Nivel de prioridad = 1
   IEC0bits.IC1IE = 1;    //Interrupción Input Capture ON
   PR2   = 0xFFFF;         //Máximo nivel de conteo para el TMR2. Entonces el TMR2 se vuelve
                     //Free-running   
   T2CON  = 0x8010;       //TMR2 ON, Prescaler = 8 = 8*0.1useg = 0.8 useg
   IC1CON = 0x0083;       //Input Capture 1, selección TMR2, captura flancos de bajada   
   __delay_ms(15);
   LCD_CONFIG();   
   ESCRIBE_MENSAJE("Pulse una tecla",15);
   cod_error.dato_TV = 0;
   dato_rx.dato_TV = 0;
   INICIO_UART1(_9600);
   while(1)
   {
   if(listo == 1)
      {
         BORRAR_LCD();
         listo = 0;
         if(cod_error.dato_TV == 0x00)
         {
            ESCRIBE_CHAR(dato_rx.dato_TV+'0');
            LATB = dato_rx.dato_TV;
         }
         else
         ESCRIBE_MENSAJE("ERROR",5);
         dato_rx.dato_TV = 0;
         cod_error.dato_TV = 0;
         IC1CON = 0x0083;
      }
   }
}

void __attribute__((__interrupt__)) _IC1Interrupt(void){
val_cap=IC1BUF;
TMR2  = 0;
switch(vez)
{
   case 18:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)        dato_rx._Bits.bit0 = 1;
      else if(val_cap>= LIMEN_1_12MS && val_cap<LIMAS_1_12MS) dato_rx._Bits.bit0 = 0;
      else                                               {cod_error._Bits.bit0 = 1;}
   break;
   case 19:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)       dato_rx._Bits.bit1 = 1;
      else if(val_cap>=LIMEN_1_12MS && val_cap<LIMAS_1_12MS)  dato_rx._Bits.bit1 = 0;
      else                                               {cod_error._Bits.bit1 = 1;}
   break;
   case 20:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)       dato_rx._Bits.bit2 = 1;
      else if(val_cap>=LIMEN_1_12MS && val_cap<LIMAS_1_12MS)  dato_rx._Bits.bit2 = 0;
      else                                               {cod_error._Bits.bit2 = 1;}
   break;
   case 21:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)       dato_rx._Bits.bit3 = 1;
      else if(val_cap>=LIMEN_1_12MS && val_cap<LIMAS_1_12MS)  dato_rx._Bits.bit3 = 0;
      else                                               {cod_error._Bits.bit3 = 1;}
   break;
   case 22:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)       dato_rx._Bits.bit4 = 1;
      else if(val_cap>=LIMEN_1_12MS && val_cap<LIMAS_1_12MS)  dato_rx._Bits.bit4 = 0;
      else                                               {cod_error._Bits.bit4 = 1;}
   break;
   case 23:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)       dato_rx._Bits.bit5 = 1;
      else if(val_cap>=LIMEN_1_12MS && val_cap<LIMAS_1_12MS)  dato_rx._Bits.bit5 = 0;
      else                                               {cod_error._Bits.bit5 = 1;}
   break;
   case 24:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)       dato_rx._Bits.bit6 = 1;
      else if(val_cap>=LIMEN_1_12MS && val_cap<LIMAS_1_12MS)  dato_rx._Bits.bit6 = 0;
      else                                               {cod_error._Bits.bit6 = 1;}
   case 25:
      if(val_cap>=LIMEN_2_25MS && val_cap<LIMAS_2_25MS)       dato_rx._Bits.bit7 = 1;
      else if(val_cap>=LIMEN_1_12MS && val_cap<LIMAS_1_12MS)  dato_rx._Bits.bit7 = 0;
      else                                               {cod_error._Bits.bit7 = 1;}
   default:
   break;
}
vez++;
if(vez == 33)
{
   vez = 0;
   listo = 1;IC1CON = 0x0000;__delay_ms(300);
}
IFS0bits.IC1IF = 0;
}

PD: Nosotros tomaremos los 8 bits de dato y lo mostraremos por unos leds que están en el puerto B, recordar que estos por defecto son pines analogos
Share on Google Plus

About Unknown

    Blogger Comment
    Facebook Comment