[Aporte] Programa para leer codigos de hasta 24 bits

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.jpgReceptor 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:
a ver, a ver.

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

two-way-alarm2.jpg


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

  • PT2260.pdf
    596.7 KB · Visitas: 19
Última edición:
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:
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.

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

 
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.

 
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.
 
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:
Hola Juanma2468, que tal. Pues curioseando por el foro me he encontrado con tu aporte que a demás me parece buenísimo.
Te quería comentar, que me gusta el cacharreo , como a todos, pero solo se programar en Assembler (perro viejo no aprende trucos nuevos), me refiero a que ya soy mayor de 50 y no me veo con ganas de ponerme a aprender C.
Por tal motivo , viendo tu código, me cuesta bastante seguirlo y tenía un par de cuestiones:
1º.- ¿como podría compilarlo (con que programa) y como tendría que modificar el programa para por ejemplo meter el .hex resultante en un 16f876?.
2º.- ¿Tienes algún esquema de conexionado? Lo digo porque como no sigo bien el código, no sé si tiene asignado algún botón para memorizar códigos, o algún led que indique algo, o por dónde saldría el código memorizado para reenviarlo a un receptor...
Verás que estoy lleno de dudas. Te doy las gracias desde ya.
[SPAM Eliminado] Normas del Foro 2.1
 
Hola maisys. Entiendo que seas de la vieja escuela, donde lo único que se veía o manejaba era el asambler, de hecho yo también lo he trabajado, pero la verdad es que una vez que migras al C te das cuenta del tiempo inútil que perdés haciendo un proyecto. Los que dicen que el C no sirve porque no podes controlar a bajo nivel son pamplinas, ya que un buen programador sabe en que casos deberá usar lenguaje de bajo nivel dentro de la misma programación de C para optimizar el código. Migrar del asambler al C no es tan complicado como cree, de hecho es mucho más sencillo que el asambler. Si quisieras enseñarle asambler a alguien que sólo a visto C en su vida le resultaría mucho más complicado que al revés. Pero bueno, respondiendo a tu consulta. El compilador que utilizo es el CCS, para reutilizarlo para un 16F876 seguramente vas a tener que modificar/agregar/quitar los fuses, que son los bit de la palabra de configuración, cada micro puede variar esa configuración ya sea o porque tienen otros bit o porque faltan ciertos bits. No hay esquema porque lo que hace el soft es solo leer códigos que entran por el pin A0 y almacenarlos en la memoria eeprom. Fijate que tengo hecho otros aportos de un receptor que hace uso de este soft para activar un rele por ejemplo, la ultima versión creo que era la V3. Saludos.
 
Muchas gracias Juanma2468 por responder.
Pues no lo creerás pero ahora que estoy confinado en casa sin poder hacer nada en mi trabajo, ayer decidí que no sería un mal momento para curiosear sobre el lenguaje C, y estoy siguiendo una serie de vídeos , muy bien explicados por un ingeniero...y si, tienes toda la razón, no parece tan dificil. Como todo hay que tener en cuenta muchos factores, pero no más que en assembler.
Lo que voy a hacer es (con tu permiso) esperar un poco para aprender C y jugar un poco con tu código y ver las posibilidades que seguro son muchas.
Un cordial saludo.
 
Maisys, si trabajase con assambler. Te aconsejaría mas el micro estudio pic básic como compilador. Por lo menos lor registros tienen los nombres tal cual la ficha técnica de los microcontroladores y te muestra las instrucciones de proceso al compilar (te permite trabajar mas como assambler de microchip) pero resulta mas cómodo usar instrucciones completas tan sólo cojerles el truco de como trabajan los emplazamientos W y f .
Y ese código lectura serial asíncrono me parece escesivo y malgastando tmr1. Todavía si usara T1GO e interrupcion por cambio de flanco podría meterse en interrupciones las lecturas de los pulsos (por un decir)
 
Arriba