[Aporte] - Receptor RF-IR universal - V2.0

Claro, pero los llaveros que dispongo son code learn y hay que grabarlos con otro control que ya esté funcionando con el receptor. Son precisamente los copiadores. Los desarmé y tienen un pic12f629 en su interior.

Te paso el manual del control en los archivos adjuntos y verás cómo se programa.

pero eso no es rs232 eso es la codificacion Philips una bastante antigua y muy curiosa por no acoplar mucho con el ruido ir ya sea solar o de una luz de sodio.
rc5 y nec hasta el sony este mitico que manda solo 12bit o 9.. utilizan un principio rs232

el Philips controla los bit segun canvia el flanco ascendente o descendente. la manera facil programando un pic y salir del atolladero con un pis es contar si el pulso largo es alto o bajo cuando el largo de pulso es mas corto o la frecuencia mas alta mantines el mismo bit tienes un pulso largo cambias el estado del bit cada pulso corto añades ese numero otro pulso largo buelves a cambiar el pulso del bit y lo mantienes si fueran todo pulsos largos seria 10101010. por ejemplo..
o 111100 que serian 6 pulsos cortos uno largo para cambiar a 0 y otro corto para mantener 0

si no me equivoco,, aparte por que el codigo que vi en el pdf me parece muy largo cuando se termine compilando.

un saludo
 
Última edición:
Muy buen trabajo. Gracias por compartilo. Tengo una pregunta, he intentado grabar un control HT6P20X y no me ha funcionado, he estado revisando el por que mas aun no lo se. Puede darme alguna luz por favor:
 
si la verdad que no es mala idea y daria lo mismo el tipo de codificacion que mande el IR, al final se mudura el emisor RF y se vuelve a acoplar al receptor RF para dar la portadora al reset del un 555 que crea la portadora para el IR emisor a 38khz.

la verdad que si la idea es buena y sencilla
 
como hacer que funcione con un mando generico de 4 pulsadores y que una salida salida de siempre un pulso de 1/2 seg. y luego el pulso de 1/2 segundo correspondiente de cada canal activado, es un proyecto de una puerta principal y cuatro puertas secundarias, conozco de electrónica pero programacion de pics muy poco, ojala puedas ayudarme. gracias anticipadas.
Mensaje automáticamente combinado:

 
Última edición:
Buenas tardes, Juanma.

Quería saber si te podía hacer unas consultas sobre el aporte que hiciste.

Estoy tratando de hacerlo andar con un PIC12F1840 y no he tenido resultados.

En mi caso estoy utilizando un receptor de 433Mhz (de los económicos), y un control remoto que tiene el chip PT2260.

Las únicas modificaciones que he realizado son de los pines y los registros asociados a esos pines. Lo demás está tal cuál el código que vos pasaste. También le borré algunas líneas que no hacían al funcionamiento (vos las habías comentado o no tenían efecto en el código).

Si ves que tengo algo que podría estar mal, te agradecería mucho. En caso de que no puedas, igual te agradezco por compartir tu trabajo.

C:
#INCLUDE <12F1840.h>

// Declaración para trabajar con punteros a constantes.
#device PASS_STRINGS=IN_RAM

#FUSES INTRC_IO               // Oscilador interno.
#FUSES WDT                    // Utilizamos el perro guardián.
#FUSES PUT                    // Habilita el power uP timer.
#FUSES NOMCLR                 // Utilizamos el pin MCLR como E/S.
#FUSES NOPROTECT              // No proteje el código del microcontrolador -- DE MOMENTO.
#FUSES NOCPD                  // No proteje el área de la memoria EEPROM.
#FUSES NOBROWNOUT             // No hay reset por bajo voltaje.     
#FUSES NOCLKOUT               // Utiliza los pines de clk como E/S.
#FUSES NOIESO                 
#FUSES FCMEN                  // Monitor de falla de clock.                 
#FUSES NOWRT                  // No hay protección de registros especiales.
#FUSES PLL_SW                 // Utiliza el PLL para generar el clock del micro = 32Mhz.
#FUSES STVREN                 // Si la pila se llena, generará un reset.     
#FUSES NODEBUG                // No utilizaremos código de debug.
#FUSES NOLVP                  // No utilizaremos programación a bajo voltaje.

#USE delay (Clock = 16000000,RESTART_WDT)                            // Reloj = 16Mhz.

// Se define etiquetas de pines de pines //

