Autor Tema: Leer mando JVC  (Leído 2308 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Leer mando JVC
« en: 30 de Marzo de 2009, 16:05:18 »
No se si este codigo es correcto, creo que si pero no me funciona.

Se trata de leer un mando a distancia JVC, el protocolo es este: http://www.sbprojects.com/knowledge/ir/jvc.htm

Y mi programa es este:

Código: [Seleccionar]
#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPROTECT

#byte PORTA                = 0x05
#byte PORTB                = 0x06

#bit  GRABAR       = PORTA.0
#bit  LED          = PORTA.1

#define REC_IR PIN_B0
#bit  SALIDA_1     = PORTB.1
#bit  SALIDA_2     = PORTB.2
#bit  SALIDA_3     = PORTB.3
#bit  SALIDA_4     = PORTB.4
#define ON          1
#define OFF         0
#define N_TECLAS    4
int1 bit;
int i, nbit,data[3],state;
int EstadoProceso;
int LecturaTemporal[3];
//****************************************************************************//
void AlmacenaTecla(void){
int cont,Direccion;
restart_wdt();
if(EstadoProceso%2==1){//Paso impar.
   //Captura de tecla.
   LecturaTemporal[0]=data[0];
   LecturaTemporal[1]=data[1];
   LecturaTemporal[2]=data[2];
   EstadoProceso++;
   PitidoCorto();//Indica tecla leida.Da un destello corto a un led
}else{//Paso par.
   //Comprobacion de tecla.
   if((LecturaTemporal[0]==data[0])&&
      (LecturaTemporal[1]==data[1])&&
      (LecturaTemporal[2]==data[2])){
   //Tecla correcta.
   Direccion=EstadoProceso*2-4;
   write_eeprom(Direccion,data[0]);
   write_eeprom(Direccion+1,data[1]);
   write_eeprom(Direccion+2,data[2]);
   EstadoProceso++;
   PitidoLargo();//Indica tecla almacenada correctamente.
   }else{//Comprobacion fallida.
   EstadoProceso--;
   LecturaTemporal[0]=0;
   for(cont=0;cont<4;cont++){//Indica fallo de lectura, se repite esa tecla.
       PitidoCorto();//Da un destello corto a un led
       Delay_ms(200);
   }
   }
}
if( EstadoProceso== (N_TECLAS*2+1) ){//teclas grabadas correctamente.
      LeerCodigosMando();
      EstadoProceso=1;
      for(cont=0;cont<4;cont++){//Indica fin de teclas almacenadas.
         PitidoLargo();//Da un destello largo a un led
         Delay_ms(200);
      }
      Delay_ms(400);
}
}
//****************************************************************************//
void main(){

set_tris_a(0b11111101);
set_tris_b(0b11100001);
EstadoProceso=1;

while(1){
data[0]=0;
data[1]=0;
data[2]=0;
state=0;
nbit=0;
i=0;

while(input(REC_IR)==1);       // Espera al 1er bit de START (flanco de bajada)
delay_us(8400);//Saltamos el
delay_us(4200);//bit de inicio.
delay_us(263);//Nos situamos a la mitad del primer nivel del primer bit.
while((nbit++ != 16) && (state == 0)){
   // 8 bits DIR + 8 bits COMANDO.
   // nbit varía de 0 a 15 = 16 bits
   if(input(REC_IR)==0){//Todos los bit empizan por 0 (invertido).
      delay_us (526);//Sobrepasamos la mitad del primer nivel.
      if(input(REC_IR) != 1)//Si no es un 1, no es codigo Samsumg.
            state=1;
      delay_us (526);//Si sigue siendo un 1, es un 1, sino es un 0.
      if(input(REC_IR)==0){
            bit=0;//Es un cero.
      }else{
            bit=1;//Es un uno
            delay_us(1048);//Sobrepasamos el nivel alto (invertido) del 1.
            if(input(REC_IR) != 0)
                  state=1;
      }
   }else{
        state=1;//No es codigo JVC.
   }
   shift_left(data,2,bit);//  2·8=16bits, bit=0 ó 1
}
   if(state){//Error.
         /*lcd_gotoxy(1,1);//fila 1, col 1
         printf(lcd_putc,"Error           ");*/
   }else{//Dato correcto.
         if(!GRABAR)//Jumper de programacion de teclas.
            AlmacenaTecla();
         else
            ProcesaTecla();
   }
   Delay_ms(200);
}
}


Al pulsar una tecla del mando, el led deberia dar un destello, pero no lo hace. Con el codigo de PHILIPS RC5 hice un programa similar y funcionaba, la funcion Almacenatecla es la misma.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Leer mando JVC
« Respuesta #1 en: 01 de Abril de 2009, 19:25:27 »
La parte que lee la trama de datos es esta:

Código: [Seleccionar]
while(input(REC_IR)==1);       // Espera al 1er bit de START (flanco de bajada)
delay_us(8400);//Saltamos el
delay_us(4200);//bit de inicio.
delay_us(263);//Nos situamos a la mitad del primer nivel del primer bit.
while((nbit++ != 16) && (state == 0)){
   // 8 bits DIR + 8 bits COMANDO.
   // nbit varía de 0 a 15 = 16 bits
   if(input(REC_IR)==0){//Todos los bit empizan por 0 (invertido).
      delay_us (526);//Sobrepasamos la mitad del primer nivel.
      if(input(REC_IR) != 1)//Si no es un 1, no es codigo Samsumg.
            state=1;
      delay_us (526);//Si sigue siendo un 1, es un 1, sino es un 0.
      if(input(REC_IR)==0){
            bit=0;//Es un cero.
      }else{
            bit=1;//Es un uno
            delay_us(1048);//Sobrepasamos el nivel alto (invertido) del 1.
            if(input(REC_IR) != 0)
                  state=1;
      }
   }else{
        state=1;//No es codigo JVC.
   }
   shift_left(data,2,bit);//  2·8=16bits, bit=0 ó 1
}

Sucede que si acorto el numero de bits a 10, me funciona el programa con algunas teclas del mando.

No encuentro forma de ver la trama que me envia el mando, en el osciloscopio analogico que tengo no se ve bien, y no tengo un analizador logico.

Estoy usando un mando universal, quizas la trama no sea igual a la original...

Un saludo.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Leer mando JVC
« Respuesta #2 en: 02 de Abril de 2009, 02:46:19 »
Yo no lo haría con delays, porque si la tabla de tiempos no coincide exactamente, vas arrastrando error bit tras bit y puede que al final te encuentres con algún problema.
Creo que lo ideal es utilizar la interrupción externa en combinación con el timer para saber el tiempo que transcurre entre un flanco ascendente y el siguiente (o descendente, si tu receptor es de lógica inversa).
De esta manera, el bit de start será identificado porque el siguiente flanco llegará después de 12,6ms; el bit 0 después de 1,05ms y el bit 1 después de 2,1ms por lo que el código de tu interrupción externa quedaría sencillito:

if (TiempoTranscurrido<1200) // se ha recibido un 0
    Trama<<1;
else if (TiempoTranscurrido<3000) // se ha recibido un 1
    Trama=Trama<<1 + 1;
else Trama=0;  // comienzo de recepción


Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Leer mando JVC
« Respuesta #3 en: 02 de Abril de 2009, 16:49:35 »
Efectivamente es un problema de retardos arrastrados. He probado a reducir un poco los delay, y funciona correctamente, pero tengo que probar de la manera que me has comentado, es mucho mejor.

Muchas gracias por la ayuda Nocturno. Cuando tenga funcionando con la interrupcion lo comento.

Un saludo.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Leer mando JVC
« Respuesta #4 en: 03 de Abril de 2009, 10:09:02 »
Codigo de Nocturno funcionando  :-/ :-/

La rutina de interrupción queda así:

Código: [Seleccionar]
#INT_EXT
void Leer_Trama(void){

TiempoTranscurrido=GET_TIMER0();
SET_TIMER0(0x00);

if (TiempoTranscurrido<TIEMPO_CERO) // se ha recibido un 0
    shift_left(data,2,0);
else if (TiempoTranscurrido<TIEMPO_UNO) // se ha recibido un 1
    shift_left(data,2,1);
else { data[0]=0;data[1]=0;data[2]=0; } // comienzo de recepción

cont++;
}

Y la parte de codigo para saber cuando terminamos de leer:

Código: [Seleccionar]
   while(input(REC_IR)==1);
   cont=0;
   SET_TIMER0(0x00);
   enable_interrupts(INT_EXT);
   ext_int_edge(H_TO_L);
   enable_interrupts(GLOBAL);
   while(cont!=N_BIT+1);
   disable_interrupts(GLOBAL);

Un saludo.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Leer mando JVC
« Respuesta #5 en: 03 de Abril de 2009, 15:01:47 »
!Guay!

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Leer mando JVC
« Respuesta #6 en: 16 de Mayo de 2009, 19:48:39 »
Ahora trato de hacer lo mismo con el protocolo RC5 de PHILIPS, es decir por interrupcion. Es diferente porque los bit '0' o '1' tienen la misma duracion:

http://www.sbprojects.com/knowledge/ir/rc5.htm

Tengo la siguiente interrupcion para leer una trama del mando:

Código: [Seleccionar]
//****************************************************************************//
#INT_EXT
void Leer_Trama(void){
int bit;

   TiempoTranscurrido=GET_TIMER1();
   SET_TIMER1(0x0000);
   if(TiempoTranscurrido<MEDIO_BIT){
      FlancoParImpar++;
      if(FlancoParImpar%2==0){//Si el tiempo es de medio bit, tenemos dos '0'o
      //dos '1' seguidos, se salta el primer flanco para situarse en medio del
      //bit para poder determinar si es un '0' o un '1'.
            if(FlancoSubidaBajada==Subida)//es un cero(invertido por receptor IR)
               bit=0;
            else
               bit=1;
            shift_left(data,2,bit);
            ContadorBitsLeidos++;
      }
   }else if(TiempoTranscurrido<UN_BIT){
            if(FlancoSubidaBajada==Subida)//es un cero(invertido por receptor IR)
               bit=0;
            else
               bit=1;
            shift_left(data,2,bit);
            ContadorBitsLeidos++;     
   }
if(FlancoSubidaBajada==Subida){
      FlancoSubidaBajada=Bajada;
      ext_int_edge(H_TO_L);
}else{
      FlancoSubidaBajada=Subida;
      ext_int_edge(L_TO_H);
}
}
//****************************************************************************//

Y la inicializacion del main:

Código: [Seleccionar]
void main(){

set_tris_a(0b11111101);
set_tris_b(0b11100001);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64);
SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_1);
EstadoProceso=1;
LED=OFF;
LeerCodigosMando();

