[Aporte] Programa para leer codigos de hasta 24 bits

#1
Gente en esta oportunidad les quiero dejar un programa sencillo que corriendolo a 4MHz con el oscilador interno de cualquier microcontrolador funciona de maravillas. El mismo realiza una rutina de escaneo, detección, determinación del tipo de encoder, decodificación de la trama recibida y almacenamiento del código recibido de una longitud de hasta 24 bits, pudiendose almacenar en la memoria eeprom de 256 byte un total de 85 códigos distintos. Este programa permite levanta cualquier código de un control remoto RF que utilice los siguientes encoders: PT2262, PT2264, PT2242, PT2240, SC2260, SC2262, HX2260, HX2262, HS2262, HS2260, AX5026, SMC918, SMC926, AX5326, RT1527, FP1527, FP527, HS1527, HX1527, HT600, HT680, HT6201, HT6010, HT6012, HT6014, HT6013, HT12A.
Con un simple receptor de RF de AM sirve para recibir los datos del control remoto siempre y cuando sean de la misma frecuencia.
Control.jpg Receptor RF.jpg

Código:
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES PUT                      //Power Up Timer
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=4000000)

// Definiciones del puerto A

#define Datos     PIN_A0

#use fast_io(A)

int i,Trama_encontrada,Contador_bits,Codigo[3],Auxiliar[3];
int Contador_codigos,Bien,Mal,Nuevo_codigo,Aux,Salto;
long Tiempo_entre_tramas,Aux_tiempo_entre_tramas;
long Tiempo_ET_delta_neg,Tiempo_ET_delta_pos,Tiempo_bits,Tiempo_bit,Bit,Tiempo;

void main()
{
   set_tris_a (0b11111111); // Entradas:A0,A1,A2,A3,A4,A5
   output_a (0);
   Salto = 0;
   setup_timer_1 (T1_INTERNAL|T1_DIV_BY_1); // Base de tiempo de 1 useg
   for (;;)
   {
   Tiempo_entre_tramas = 0;
   Trama_encontrada = false;
   Contador_bits = 0;
   Nuevo_codigo = 0;
   Contador_codigos = 0;
   Mal = 0;
   Bien = 0;
   for (i=0;i<25;i++)
   {
      while (input(Datos) == 1);
      set_timer1(0);  
      while (input(Datos) == 0);
      Aux_tiempo_entre_tramas = get_timer1();
      if (Tiempo_entre_tramas < Aux_tiempo_entre_tramas)
         Tiempo_entre_tramas = Aux_tiempo_entre_tramas;
   }
   Tiempo_ET_delta_neg = Tiempo_entre_tramas-Tiempo_entre_tramas/8;
   Tiempo_ET_delta_pos = Tiempo_entre_tramas+Tiempo_entre_tramas/8;
   for (i=0;i<25;i++)
   {
      while (input(Datos) == 1);
      set_timer1(0);  
      while (input(Datos) == 0);
      if ((Tiempo_ET_delta_neg < get_timer1())&(get_timer1() < Tiempo_ET_delta_pos))
      {
         i = 25;
         Trama_encontrada = true;
      }
   }
   if (Trama_encontrada == true)
   {
      while (input(Datos) == 1);
      set_timer1(0);  
      while (input(Datos) == 0);
      while ((Tiempo_ET_delta_neg > get_timer1())|(get_timer1() > Tiempo_ET_delta_pos)&(Contador_bits<25))
      {
          Contador_bits++;
        while (input(Datos) == 1);
        set_timer1(0);  
        while (input(Datos) == 0);
      }
      if (Contador_bits < 25)
      {
         while (input(Datos) == 0);
         set_timer1(0);  
         while (input(Datos) == 1);
         while (input(Datos) == 0);
         Tiempo_bits = get_timer1();
         while (input(Datos) == 0);
         set_timer1(0);  
         while (input(Datos) == 1);
         while (input(Datos) == 0);;
         Tiempo = get_timer1();
         if (((Tiempo_bits - Tiempo_bits/8) > Tiempo)|(Tiempo > (Tiempo_bits + Tiempo_bits/8)))
         {
            if (Tiempo < Tiempo_bits)
               Tiempo_bit = Tiempo_bits/2;
            else
               Tiempo_bit = Tiempo/2;
         }
         else
            Tiempo_bit = Tiempo_bits/2;
         do
         {
            do
            {
               while (input(Datos) == 1);
               set_timer1(0);  
               while (input(Datos) == 0);
               Tiempo = get_timer1();
            }while ((Tiempo_ET_delta_neg > Tiempo)|(Tiempo > Tiempo_ET_delta_pos));
            for (i=0;i<Contador_bits;i++)
            {
               while (input(Datos) == 1);
               set_timer1(0);  
               while (input(Datos) == 0);
               Bit = get_timer1();
               if (Bit < Tiempo_bit)
                  shift_left(Codigo,3,1);
               else
                  shift_left(Codigo,3,0);
            }
            if ((Codigo[0]==0)&(Codigo[1]==0)&(Codigo[2]==0))
               Mal = 1;
            if ((Nuevo_codigo == 0)&(Mal == 0))
            {
               for (i=0;i<3;i++)
                  Auxiliar[i]=Codigo[i];
            }
            if ((Mal == 0)&(Nuevo_Codigo == 1))
            {
               if (Auxiliar[0] == Codigo[0])
               {
                  if (Auxiliar[1] == Codigo[1])
                  {
                     if (Auxiliar[2] == Codigo[2])
                        Bien = 1;
                     else
                     {
                        Mal = 1;
                        Bien = 0;
                     }
                  }
                  else
                  {
                     Mal = 1;
                     Bien = 0;
                  }
               }
               else
               {
                  Mal = 1;
                  Bien = 0;
               }
            }
            Nuevo_codigo = 1;
            Contador_codigos++;
            for (i=0;i<3;i++)
               Codigo[i] = 0;
         }while((Mal == 0)&(Contador_Codigos < 4));
         if (Bien == 1)
         {
            for (i=0;i<3;i++)
            {
               Aux = Auxiliar[i];
               write_eeprom(i+Salto,Aux);
            }
            Salto+=3;
            write_eeprom(252,Salto);
         }
      }
   }
   }
}
Ahora hasta aca todo está bien y funciona de maravillas, pero como se habran dado cuenta, el código se frena hasta tanto no ocurran cambios en la entrada de datos y solo avanza cuando la entrada de datos va cambiando. La medición de los tiempo es importante para la posterior decodificación del código, por lo que si se comienzan a agregar interrupciones es probable que ya el código comience a fallar por la poca eficiencia del mismo. Entonces se me ocurre que el código puede ser mejorado si se utiliza el módulo de ocurrencia de eventos (cambios de estado en la entrada de datos) para poder medir los tiempos de los bits de entrada y que el programa no se quede esperando por los cambios en la entrada de datos, que opinan lo que saben? que manera de optimización encontrarían viable? espero sus aportes.