#use fast_io(A) // Asignación rápida de los pines del puerto A

#locate Puerto_A = 0xf92 // Defino el puerto A con una etiqueta.

#bit Pgm_Cod       = Puerto_A.4 // A4 como entrada del pulsador para programar los códigos
#bit Led_Cod_OK    = Puerto_A.0 // A0 como salida de indicación de código grabado correctamente
#bit Led_Cod_Error = Puerto_A.1 // A1 como salida de indicación de código erroneo
#bit Config        = Puerto_A.5 // A5 como entrada del pulsador de configuración
#bit Dato_entrada =  Puerto_A.2 // A2 como entrada de datos del control remoto

// Defino un registro de estado con sus bits respectivos

int Estado = 0; // Registro de Estado ==> BITS: 7 6 5 4 3 2 1 0
                //                              | | | | | | | |_ Bien : Se recibio un código correcto
                //                              | | | | | | |___ Mal : Se recibio un código incorrecto
                //                              | | | | | |_____ Comienzo : Determina cuando comienza un código
                //                              | | | | |_______ Fin : Determina cuando termina un código
                //                              | | | |_________ Estado_inicial : Se pone el estado en el que se comienza a analizar el código
                //                              | | |___________ Escaneo_tiempo : Indica que se encuentra en la parte de analisis de tiempos
                //                              | |_____________ Nuevo_Codigo : Hay disponible un nuevo codigo
                //                              |_______________ Abrir_Cerrar : Al abrir el portón se pone en 1, cuando se cierra se pone en 0
                
#bit Bien           = Estado.0 // Si recibe un codigo correcto, Bien = 1
#bit Mal            = Estado.1 // Si recibe un codigo incorrecto, Mal = 1
#bit Comienzo       = Estado.2 // Si comienza un código, Comienzo = 1
#bit Fin            = Estado.3 // Si termina un código, Fin = 1
#bit Estado_inicial = Estado.4 // Se pone el valor con el que se empieza a leer el código para ver el momento de cambio
#bit Escaneo_tiempo = Estado.5 // Si se está evaluando los tiempo del código, Escaneo_tiempo = 1
#bit Nuevo_Codigo   = Estado.6 // Si hay un nuevo codigo medido, Nuevo_Codigo = 1
#bit Abrir_Cerrar   = Estado.7 // Si se esta abriendo el portón, Abrir_Cerrar = 1


// Definición de variables

long Tiempo,Tiempo_Max,Tiempo_Min,Reset;
int i,Contador,Contador_Unos,Codigo[3],Salto,aux,Contador_Codigo,Auxiliar[3];

// Declaro las funciones utilizadas

void Inicializacion_dispositivo (); // Rutina de inicialicación del dispositivo
void Demora_ms(long tiempo_ms);     // Rutina para hacer demoras en milisegundos
void Tiempo_Bajo ();                // Rutina para analizar el tiempo de los pulsos en bajo
void Tiempo_Alto ();                // Rutina para analizar el tiempo de los pulsos en bajo
void Decodificacion_cero ();        // Rutina donde registra un cero de la decodificación
void Decodificacion_uno ();         // Rutina donde registra un uno de la decodificación
void Decodificacion_Codigo ();      // Rutina que realiza el proceso de decodificación del código
//!void Borrar_Eeprom ();           // Rutina que borra el contenido de la memoria eeprom interna
void Registro_codigos ();           // Rutina para registrar los tiempos del código
void Guardar_Codigo_Eeprom ();      // Rutina para guardar el código en la eeprom interna
void Leer_codigo ();                // Rutina para leer los códigos de entrada
void Configurar ();                 // Rutina que permite realizar la configuracion del funcionamiento
//!void Funcionamiento ();             // Rutina de funcionamiento acorde a como fue configurado

// Interrupción del timer 0
#int_timer0
void Reset_temp (void)
{
   Reset++;
}

// Programa principal

void main()
{
   Inicializacion_dispositivo();          // Inicializo el dispositivo
   Led_Cod_Error = 1;                     // Prendo el led de error al iniciar
   Demora_ms (500);                       // Espero 500 mseg
   Led_Cod_Error = 0;                     // Apago el led de error
   Demora_ms (500);                       // Espero 500 mseg
   Salto = read_eeprom (125);             // Cargo el valor del ultimo salto realizado en la memoria eeprom
   for (;;)                               // Buecle infinito
   {
      if (Pgm_Cod == true)                // Si se presiona el pulsador entro a la rutina Registro_codigos
         Registro_codigos ();             // Llamo la rutina Registro_codigo
      if (Config == true)                 // Si se presiona el pulsador entro a la rutina Configurar
         Configurar ();                   // Llamo la rutina Configurar
      Leer_codigo ();                     // Llamo la rutina Leer_codigo
   }
}

