PicManía by RedRaven
 

Búsqueda personalizada

 

EXPERIMENTOS : INFRARROJOS

 
  Esta es una sección especial de nuestros Experimentos, dedicada en exclusiva a trabajar con los Infrarrojos (IR), tanto emitiendo como recibiendo señales mediante este tipo de onda luminosa.


Recibiendo tramas y preguntándonos : ¿Esto qué es lo que es?
 
  • Lo primero y evidente es que para hacer experimentos con los IR necesitamos algo que emita IR y algo que los reciba. En uno de ellos, o en ambos, vamos a colocar nuestro PIC y a ver con qué nos encontramos.


 

  • En este primer experimento IR vamos a utilizar como emisor un mando viejo de vídeo o televisión, como cualquiera de los que se esconden en el fondo de algún oscuro cajón. Es el momento de revivirlo y darle nuevo uso .... imagino que cualquiera que funcione emitiendo vale.


 

  • En mi caso voy a utilizar para Emitir un mando SONY Dual Mode Shuttle Commander RMT-V104B, un verdadero armatoste antediluviano, grande como un ladrillo y cuyos botones hace tiempo que perdieron los textos que los alumbraban.


 

  • Y para Recibir vamos a tirar de un TSOP1738 que es una pequeña maravilla, ya que extrae la modulación de datos de la portadora de 38Khz, de ahí el 38 de su nomenclatura, y por una única patilla nos brinda los datos, en serie y con modulación por ancho de pulso. (Aquí tenéis su


     

  • Como podemos ver, el conectar el TSOP al PIC es un juego de chiquillos. Dos hilos para alimentación, 5V y GND, y un hilo para conectarlo a un pin de entrada del PIC, a ser posible a un pin que disponga de la función de Interrupción Externa. Yo la he conectado al RB0 del PORTB. No hace falta hardware añadido alguno.
  • Y qué mejor para monitorizar los datos que reciba que nuestro anterior proyecto del Analizador Lógico. Le he configurado únicamente el Canal 1 como disparo y en Flanco de Bajada y ...


 

  • Allí podíamos leer que la modulación de este protocolo codificaba los "1" lógicos con un pulso de unos 1.2 mS de duración y los "0" con una duración de aproximadamente la mitad, 600 uS, separados unos de otros por 600 uS:


 

  • Y que la interpretación de los 12 bits de que se compone cada emisión es como sigue:


 

  • A continuación me he ido al Analizador Lógico y con el mando he pulsado sobre la tecla +Prog, estos son los resultados utilizando además la Herramienta Medir del Software:


 

  • Si ahora pulsamos la tecla -Prog el cronograma es:


 

  • Y como podemos ver es absolutamente compatible con lo visto allá y que se corresponde exactamente con los comandos 16 y 17 enviados a la dirección 11.
 

 


Decodificando un protocolo y obteniendo direcciones y comandos.
 
  • Debemos empezar por describir el protocolo que deseamos decodificar. En mi caso, al enfrentarme a un nuevo protocolo, en principio desconocido, lo que hago es colgarle el TSOP1738 al Analizador Lógico. Con él obtengo una serie de cronogramas que voy comparando con la información sobre protocolos de la que dispongo y mas pronto que tarde logro encontrar al que corresponde.

  • Alternativamente un buen método de rastrear un protocolo consiste en hacer un programa para el PIC que registre sucesivamente los tiempos que separan dos flancos de bajada correlativos. Yo lo he realizado utilizando las interrupción externa de RB0 y guardando los valores de TIMER0 cada vez que llegaba un flanco de este tipo. Al registrar una serie suficientemente larga de ellos, entre 25 y 35 pulsos consecutivos, transmitía vía RS232 los valores de TIMER0 recogidos al PC y los veía sobre un Monitor Serie estilo HyperTerminal o Siow.

    De un simple vistazo a los valores recibidos se puede deducir la estructura de los datos recogidos.

  • Una vez identificado el protocolo del que se trata podremos encarar la realización del software que lo interpreta. En el ejemplo que os brindo a continuación se trata del protocolo NEC-32 que lleva embebido el mando ANSONIC SDG-20H de mi decodificador de Televisión Digital Terrestre.


 

Fundamentos del Protocolo NEC-32:
 
  • Longitud de 8 bits de dirección y 8 bits de comando.
  • Tanto la dirección como el comando son enviados dos veces a modo de CRC.
  • La primera vez 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 TSOP1738).
  • La longitud de un Bit "0" es de 1.12ms y la de un "1" es de 2.25ms.
  • En total de transmiten un bit de Start de 9ms+4.5ms=13.5ms mas 32 bits de datos.

 


 


 