PD: Quien tenga dudas de como funciona el programa que me pregunte que se lo explico, no lo comenté por falta de tiempo.
 
Última edición:
#2
a ver, a ver.

¿es un codigo que puede leer los codigos de los controles RF de los automoviles?



eso si me gustaria saber
digo ya he destapado varios modulos de alarma de coches y traen un receptor RF como los que venden para jugar con los HT12D y un PIC.

y en el autozone venden los controles solitos sin el modulo de alarma

mi duda es:

¿cuantos protocolos de RF automotriz hay ?

me gustaria hacer un modulo para con un boton abrir mi puerta y con otro abrir mi cajuela y con otro botar seguros y asi.
 
#3
Pues si esta en la lista de integrados el código funciona ya que esta probado. Yo lo utilizo para centrales de portones automáticos y funciona de 10. Si buscas la hoja de datos de los integrados, de algunos no todos, veras que todos tienen la misma forma de codificar difieren en 3 cosas, la ubicación del bit de sincronización, la duración de los bit, y la cantidad y forma de codificar los bits. Pero si no te quedas mirando el árbol y miras el bosque verás que terminan siendo todos iguales y si se aplica la lógica correcta podes saber que código es. Pues no tienes mucho que perder, armalo en el pic que tu quieras, puede ser hasta en un 12FXX, has una rutina de escaneo de un pulsador y que cuando lo aprietes entre al programa, previo tenes que estar presionando el botón a grabar y luego verifica el codigo almacenado en la eeprom leyendo el pic con el programador y comparandolo con el del control. El programa considera un cero lógico un pulso en alto corto y con un bajo largo y considera un uno lógico un pulso en alto largo y un bajo corto, si ves una hoja de datos de un encoder entenderás de lo que te hablo. Luego te toca a ti usar esta misma rutina para estar escaneando constantemente para ver cuando se recibe un código. Tambien puedes emularlo en proteus usando la herramienta pattern. Bueno cualquier otra duda aquí estare.



---------------------------------- Actualizado ---------------------------------------------------
Te adjunto el datasheet del PT2260 para que veas como es la codificacion.
Fe de erratas: En la lista de encoders, el ultimo encoder figura el HT12A pero en realidad es el HT12D.