void Demora_ms(long tiempo_ms)   // Rutina para generar demoras en ms sin agregar mas codigo
{
   while (--tiempo_ms)           // Bucle de tiempo en mseg
      delay_ms(1);               // Retardo de 1 mseg
}

void Inicializacion_dispositivo(void)
{
   setup_oscillator(OSC_16MHZ);                          // Configura el oscilador interno.
   setup_adc_ports(NO_ANALOGS|VSS_VDD);                  // Todos los pines son E/S digital.
   setup_adc(ADC_OFF);                                   // Apaga el conversor A/D.
   setup_dac(DAC_OFF);                                   // Apaga el DAC.
   setup_spi(SPI_SS_DISABLED);                           // Desactiva el puerto SPI.
   setup_ccp1(CCP_OFF);                                  // Módulo de captura desactivado.
   setup_comparator(NC_NC);                              // Módulo de comparación desactivado.
 
   set_tris_a (0b111100);     
   output_a (0);   
   setup_timer_1 (T1_INTERNAL | T1_DIV_BY_4);            // Seteo el timer 1 para funcionar a 1 useg
   setup_timer_0 (T0_DIV_256);
   enable_interrupts (GLOBAL);
}

void Registro_codigos (void)
{
   while (Pgm_Cod == true);                        // Se queda esperando hasta soltar el pulsador
   Reset= 0;
   clear_interrupt (INT_TIMER0);
   enable_interrupts (INT_TIMER0);
   while ((Bien == 0)&(Reset<611))
   {
      Contador_Codigo = 0;
      Mal = 0;
      Nuevo_Codigo = 0;
      for (i=0;i<3;i++)                               // Borro el contenido de los 3 bytes de Auxiliar
         Auxiliar[i] = 0;
      do
      {
         for (i=0;i<3;i++)                               // Borro el contenido de los 3 bytes de Codigo
            Codigo[i] = 0;
         Contador = 25;                                  // Para un bucle que analiza 25 ceros del código
         Contador_Unos = 0;                              // Contador de unos del código para determinar el tipo de codificación
         Tiempo_Max = 0;                                 // Seteo el valor de tiempo máximo en el mínimo valor
         Tiempo_Min = 0xFFFF;                            // Seteo el valor de tiempo mínimo en el máximo valor
         while (Contador!=0)                             // Sale del bucle cuando Contador = 0
         {
            Tiempo_Bajo ();                              // Llamo a la rutina Tiempo_Bajo
            if (Tiempo_Max<Tiempo)                       // Pregunto si el valor de Tiempo es mayor que Tiempo_Max
               Tiempo_Max = Tiempo;                      // Reemplazo el valor de Tiempo_Max por Tiempo si Tiempo_Max < Tiempo
            Contador--;                                  // Decremento el valor del Contador
         }
         Contador = 25;                                  // Para un bucle que analiza 25 ceros del código
         while (((Tiempo_Max-(Tiempo_Max/16))>Tiempo)&(Contador!=0)) // Me quedo hasta que encuentro el espacio entre tramas o hata que contador sea cero
         {
            Tiempo_Bajo ();                              // Llamo a la rutina Tiempo_Bajo
            Contador--;
         }
         Decodificacion_Codigo ();                          // Llamo a la rutina Decodificacion_Codigo
         if (Nuevo_Codigo == 0)
         {
            for (i=0;i<3;i++)
               Auxiliar[i]=Codigo[i];
            if ((Codigo[0]==0)&(Codigo[1]==0)&(Codigo[2]==0))
               Mal = 1;
         }
         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;
            }
         }
      Contador_Codigo++;
      Nuevo_Codigo = 1;
      }while ((Mal == 0)&(Contador_Codigo < 4));
   }
   disable_interrupts (INT_TIMER0);
   if (Bien == 1)
   {
      Guardar_Codigo_Eeprom();                        // Llamo a la rutnia Guardar_Codigo_Eeprom
      Led_Cod_OK = 1;                                 // Prendo el led de OK para indicar que el código se copio correctamente
      Demora_ms (1000);                               // Espero 1 seg
      Led_Cod_OK = 0;                                 // Apago el led de OK
   }
   else
   {
      Led_Cod_Error = 1;                              // Prendo el led de OK para indicar que el código se copio correctamente
      Demora_ms (1000);                               // Espero 1 seg
      Led_Cod_Error = 0;                              // Apago el led de OK
   }
   Bien = 0;
   Mal = 0;
}