Desarrollo del software de decodificación:
 
  • Con el fin de mostrar claramente el funcionamiento de nuestro decodificador vamos a recoger los distintos bits uno a uno y guardarlos en una tabla de bits, posteriormente los trataremos para componer los bytes correspondientes.

    La tabla de bits es char sbits[32] y la inicializamos (limpiamos) con '\0'. Cuando los hayamos recibidos todos los acumularemos sobre bytes[4] que son los valores a recoger.
     

  • Todo el software gira en torno a la Interrupción externa por RB0, que es donde recogemos los distintos Bits. En #int_ext podemos distinguir tres bloques distintos:
     

#int_ext
void ext_isr() {

   // Obtengo datos de Timer0
   tt = get_timer0();
   t = tt-tti;
   tti= tt;

   // Si he recibido el Start Bit puedo guardar
   if(start_recived==1){
      // Bit "0"
      if(t>40 && t<50){ sbits[ntbits]='0'; }
      // Bit "1"
      if(t>85 && t<90){ sbits[ntbits]='1'; }
      // Si he recibido 32 bits entonces hay dato
      if(++ntbits==total_bits){
         hay_dato=1;
      }
   }

   // Detecto Start Bit
   if(t>525 && t<530){
      start_recived=1;
      limpia_bits();
   }
}
 

  • Para recoger cada bit, o mejor dicho el ancho de cada bit que es lo que nos interesa, lo que hacemos es guardar la diferencia entre el estado del TIMER0 en cada interrupción y el valor que tenía en la interrupción anterior. Esto es lo que hacemos en la primera parte donde el valor de t alcanza el valor de dicha diferencia.
  • Para comenzar a recoger los 32 bits correspondientes a los cuatro bytes de dirección y comando debemos esperar a recibir el bit de Start, a partir del cual comenzaremos a acumular valores de bits en sbits[x].
     

  • Para un Cristal de 20 Mhz y un Preescaler  de TIMER0 de RTCC_DIV_128 el bit de Start son unos 525 Ticks de TIMER0, así que solo tras haber recibido un bit de una amplitud aproximada, entre 525 y 530 ticks de ancho, habilitaremos la recepción de los demás mediante la variable de tipo flag start_recived.

  • Para un Cristal de 20 Mhz y un Preescaler  de TIMER0 de RTCC_DIV_128 un bit "0" son unos 44 Ticks de TIMER0, así que guardamos un '0' si recibimos un bit de una amplitud aproximada de entre 40 y 50 ticks de ancho, y como un bit "1" son unos 88 Ticks de TIMER0 guardamos un '1' si recibimos un bit de una amplitud de entre 85 y 90 ticks de ancho.

  • Una vez recogidos los 32 bits podemos pasar a convertirlos en los correspondientes 4 bytes de dirección y comando (recordad que el primer byte es la dirección, el segundo es la misma dirección pero con todos los bits "invertidos", el tercero es el comando y el cuarto y último es el comando "invertido")