while(1){

   while(input(REC_IR)==1);
   cont=0;
   data[0]=0;data[1]=0;data[2]=0;
   FlancoParImpar=2;//inicio en par.
   SET_TIMER1(0x0000);
   FlancoSubidaBajada=Subida;
   enable_interrupts(INT_EXT);
   ext_int_edge(L_TO_H);
   enable_interrupts(GLOBAL);
   ContadorBitsLeidos=0;
   while(contadorBitsLeidos!=N_BIT);
   disable_interrupts(GLOBAL);
   
   data[1]=data[1]&0b00000111;//Se ignoran bits de inicializacion.
   if(!GRABAR)
       AlmacenaTecla();
   else
       ProcesaTecla();
}
}

Para grabar una tecla hago dos lecturas de la tecla pulsada, osea se pasa dos veces por la funcion AlmacenaTecla();, la primera pasada la hace, pero en la segunda me da una lectura erronea. He dado mil vueltas pero no encuentro el error. Sospecho que el error está en el codigo que he puesto, pues el resto del codigo funciona con la lectura inicial que usaba con delays en lugar de con interrupciones.

Un saludo.
« Última modificación: 16 de Mayo de 2009, 19:54:34 por micro_pepe »
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado hecgifo

  • PIC10
  • *
  • Mensajes: 1
Re: Leer mando JVC
« Respuesta #7 en: 03 de Mayo de 2013, 18:07:39 »
HOLA micro pepe estoy investigando sobre controles jvc podrias colocar el codigo completo del  JVC para poderlo estudiar

gracias