void Tiempo_Bajo (void)
{
   while(Dato_entrada == 1);                 // Está en alto y espera que baje
   set_timer1(0);                            // Pone a cero el Timer 1
   while(Dato_entrada == 0);                 // Se mantiene en el pulso bajo hasta que cambie
   Tiempo = get_timer1();                    // Leo el tiempo del pulso bajo
}

void Tiempo_Alto (void)
{
   while(Dato_entrada == 0);                 // Está en alto y espera que baje
   set_timer1(0);                            // Pone a cero el Timer 1
   while(Dato_entrada == 1);                 // Se mantiene en el pulso bajo hasta que cambie
   Tiempo = get_timer1();                    // Leo el tiempo del pulso bajo
}

void Decodificacion_cero (void)
{
   shift_left(Codigo,3,0);                   // Roto hacia la izquierda un 0
}

void Decodificacion_uno (void)
{
   shift_left(Codigo,3,1);                   // Roto hacia la izquierda un 1
}

void Guardar_Codigo_Eeprom (void)
{
   if (Salto>120)                                              // Verifico cuando Salto llega al máximo permitido
      Salto = 0;                                               // Lo reseteo a cero
   for (i=0;i<3;i++)                                           // Guardo el Codigo en la eeprom de acuerdo al valor de Salto
   {
      aux = Codigo[i];
      write_eeprom(i+Salto,aux);
   }
   if (make16(read_eeprom(126),read_eeprom(127))>Tiempo_Max)   // Veo si el valor de Tiempo_Max guardado es mayor que el último tiempo máximo guardo y lo reemplazo
   {   
      write_eeprom(126,make8(Tiempo_Max,1));                   // Guardo parte alta de Tiempo_Max en la posición 126
      write_eeprom(127,make8(Tiempo_Max,0));                   // Guardo parte baja de Tiempo_Max en la posición 127
   }
   Salto+=3;                                                   // Si Salto no llego al máximo lo incremento en 3
   write_eeprom(125,Salto);                                    // Guardo el valor de Salto en la eeprom en la posición 125
}

void Leer_codigo (void)
{
   for (i=0;i<3;i++)                                        // Borro el contenido de los 3 bytes de Codigo
      Codigo[i] = 0;
   Contador = 25;                                           // Para un bucle que analiza 25 ceros del código
   Contador_Unos = 0;                                       // Contador de unos del código para determinar el tipo de codificación
   Tiempo_Min = 0xFFFF;                                     // Seteo el valor de tiempo mínimo en el máximo valor
   Tiempo_Max = make16(read_eeprom(126),read_eeprom(127));  // Leo el valor de Tiempo_Max
   Tiempo_Bajo ();                                          // Llamo a la rutina Tiempo_Bajo
   if ((Tiempo_Max-(Tiempo_Max/16))<Tiempo)                 // Decodifico si el tiempo leido es mayor que Tiempo_Max-(Tiempo_Max/16)
   {
      Decodificacion_Codigo ();                             // Llamo a la rutina Decodificacion_Codigo
      if (Mal == 0)
      {
         for (i=0;i<120;i+=3)
         {
            if (Bien == 0)
            {
               if (read_eeprom(1+i) == Codigo[1])
               {
                  if (read_eeprom(2+i) == Codigo[2])
                  {
                     if (read_eeprom(0+i) == Codigo[0])
                     {
                        Bien = 1;
                        Mal = 0;
                     }
                  
                     else
                        Mal = 1;
                  }
                  else
                     Mal = 1;
               }
               else
                  Mal = 1;
            }
         }
      }
      if (Bien == 1)
      {
         output_toggle(PIN_A0);
         Demora_ms(500);
      }
      Bien = 0;
      Mal = 0;
   }
}