PD: Reemplazar la instrucción
Código:
Salto = 0;
Por esta porción de programa al comienzo del programa original
Código:
Salto = read_eeprom (252);
if (Salto==255)
Salto = 0;
 

Adjuntos

Última edición:
#4
Me parece que el código es un tanto excesivo. ¿No?

¿A-la hora de compilarlo, cuánto te ocupa?
Tiene pinta de ser casi 700 procesos, sólo por abusar tanto del else y and, sólo para cazar 24-bits.

Y otra cosa; ¿No te sería más fácil hacer-la lectura del receptor en una subrrutina para la lectura y otra para la identificación de código y tecla pulsada?
¿O hacerlo todo de una, de hecho?

Un saludo.
 
Última edición por un moderador:
#5
Ese código es para la identificación de código, con una ligera modificación se utiliza para la lectura de código. Pues cada instrucción que hay es realmente necesaria, de hecho lo tengo implementado en centrales para portones automáticos que no es lo único que hacen y anda de 10. Pero si tu consideras excesivo el código te invito a modificarlo o realizar tu propio programa que realice lo mismo que hace el mio a ver como queda. Saludos.

 
#6
dejalo no vale la pena discutir con el nunca cree en los codigos que en verdad funcionan.

lo que si me gustaria saber
¿es parecido a leer un control de TV?
cuando tenga tiempo me chutare las tramas me gustaria abrir mi puerta con un boton , con otro botar seguros y con otro abrir cajuela :D
 
#7
Como estas TRILO-BYTE, pues te voy a ser sincero, nunca lo probé con un control remoto de tele, pero es quizás probable que funcione, habría que ver como es el protocolo de estos y como codifican los datos, quizás te funciona. Si es así, vas a poder prender el tele, el ventilador, la compu y quien sabe cuantas mas cosas, lo que se te ocurra. Esa tarea de investigar te lo dejo a ti, desde ya que te voy a ayudar con cualquier duda o inquietud que tengas.

 
#8
El modo de funcionamiento de cada control depende de cada fabricante, pero de forma popularizada se utilizan integrados codificadores que universalizan la forma de funcionar. Si cuentas con un control y verificas el integrado que posee con la lista que esta puesta en el primer post podras saber si te sirve o no.

 
#9
ando viendo que venden alarmas de coche que no son caras pero no hacen lo que me gustaria para mis espectativas.

¿mi duda es como consigues estos controles sueltos?

cada control tiene un codigo unico.:unsure:

tengo muchas dudas, otra cosa eso de los portones automaticos me llama la atencion poner uno en mi casa apoco cajan bien con un control de estos.

revise tu codigo esta bastante espaguetizado un poco pulir el codigo quedaria super, aver si en estos dias me pongo a hacer unos experimentos pero para eso debo buscar un control bonito.

los que tengo en el cajon de los recuerdos estan horribles.
 
#10
ando viendo que venden alarmas de coche que no son caras pero no hacen lo que me gustaria para mis espectativas.

¿mi duda es como consigues estos controles sueltos?

cada control tiene un codigo unico.:unsure:

tengo muchas dudas, otra cosa eso de los portones automaticos me llama la atencion poner uno en mi casa apoco cajan bien con un control de estos.

revise tu codigo esta bastante espaguetizado un poco pulir el codigo quedaria super, aver si en estos dias me pongo a hacer unos experimentos pero para eso debo buscar un control bonito.

los que tengo en el cajon de los recuerdos estan horribles.
Hola TRILO-BYTE, pues te cuento que los controles me los fabricó yo mismo, por lo que no tengo problema con eso. El algoritmo es algo Así, lo primero que hace el programa es buscar el espacio entre tramas, esta es la separación que hay entre un código y el próximo nuevo a repetir o mejor dicho, es el famoso preámbulo del código. Mido cada uno de los tiempos bajo y lo comparó con el que sigue para ver si el anterior es mayor que el que estoy midiendo, así una cantidad de 25 bits para asegurarme de que seguro en algún momento lo voy a encontrar. Cuando encuentro el mayor valor de tiempo en bajo, me quedo esperando a que aparezca de nuevo para saber que ese es el momento de inicio del código. Luego mido el tiempo de un bit, esto lo hago porque cada control tiene su tiempo, no son todos iguales, y por lo tanto me adapto a cada control. Luego de obtener la duración de un bit, guardo ese tiempo dividido 2 y vuelvo a buscar la referencia para poder comenzar a decodificar el código en función de la duración del tiempo en bajo teniendo en cuenta la duración del bit. Así determinó si el bit es un cero o un uno. Espero haberte orientado, desde ya que si sabes el codigo del control y los tiempos de duracion todo es mas sencilllo de hacer, saludos.

 
Última edición:

Arriba