int bits[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void convierte_bits_a_bytes(void){

  for(i=0;i<4;++i){
    Bytes[i]=0x00;
    for(j=0;j<8;++j){
      if(sbits[(i*8)+j]=='1'){
        bytes[i]=bytes[i]|Bits[j];
      }
    }
  }
}
 

  • Todo lo demás de programa es "paja" ... o sea habilitar que todo esto sea posible.

  ir_capture  
  // ir_capture ANSONIC SDG-20H (TDT) with NEC-32 Protocol
//

#include <18f4550.h>
#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN,NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)


const char Version[]="1.0.H\0";

const int total_bits=32;
const int total_bytes=4;

char sbits[total_bits];
int1 first_ext=0;
int1 start_recived=0;
int i,j,k;
long tt,tti,t;
int ntbits=0;
int1 hay_dato=0;
char sbit1;
int bits[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int bytes[total_bytes]={0x00,0x00,0x00,0x00};

void limpia_bits(void);

// INTERRUPCION por RECEPCION SERIE -------------------------------------------

#int_rda
void serial_isr() {
  if(kbhit()){
    putchar(getc());
  }
}

// INTERRUPCION EXT por RB0 --------------------------------------------------

#int_ext
void ext_isr() {

  // Obtengo datos de Timer0
  tt = get_timer0();
  t = tt-tti;
  tti= tt;

  // Si he recibido el Start Bit puedo guardar
  if(start_recived==1){
    // Bit "0"
    if(t>40 && t<50){ sbits[ntbits]='0'; }
    // Bit "1"
    if(t>85 && t<90){ sbits[ntbits]='1'; }
    // Si he recibido 32 bits entonces hay dato
    if(++ntbits==total_bits){
      hay_dato=1;
    }
  }

  // Detecto Start Bit
  if(t>525 && t<530){
    start_recived=1;
    limpia_bits();
  }
}

//-----------------------------------------------------------------------------

void flash_porte(void){

  for(i=0;i<3;i++){
    output_e(0x07);
    delay_ms(75);
    output_e(0x00);
    delay_ms(75);
  }
}

void limpia_bits(void){

  for(i=0;i<total_bits;++i){
    sbits[i]='\0';
  }
  ntbits=0;
}

void convierte_bits_a_bytes(void){

  for(i=0;i<4;++i){
    Bytes[i]=0x00;
    for(j=0;j<8;++j){
      if(sbits[(i*8)+j]=='1'){
        bytes[i]=bytes[i]|Bits[j];
      }
    }
  }
}

void muestra_bits(void){

  printf("\r\nPULSO RECIBIDO -----------------------\r\n");

  for(i=0;i<4;++i){
    printf("Byte %u = ",i+1);
    for(k=0;k<2;++k){
      if(k==1){
        printf(" ",i+1);
      }
      for(j=0;j<8;++j){
        switch(k){
          case 0: printf("%2u ",(i*8)+j+1);
                  break;
          case 1: printf("%2c ",sbits[(i*8)+j]);
                  break;
        }
      }
      if(k==0){ printf("\r\n"); }
    }
    printf(" Valor = %u\r\n",Bytes[i]);
  }
  printf("Address = %u Command = %u\r\n",Bytes[0],Bytes[2]);

  ntbits=0;
}

void main() {

  disable_interrupts(global);
  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_OFF);
  setup_spi(FALSE);
  setup_psp(PSP_DISABLED);
  setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_timer_3(T3_DISABLED);
  setup_comparator(NC_NC_NC_NC);
  setup_vref(FALSE);
  port_b_pullups(FALSE);

  setup_timer_0(RTCC_INTERNAL | RTCC_DIV_128);

  set_tris_b(0b00000001);
  set_tris_c(0b10000000);
  set_tris_e(0b00010000);
  output_e(0x00);

  delay_ms(500);
  printf("\r\n");
  printf("[RRBOARD2] IR TSOP1738 Reader-Decoder version %s\r\n",version);
  printf("for ANSONIC SDG-20H (TDT) with NEC-32 Protocol\r\n\n");
  flash_porte();

  ext_int_edge(H_TO_L);
  first_ext=0;
  start_recived=0;
  hay_dato=0;

  limpia_bits();

  enable_interrupts(int_rda);
  enable_interrupts(int_ext);
  enable_interrupts(global);

  do {

    if(hay_dato==1){
       hay_dato=0;
       convierte_bits_a_bytes();
       muestra_bits();
       limpia_bits();
    }

  } while (TRUE);
}
   
 
 

 

 

 

 


 Procesador de comandos recibidos vía IR programable.
 
  • Basándome en todo lo escrito anteriormente he construido un programa que realiza una serie de funciones básicas como activar o desactivar unos pines del PIC o incrementar o decrementar cierto valor. Lo bonito de este programa es que los comandos para realizar estas funciones pueden enviarse al PIC vía RS232 como en tantos de mis ejemplos anteriores ... Pero además pueden enviarse vía IR utilizando el mando del televisor.

  • El rollo estaba en que para realizarlo había antes que leer los comandos que dicho mando IR envía con las teclas que nos interesaban y después programar nuestro programa para que las recibiese y aceptase en cada caso. Pero esta forma de hacerla no es elegante.

  • Lo elegante y bonito es que el programa fuese capaz de leer comandos y asignarlos a cada función, guardándolos en la EEPROM durante lo que podríamos llamar como fase de aprendizaje o memorización.

  • A partir de ahí tendríamos guardados los comandos asignados a cada función y que podrían ser cambiados en cualquier momento con solo reprogramar los comandos de nuevo. Además para hacerlo elegante del todo debería haber una manera de hacer todo esto sin hacer uso de hardware accesorio alguno, ningún botón, ni software externo, nada de enviar un comando RS232 para entrar en modo programación.

  • Para ello decidí que iba a tener disponibles 5 segundos tras el reset para que si en ese lapso recibía cualquier comando IR entonces entraba automáticamente en modo programación. Si transcurrido ese lapso de tiempo no recibía nada entonces recargaba desde la EEPROM los comandos configurados anteriormente y santas pascuas. De cualquier forma le he dejado implementado el que cada ejecución que realiza lo monitoriza por la RS232 para que podamos seguir su funcionamiento.

  • Imagen de una programación completa tras un Reset:

 
  • Imagen de un funcionamiento normal fuera de la fase de programación:

 

 
ir_command.c
 
 
  // ir_command.c by Redpic
// ANSONIC SDG-20H (TDT) supporting NEC-32 Protocol
// With recording Command send function
// and automode programing on reset

#include <18f4550.h>
#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN,NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)

#define PIN_FUNC1 PIN_E0
#define PIN_FUNC2 PIN_E1
#define PIN_FUNC3 PIN_E2

#define PIN_LED PIN_E0

// CONSTANTES -

const char Version[]="1.0.H\0";

const int total_bits = 32;
const int total_bytes = 4;

const char COMANDO232_MENU = '?'; const char COMANDO232_TXT_MENU[] = "Muestra menu de opciones RS232.";
const char COMANDO232_MODO_PROG = 'p'; const char COMANDO232_TXT_MODO_PROG[] = "Entrar en modo Programación.";
const char COMANDO232_FUNC_ON = 'o'; const char COMANDO232_TXT_FUNC_ON[] = " * 1 Activa/Desactiva procesar Comandos IR.";
const char COMANDO232_FUNC_1 = '1'; const char COMANDO232_TXT_FUNC_1[] = " * 2 Ejecutar Función 1";
const char COMANDO232_FUNC_2 = '2'; const char COMANDO232_TXT_FUNC_2[] = " * 3 Ejecutar Función 2";
const char COMANDO232_FUNC_3 = '3'; const char COMANDO232_TXT_FUNC_3[] = " * 4 Ejecutar Función 3";
const char COMANDO232_FUNC_VEX = 'f'; const char COMANDO232_TXT_FUNC_VEX[] = " * 5 Ver Estado actual de funciones.";
const char COMANDO232_FUNC_VER = 'm'; const char COMANDO232_TXT_FUNC_VER[] = " * 6 Ver Comandos almacenados por función.";
const char COMANDO232_FUNC_RESET= 'r'; const char COMANDO232_TXT_FUNC_RESET[]= " * 7 Reset Hardware.";
const char COMANDO232_FUNC_PLUS = '+'; const char COMANDO232_TXT_FUNC_PLUS[] = " * 8 Incrementa valor Ref.";
const char COMANDO232_FUNC_Minus= '-'; const char COMANDO232_TXT_FUNC_MINUS[]= " * 9 Decrementa valor Ref.";

const int MODO_INACTIVO = 0; const char MODO_TXT_INACTIVO[] = "INACTIVO";
const int MODO_ACTIVO = 1; const char MODO_TXT_ACTIVO[] = "ACTIVO";
const int MODO_PROGRAMACION = 2; const char MODO_TXT_PROGRAMACION[] = "PROGRAMACIÓN";

const int RTCCS_AUTOPROG = 3;

// VARIABLES EN RAM -

// De recepción IR y generales --

int1 first_ext=0;
int1 start_recived=0;
int1 hay_dato=0;
int1 autoprog_enabled=0;
int1 flag_flash_led=0;
char sbits[total_bits];
int i,j,k;
long tt,tti,t;
int ntbits=0;
char sbit1;
int bits[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int bytes[total_bytes]={0x00,0x00,0x00,0x00};
int nrtcc=0;

// De Comandos y Funciones --

char rec232=0x00;
char opcion=0x00;
int Modo=MODO_INACTIVO;
int nextPROG=0;

int1 FUNC1=0;
int1 FUNC2=0;
int1 FUNC3=0;
int VALREF;

int ADDRESSDEV;
int COMANDODEV_FUNC_ON;
int COMANDODEV_FUNC_1;
int COMANDODEV_FUNC_2;
int COMANDODEV_FUNC_3;
int COMANDODEV_FUNC_VEX;
int COMANDODEV_FUNC_VER;
int COMANDODEV_FUNC_RESET;
int COMANDODEV_FUNC_PLUS;
int COMANDODEV_FUNC_MINUS;

// Prototipos de funciones --

void flash_led(int n);
void limpia_bits(void);
void convierte_bits_a_bytes(void);
void muestra_bits(void);
void lee_config_desde_EEPROM(void);
void programar_comandos(int funcion, int device_address, int device_command);
void presenta_menu(void);
void on_reset(void);

// INTERRUPCION por RECEPCION SERIE -

#int_rda
void serial_isr() {

rec232=0x00;
if(kbhit()){
rec232=getc();
if( rec232==COMANDO232_MENU ||
rec232==COMANDO232_MODO_PROG ||
rec232==COMANDO232_FUNC_ON ||
rec232==COMANDO232_FUNC_1 ||
rec232==COMANDO232_FUNC_2 ||
rec232==COMANDO232_FUNC_3 ||
rec232==COMANDO232_FUNC_PLUS ||
rec232==COMANDO232_FUNC_MINUS ||
rec232==COMANDO232_FUNC_RESET ||
rec232==COMANDO232_FUNC_VEX ||
rec232==COMANDO232_FUNC_VER){
opcion=rec232;
}
}
}

// INTERRUPCION EXT por RB0 --

#int_ext
void ext_isr() {
// Obtengo datos de Timer0
tt = get_timer0();
t = tt-tti;
tti= tt;
// Si he recibido el Start Bit puedo guardar
if(start_recived==1){
// Bit "0"
if(t>40 && t<50){ sbits[ntbits]='0'; }
// Bit "1"
if(t>85 && t<90){ sbits[ntbits]='1'; }
// Si he recibido 32 bits entonces hay dato
if(++ntbits==total_bits){
hay_dato=1;
}
}
// Detecto Start Bit
if(t>525 && t<530){
start_recived=1;
limpia_bits();
}
}


// INTERRUPCION RTCC por TIMER0 -

#int_rtcc
void rtcc_isr() {

if(autoprog_enabled){
++nrtcc;
printf(".");
flag_flash_led=1;
if(nrtcc==RTCCS_AUTOPROG){
autoprog_enabled=0;
printf("\r\nAutoprog disabled.\r\n");
}
}
}

//-

void flash_led(int n){

for(i=0;i<n-1;i++){
output_high(PIN_LED);
delay_ms(75);
output_low(PIN_LED);
delay_ms(75);
}
}

void limpia_bits(void){

for(i=0;i<total_bits;++i){
sbits[i]='\0';
}
ntbits=0;
}

void convierte_bits_a_bytes(void){

for(i=0;i<4;++i){
Bytes[i]=0x00;
for(j=0;j<8;++j){
if(sbits[(i*8)+j]=='1'){
bytes[i]=bytes[i]|Bits[j];
}
}
}
}

void muestra_bits(void){

printf("[COMANDO] %u\\%u\r\n",Bytes[0],Bytes[2]);
}

void lee_config_desde_EEPROM(void){

ADDRESSDEV = read_eeprom( 0); if(ADDRESSDEV ==0xFF){ADDRESSDEV=64;}
VALREF = read_eeprom( 1); if(VALREF ==0xFF){VALREF=127;}
COMANDODEV_FUNC_ON = read_eeprom( 2); if(COMANDODEV_FUNC_ON ==0xFF){COMANDODEV_FUNC_ON = 24;} // Btn ON/OFF
COMANDODEV_FUNC_1 = read_eeprom( 3); if(COMANDODEV_FUNC_1 ==0xFF){COMANDODEV_FUNC_1 = 26;} // Btn 1
COMANDODEV_FUNC_2 = read_eeprom( 4); if(COMANDODEV_FUNC_2 ==0xFF){COMANDODEV_FUNC_2 = 17;} // Btn 2
COMANDODEV_FUNC_3 = read_eeprom( 5); if(COMANDODEV_FUNC_3 ==0xFF){COMANDODEV_FUNC_3 = 9;} // Btn 3
COMANDODEV_FUNC_VEX = read_eeprom( 6); if(COMANDODEV_FUNC_VEX ==0xFF){COMANDODEV_FUNC_VEX = 7;} // Btn Ok
COMANDODEV_FUNC_VER = read_eeprom( 7); if(COMANDODEV_FUNC_VER ==0xFF){COMANDODEV_FUNC_VER = 25;} // Btn Menu
COMANDODEV_FUNC_RESET = read_eeprom( 8); if(COMANDODEV_FUNC_RESET==0xFF){COMANDODEV_FUNC_RESET= 3;} // Btn Exit
COMANDODEV_FUNC_PLUS = read_eeprom( 9); if(COMANDODEV_FUNC_PLUS ==0xFF){COMANDODEV_FUNC_PLUS= 13;} // Btn CH+
COMANDODEV_FUNC_MINUS = read_eeprom(10); if(COMANDODEV_FUNC_MINUS==0xFF){COMANDODEV_FUNC_MINUS= 30;} // Btn CH-

}

void programar_comandos(int funcion, int device_address, int device_command){

switch(funcion){
case 0:
printf("Modo PROGRAMACIÓN activado ...\r\n");
printf("Pulse cualquier botón para obtener el ADDRESS ");
flash_led(1);
break;
case 1:
printf("Address=%2u (0x%x)\r\n",device_address,device_address);
write_eeprom(0,device_address);
delay_ms(10);
printf("Pulse para [Activar/Desactivar] ");
flash_led(2);
break;
case 2:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(2,device_command);
delay_ms(10);
printf("Pulse para [Ejecutar Función 1] ");
flash_led(3);
break;
case 3:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(3,device_command);
delay_ms(10);
printf("Pulse para [Ejecutar Función 2] ");
flash_led(4);
break;
case 4:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(4,device_command);
delay_ms(10);
printf("Pulse para [Ejecutar Función 3] ");
flash_led(5);
break;
case 5:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(5,device_command);
delay_ms(10);
printf("Pulse para [Ver estado de funciones] ");
flash_led(6);
break;
case 6:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(6,device_command);
delay_ms(10);
printf("Pulse para [Ver comandos almacenados] ");
flash_led(7);
break;
case 7:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(7,device_command);
delay_ms(10);
printf("Pulse para [Reset Hardware] ");
flash_led(8);
break;
case 8:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(8,device_command);
delay_ms(10);
printf("Pulse para [Inc. Valor Ref.] ");
flash_led(9);
break;
case 9:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(9,device_command);
delay_ms(10);
printf("Pulse para [Dec. Valor Ref.] ");
flash_led(9);
break;
case 10:
printf("Command=%2u (0x%x)\r\n",device_command,device_command);
write_eeprom(10,device_command);
delay_ms(11);
// fin programación
printf("Fin Modo PROGRAMACION.\r\n");
on_reset();
break;
}
}

//-

void presenta_menu(void){

printf("Opciones Menu RS232:\r\n\n");
printf(" [%c] %s\r\n", COMANDO232_MENU, COMANDO232_TXT_MENU);
printf(" [%c] %s\r\n", COMANDO232_MODO_PROG, COMANDO232_TXT_MODO_PROG);
printf(" [%c] %s\r\n", COMANDO232_FUNC_ON, COMANDO232_TXT_FUNC_ON);
printf(" [%c] %s\r\n", COMANDO232_FUNC_1, COMANDO232_TXT_FUNC_1);
printf(" [%c] %s\r\n", COMANDO232_FUNC_2, COMANDO232_TXT_FUNC_2);
printf(" [%c] %s\r\n", COMANDO232_FUNC_3, COMANDO232_TXT_FUNC_3);
printf(" [%c] %s\r\n", COMANDO232_FUNC_VEX, COMANDO232_TXT_FUNC_VEX);
printf(" [%c] %s\r\n", COMANDO232_FUNC_VER, COMANDO232_TXT_FUNC_VER);
printf(" [%c] %s\r\n", COMANDO232_FUNC_RESET,COMANDO232_TXT_FUNC_RESET);
printf(" [%c] %s\r\n", COMANDO232_FUNC_PLUS, COMANDO232_TXT_FUNC_PLUS);
printf(" [%c] %s\r\n", COMANDO232_FUNC_MINUS,COMANDO232_TXT_FUNC_MINUS);
printf("\r\n");
}

void on_reset(void){

disable_interrupts(global);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_psp(PSP_DISABLED);
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
port_b_pullups(FALSE);

setup_timer_0(RTCC_INTERNAL | RTCC_DIV_128);

set_tris_b(0b00000001);
set_tris_c(0b10000000);
set_tris_e(0b00010000);
output_e(0x00);

delay_ms(500);
printf("\r\n");
printf("[RRBOARD2] IR Command Receiver version %s\r\n",version);
printf("TSOP1738 Reader-Decoder over 18F4550\r\n");
printf("for ANSONIC SDG-20H with NEC-32 Protocol\r\n\n");
flash_led(3);
presenta_menu();

ext_int_edge(H_TO_L);
first_ext=0;
start_recived=0;
hay_dato=0;

limpia_bits();


rec232=0x00;
opcion=0x00;
Modo=MODO_INACTIVO;
FUNC1=0;
FUNC2=0;
FUNC3=0;
nextPROG=0;
nrtcc=0;
flag_flash_led=0;
autoprog_enabled=1;

lee_config_desde_EEPROM();

delay_ms(500);
printf("Autoprog enabled ");

enable_interrupts(int_rda);
enable_interrupts(int_ext);
enable_interrupts(int_rtcc);
enable_interrupts(global);

}

void main() {

on_reset();
do {
// Recibe y procesa IR Command para generar 232 Command -
if(hay_dato==1){
hay_dato=0;
// Extrae byte recibido y limpia -
convierte_bits_a_bytes();
limpia_bits();
// Detecta cualquier pulsacion IR durante Autoprog_enabled -
if(Autoprog_enabled){
Autoprog_enabled=0;
Opcion=COMANDO232_MODO_PROG;
}else{
// Si no estamos en modo PROGRAMACION -
if(Modo!=MODO_PROGRAMACION){
muestra_bits();
// Si el Address es correcto ... -
if(Bytes[0]==ADDRESSDEV){
// Comando COMANDO232_FUNC_ON -
if(Bytes[2]==COMANDODEV_FUNC_ON){
opcion=COMANDO232_FUNC_ON;
}
// Comando FUNC1 --
if(Bytes[2]==COMANDODEV_FUNC_1){
opcion=COMANDO232_FUNC_1;
}
// Comando FUNC2 --
if(Bytes[2]==COMANDODEV_FUNC_2){
opcion=COMANDO232_FUNC_2;
}
// Comando FUNC3 --
if(Bytes[2]==COMANDODEV_FUNC_3){
opcion=COMANDO232_FUNC_3;
}
// Comando FUNC_VEX -
if(Bytes[2]==COMANDODEV_FUNC_VEX){
opcion=COMANDO232_FUNC_VEX;
}
// Comando FUNC_VER -
if(Bytes[2]==COMANDODEV_FUNC_VER){
opcion=COMANDO232_FUNC_VER;
}
// Comando FUNC_RESET -
if(Bytes[2]==COMANDODEV_FUNC_RESET){
opcion=COMANDO232_FUNC_RESET;
}
// Comando FUNC_PLUS --
if(Bytes[2]==COMANDODEV_FUNC_PLUS){
opcion=COMANDO232_FUNC_PLUS;
}
// Comando FUNC_MINUS --
if(Bytes[2]==COMANDODEV_FUNC_MINUS){
opcion=COMANDO232_FUNC_MINUS;
}
}
// Si estamos en Modo PROGRAMACION -
}else{
programar_comandos(++nextPROG,bytes[0],bytes[2]);
}
}
}
// Recibe y procesa RS232 Opcion
if(opcion!=0x00){
Switch(opcion){
// Muestra menu de opciones -
case COMANDO232_MENU:
presenta_menu();
break;
// Entrar en Modo PROGRAMACION --
case COMANDO232_MODO_PROG:
nextPROG=0;
Modo=MODO_PROGRAMACION;
programar_comandos(0,0,0);
break;
// Activa/Desactiva procesar Comandos FUNC --
case COMANDO232_FUNC_ON:
if(Modo==MODO_INACTIVO){
Modo=MODO_ACTIVO;
printf("Modo : Activada recepción de Comandos\r\n");
}else{
Modo=MODO_INACTIVO;
printf("Modo : Desactivada recepción de Comandos\r\n");
};
break;
// Reset de Hardware --
case COMANDO232_FUNC_RESET:
if(Modo==MODO_ACTIVO){
on_reset();
}else{
printf("**Error, Recibido RESET pero Modo=INACTIVO\r\n");
}
break;
// Ejecutar Función 1 -
case COMANDO232_FUNC_1:
if(Modo==MODO_ACTIVO){
FUNC1=!FUNC1;
if(FUNC1){
output_high(PIN_FUNC1);
printf("FUNC1 : Activada\r\n");
}else{
output_low(PIN_FUNC1);
printf("FUNC1 : Desactivada\r\n");
}
}else{
printf("**Error, Recibido F1 pero Modo=INACTIVO\r\n");
}
break;
// Ejecutar Función 2 -
case COMANDO232_FUNC_2:
if(Modo==MODO_ACTIVO){
FUNC2=!FUNC2;
if(FUNC2){
output_high(PIN_FUNC2);
printf("FUNC2 : Activada\r\n");
}else{
output_low(PIN_FUNC2);
printf("FUNC2 : Desactivada\r\n");
}
}else{
printf("**Error, Recibido F2 pero Modo=INACTIVO\r\n");
}
break;
// Ejecutar Función 3 -
case COMANDO232_FUNC_3:
if(Modo==MODO_ACTIVO){
FUNC3=!FUNC3;
if(FUNC3){
output_high(PIN_FUNC3);
printf("FUNC3 : Activada\r\n");
}else{
output_low(PIN_FUNC3);
printf("FUNC3 : Desactivada\r\n");
}
}else{
printf("**Error, Recibido F3 pero Modo=INACTIVO\r\n");
}
break;
// Ejecutar Plus --
case COMANDO232_FUNC_PLUS:
if(Modo==MODO_ACTIVO){
++VALREF;
write_eeprom(1,VALREF);
printf("V.Ref.=%u\r\n",VALREF);
}else{
printf("**Error, Recibido Inc. pero Modo=INACTIVO\r\n");
}
break;
// Ejecutar Minus -
case COMANDO232_FUNC_MINUS:
if(Modo==MODO_ACTIVO){
--VALREF;
write_eeprom(1,VALREF);
printf("V.Ref.=%u\r\n",VALREF);
}else{
printf("**Error, Recibido Dec. pero Modo=INACTIVO\r\n");
}
break;
// Ver Estado actual de funciones -
case COMANDO232_FUNC_VEX:
switch(Modo){
case MODO_PROGRAMACION:
printf("Estado = %s, ",MODO_TXT_PROGRAMACION);
break;
case MODO_INACTIVO:
printf("Estado = %s, ",MODO_TXT_INACTIVO);
break;
case MODO_ACTIVO:
printf("Estado = %s, ",MODO_TXT_ACTIVO);
break;
}
printf("V.Ref.=%u, ",VALREF);
if(FUNC1) printf("F1 = ON, "); else printf("F1 = OFF, ");
if(FUNC2) printf("F2 = ON, "); else printf("F2 = OFF, ");
if(FUNC1) printf("F3 = ON\r\n "); else printf("F3 = OFF\r\n");
break;

// Ver Comandos almacenados por función -
case COMANDO232_FUNC_VER:
printf("Address= %3u (0x%x)\r\n",ADDRESSDEV,ADDRESSDEV);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_ON, COMANDODEV_FUNC_ON, COMANDO232_TXT_FUNC_ON);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_1, COMANDODEV_FUNC_1, COMANDO232_TXT_FUNC_1);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_2, COMANDODEV_FUNC_2, COMANDO232_TXT_FUNC_2);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_3, COMANDODEV_FUNC_3, COMANDO232_TXT_FUNC_3);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_VEX, COMANDODEV_FUNC_VEX, COMANDO232_TXT_FUNC_VEX);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_VER, COMANDODEV_FUNC_VER, COMANDO232_TXT_FUNC_VER);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_RESET, COMANDODEV_FUNC_RESET, COMANDO232_TXT_FUNC_RESET);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_PLUS, COMANDODEV_FUNC_PLUS, COMANDO232_TXT_FUNC_PLUS);
printf("Command= %3u (0x%x) %s\r\n",COMANDODEV_FUNC_MINUS, COMANDODEV_FUNC_MINUS, COMANDO232_TXT_FUNC_MINUS);
break;
//-
}
opcion=0x00;
}
// Detecto FLASH LED --
if(flag_flash_led){
flag_flash_led=0;
flash_led(2);
}
} while (TRUE);
}
   
 
 

 

 

 

 


Cronogramas a descifrar.
 
  • Cronogramas de un par de teclas del mando infrarrojo del Aire Acondicionado de mi oficina.
  • Botón Naranja


 

  • Botón Reloj


 

 

Esta página se modificó el 27/12/2008


Esta página usa la letra Ñ

Nota pública importante sobre las consultas al Webmaster de PicManía.


Sugerencias a Picmanía... (que serán leídas pero seguramente no podrán ser contestadas)

Esta página pertenece al grupo de páginas de Diego RedRaven

 

 



Nota: Esta página Web esta repleta de imágenes, textos, logotipos y demás material extraídos de los mas variados medios de los que no soy ni autor ni depositario de los correspondientes derechos de autor, uso y/o reproducción. Si Ud. es depositario de dichos derechos y desea que el material correspondiente sea eliminado de esta Web no dude en ponerse en contacto conmigo mediante e-mail y será inmediatamente retirado. Gracias.
 
Visitas
Totales : 36392 Hoy: 5 Activas: 1 Vistas: 36392

Esta página fue modificada el 07-08-2010 22:42:19

           
 DmSoft WAMP Escribir Unreal