void Configurar (void)
{
   while (Config == true);                // Me quedo hasta soltar el pulsador Config
   Demora_ms(20);                         // Espero 20 mseg

      for (i=0;i<128;i++)                 // Bucle para borrar la eeprom
      {
         write_eeprom(i,0xFF);            // Escribo FF en toda la eeprom
      }
      Led_Cod_OK = 1;                     // Prendo el led OK
      Led_Cod_Error = 1;                  // Prendo el led error
      Demora_ms (333);                    // Espero 333 mseg
      Led_Cod_OK = 0;                     // Apago el led OK
      Led_Cod_Error = 0;                  // Apago el led error
      Demora_ms (333);                    // Espero 333 mseg
      Led_Cod_OK = 1;                     // Prendo el led OK
      Led_Cod_Error = 1;                  // Prendo el led error
      Demora_ms (333);                    // Espero 333 mseg
      Led_Cod_OK = 0;                     // Apago el led OK
      Led_Cod_Error = 0;                  // Apago el led error
      Demora_ms (333);                    // Espero 333 mseg
      Led_Cod_OK = 1;                     // Prendo el led OK
      Led_Cod_Error = 1;                  // Prendo el led error
      Demora_ms (333);                    // Espero 333 mseg
      Led_Cod_OK = 0;                     // Apago el led OK
      Led_Cod_Error = 0;                  // Apago el led error

}

void Decodificacion_Codigo (void)
{
   do
   {
      Contador_Unos++;                                   // Incremento el contador de unos
      Tiempo_Bajo();                                     // Llamo a la rutina Tiempo_Bajo
      if (Tiempo_Min>Tiempo)                             // Pregunto si el valor de Tiempo es menor que Tiempo_Min
         Tiempo_Min = Tiempo;                            // Reemplazo el valor de Tiempo_Min por Tiempo si Tiempo_Min > Tiempo
   }while(((Tiempo_Max-(Tiempo_Max/16))>Tiempo)&(Contador_Unos<26));          // Repito el bucle hasta encontrar el espacio entre tramas o hasta exceder el maximo de Contador_Unos
   if (Contador_Unos == 25)                              // Si el contador de unos es igual a 25 entonces el código tiene sincronismo
      Contador_Unos--;                                   // Decremento en uno el contador de unos
   if (Contador_Unos == 13)                              // Si el contador de unos es igual a 13 realizo la rutina de decodificación HT12/MM53200/UM3750/UM86409
   {
      Contador_Unos--;                                   // Decremento el contador de unos
      do
      {
         Tiempo_Bajo();                                  // LLamo a la rutina Tiempo_Bajo
         if ((Tiempo_Min+(Tiempo_Min/2))>Tiempo)         // Prgunto si el tiempo alto es menor que Tiempo_Min+(Tiempo_Min/2) para decodificar como cero
            Decodificacion_cero();                       // Llamo a la rutina Decodificacion_cero
         else                                            // Si no decodifico como uno
            Decodificacion_uno();                        // Llamo a la rutina Decodificacion_uno
         Contador_Unos--;                                // Decremento el contador de unos
      }while(Contador_Unos != 0);                        // Termino el bucle si el contador de unos es 0
   }
   else                                                  // Sino realizo la rutina de decodificación HT6026/PT2262/EV1527
   {
      if ((Contador_Unos==24)|(Contador_Unos==18))
      {
         do
         {
            Tiempo_Alto();                                  // LLamo a la rutina Tiempo_Alto
            if ((Tiempo_Min+(Tiempo_Min/2))>Tiempo)         // Prgunto si el tiempo alto es menor que Tiempo_Min+(Tiempo_Min/2) para decodificar como cero
               Decodificacion_cero();                       // Llamo a la rutina Decodificacion_cero
            else                                            // Si no decodifico como uno
               Decodificacion_uno();                        // Llamo a la rutina Decodificacion_uno
            Contador_Unos--;                                // Decremento el contador de unos
         }while(Contador_Unos != 0);                        // Termino el bucle si el contador de unos es 0
      }
      else
         Mal = 1;
   }
}
 
C:
#locate Puerto_A = 0xf92 // Defino el puerto A con una etiqueta.

Ahí está el error. Y la corrección es la siguiente:

C:
#locate Puerto_A = 0x0C // Defino el puerto A con una etiqueta.

De todas formas, todavía no es completamente funcional, hay algunas cosas que al parecer el compilador no está interpretando bien, cuando pueda hacerlo andar bien, subiré el código.
 
Arriba