| |
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 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
Datasheet PDF 94
Kbytes)
|
|

|
|
 |
- 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.
|
|
|
|

|
|
|
- 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.
|
|
|
|

|
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.
|
|
|
#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 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];
}
}
}
}
|
|
|
| |
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);
}
|
|
| |
|
|

| |
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.
|
|
|

|
|
|

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