# RC5 de philips decodificación y control



## Moyano Jonathan (Ago 10, 2010)

Bueno antes que nada hola a todos !! 
En esta ocación les traigo un proyecto que realizé esta tarde como respuesta a un proyecto más grande que tengo en mente...

Se trata de la decodificación del código RC5 de philips. Este código es el más usado en la actualidad por los experimentadores y desarrolladores debido a que es el más difundido y es ya un standar dentro de la industria.
*Veamos algunas de sus características:*
- Dirección de 5 bits y comando de 6 bits (7 bits de comando para RC-5X) 
- Codificación de doble fase o bi-fase (Bi-phase, también llamada código Manchester)
- Frecuencia de portadora de 36 kHz 
- Tiempo de bit constante de 1,778 ms (64 ciclos de 36 kHz)
*Módulación:*
  El protocolo está basado en una modulación Manchester de doble fase sobre una portadora de  36 kHz. En esta codificación, todos los bits tienen la misma longitud, de 1,778 ms. La mitad del  bit es un tren de pulsos de la portadora de 36 kHz, y en la otra mitad la señal está  plana.
   El cero lógico es representado por un tren de pulsos en la primera mitad del  tiempo que corresponde el bit. El uno lógico es representado por un tren de pulsos en la  segunda mitad de este tiempo. La relación entre pulso y pausa en la portadora de 36 kHz  es de 1/3 o 1/4, lo que reduce el consumo de energía.
Veamos en un gráfico lo anteriormente dicho:





*Protocolo:*




Bueno este es un tren de pulsos correspondientes a un trama RC5. Como vemos son 14 bits en total de los cuales tenemos 2 bits de start + 1 de togle. Antes de que empieze la trama transcurre medio bit antes de que el receptor pueda detectarla. Luego de los bits de start comienza el bit de togle , este bit cambia de estado cada vez que nosotros presionamos un botón en el control remoto y soltamos la tecla. Su función es detectar cuando presionamos continuamente una tecla o cuando la presionamos varias veces de forma alternada.


Luego de este bit comienza el bit más significativo de la dirección del comando y se extiende 5 bits. A continuación comienza el bit más significativo del comando que se extiende 6 bits.


Haciendo la sumatoria nos dá : 2 bits de start  + bit togle + 5 bits de dirección + 6 bits de datos = 14 bits que conforman una trama con una duración total de la trama de 25ms.


Mientras se mantenga presionada la tecla, el mensaje se repite cada 114 ms. El bit de  conmutación mantendrá el mismo nivel lógico durante la repetición de un mensaje.  Esto se hace así para que el programa de interpretación del receptor pueda detectar esta  autorrepetición y no la confunda con sucesivas pulsaciones de una tecla.


*Comandos predefinidos:*
Acá se muestran algunos comandos predifinidos en la mayoría de los controles remotos.







Ya teniendo explicado esto podemos pasar a desarrollar un programa de control básico para usar en nuestros proyectos de control.


Para mis prácticas yo usé el siguiente control remoto pero pueden usar cualquiera que cumpla con la norma RC5:




En el siguiente video les muestro la aplicación básica implementada en un PIC16F88 y un sensor IRM8601.





El código fuente del programa es el siguiente:

```
// Programa que recibe tramas RC5 del sensor IRM8601 - S las decodifica
// y muestra el comando y la dirección por un display LCD 2 x 16.
// El microcontrolador utilizado es un PIC16F88.
// Programador: Moyano Jonathan.
// Año: 2010.

#include <16f88.h>              // Definiciones de registros internos del micro.     
#fuses HS,NOWDT,NOPROTECT,PUT   // Fuses del programador.
#use delay (clock=20000000)     // Utilizamos un cristal de 20Mhz.
#use fast_io(b)

// Definiciones de hardware.
#define IR_RECEPTOR PIN_B0              // Pin donde estará conectado el receptor IR.
#define INDICADOR_TRAMA_RECIBIDA PIN_B1 // Led que indica cuando se recibe una trama RC5.

// Constantes del programa.
const int16    cuartodebit=440;   // tiempo [µs] de 1/4 bit
const int16    mediobit=880;      // tiempo [µs] de 1/2 bit

// Librerías de hardware externo:
#include <74HC595.c>            // Expansor de 8 salidas.

int16 decodifica_RC5();          // Declaramos la variable.

// Interrupción por RB0 en la que recibimos los datos del sensor.
#int_EXT
EXT_isr() {
  decodifica_RC5(); // Llama a la función de decodificación de trama de datos RC5.
  output_high(INDICADOR_TRAMA_RECIBIDA);
}

// Función de decodificación de RC5:
int16 decodifica_RC5()
{ 
   int16 D0=0, D1=65535; // Variables que contienen los datos.
   int i;                // Auxiliar.
      while (input(IR_RECEPTOR)); // Espera la transición 1 a 0 para empezar e leer.  
      delay_us(cuartodebit);   // Espera el bit de start de 440uS.  
      for(i=0;i<13;i++)       // Recoje los 13 bits de datos y los guarda...
      {
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D1=D1*2+input(IR_RECEPTOR);   // lee los datos...
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D0=D0*2+input(IR_RECEPTOR);   // lee los datos pero invertidos...
         
      }
      if ((D0^D1)==65535) return (D1 & 0x3FFF); else return (0);
      // Acá chequea que el valor que devuelva la función OR_EXCLUSIVA entre 
      // D1 (código original) ^ D0 (código invertido) sea igual a 3FFF (por ser 
      // valores coindidentes pero invertidos) ...si ese es el caso entonces devuelve
      // el valor de D1 ( datos originales ) para ser procesados...caso contrario retorna
      // 0.
}

void main() {
  set_tris_b(0x01);           // RB0 como entrada , las demás como salidas.
  output_low(INDICADOR_TRAMA_RECIBIDA); // Limpiamos el indicador de trama recibida.
  enable_interrupts(int_ext); // Habilitamos la interrupción externa por RB0.
  ext_int_edge(H_TO_L);  // Activa la interrupción por flanco de bajada.
  enable_interrupts(global);  // Habilitamos las interrupciones globales.
  output_74HC595(0x00); // Limpiamos las salidas.
  

   while(1)   // Bucle infinito.
   {
      long data;
      data=decodifica_RC5();        // Leemos los datos RC5.
      data=data & 0x007F;     // Limpiamos los bits de start y el de togle.
      // Determinamos cual es el comando recibido y actuamos en consecuencia.
      if (data==1) output_74HC595(0x01); 
      if (data==2) output_74HC595(0x02);
      if (data==3) output_74HC595(0x04);
      if (data==4) output_74HC595(0x08); 
      if (data==5) output_74HC595(0x10);
      if (data==6) output_74HC595(0x20);
      if (data==7) output_74HC595(0x40);
      if (data==8) output_74HC595(0x80);
      if (data==12)                
      {
       output_74HC595(0x00); // Limpiamos las salidas.         
      }
       output_low(INDICADOR_TRAMA_RECIBIDA); // Limpiamos el indicador de trama recibida.
   }

}
```
Y el código del expansor de salidas con 74HC595:

```
// Librería de control para el expansor de 8 salidas con 74HC595.
// Programador: Moyano Jonathan
// Versión: 1.0
// Fecha: 10/08/10
// Funciones:
// output_74HC595(valor); Muestra un valor de 0 a 255 en el puerto.


// Pines intercambiables según necesidades del usuario.

#define relog  PIN_A3
#define datos  PIN_A4
#define enable PIN_A2

void output_74HC595(int valor); // Definimos la función.

void output_74HC595(int valor) {

int contador; // Contador para escribir los datos al registro de desplazamiento.

  output_low(relog);
  output_low(enable);
  output_low(datos);
  
    for(contador=0;contador!=8;contador++) {  
     output_bit(datos,bit_test(valor,contador));
      output_high(relog);
       delay_cycles(1);
        output_low(relog);
  }
 
      output_high(enable);
      output_low(enable);
      delay_ms(1);
}
```


----------



## 1jabato1 (Ago 10, 2010)

Hola Moyano Jonathan.

Gracias por el aporte,ya podre dar alguna utilidad a la pila de mandos que tengo por hay creando polvo,había echo algo con el protocolo nec,pero el rc5 es de los mas extendidos,como dices.

Gracias por la excelente explicación y por compartirlo.

Saludos!!
Javi.


----------



## Moyano Jonathan (Ago 10, 2010)

Dentro de poco añadiré más aplicaciones a medida que las valla desarrollando 
saludos !


----------



## yoquese (Sep 11, 2010)

Hola, gracias por compartir, estuve probando el código en un pic 16F648A y funciona bien, pude distinguir cada comando, y el bit de toggle, pero no logro hacerlo con los de dirección (device address), cada vez que oprimo una tecla del control, es diferente por lo que seguramente lo estoy haciendo mal. 

Recien estoy empezando desde cero, en esto de la programación, y de la electrónica, tengo apenas un par de meses ( por si les parece muy obvio lo que pregunto ). 

Mi duda es esa, como puedo separar los bits de toggle, dirección, y comando, ya que veo esta linea en el código: 


```
data=data & 0x007F;     // Limpiamos los bits de start y el de togle.
```

pero aunque he estado viendo para que sirve ese operador, (&)  no logro entender como lo hace.

Saludos y gracias por cualquier consejo.


----------



## Moyano Jonathan (Sep 11, 2010)

El operador "*&*" significa AND  de datos.

Si vos tenés un dato que mide 14 bits en hexadecimal es 3FFF ese es la longitud incluyendo los bits de start y toggle.

Si los 2 bits de start + toggle  son eliminados  queda la direccion (5 bits) + datos (6 bits)

por lo tanto para eliminar start + togle + direccion tenemos que eliminar 6 bits del principio de la trama
o mejor dicho enmascararlos por lo tanto aplicamos  *& 0x7F* y nos queda el comando.

Si queremos eliminar en cambio start + togle + comando  aplicamos *& 0x83F *y nos queda la direccion.

Fijate si te funciona en caso de que no lo volvemos a ver.

saludos !


----------



## yoquese (Sep 11, 2010)

Hola, no funciona, al hacer esto:


```
while(1)
{
    long data;
    long comando;
    long direccion;

    data = decodifica_RC5();

    comando = data;
    direccion = data;

    comando = comando & 0x007F;
    
    direccion = direccion & 0x83F;
}
```

tanto, en comando, como en direccion, obtengo lo mismo, el comando, código de la tecla pulsada del control.


----------



## Moyano Jonathan (Sep 12, 2010)

le estás asignando el mismo dato a la variable comando....dejalo que voy a ver si lo pruebo luego en el proto y después te subo un programa 
saludos !


----------



## yoquese (Sep 12, 2010)

Hola, gracias por contestar, lo estoy haciendo asi, solo para probar e intentar sacar un solo dato a la vez, como te dije estoy intentando entender lo que hacia la linea que te menciono en mi primer mensaje.

En si, el tema de que funcione el código esta resuelto, ahora tengo tanto, el bit de toggle, como los de direccion y comando, probado con tres controles distintos, y todos los códigos corresponden, tal vez no sea la mejor forma de hacerlo, pero como te dije, mi objetivo era enteder como se hacia y estoy en eso. 


```
data = decodifica_RC5();

            toggle = data & 0x0800;
            toggle = toggle >> 11;
            
            direccion = data & 0x07C0;
            direccion = direccion >> 6;
            
            comando = data & 0x003F;
```

La verdad me da pena hacer preguntas que para la mayoria seran tontas, asi que procurare no hacerlo hasta leer y tratar de comprender las cosas un poco.

Gracias por tu tiempo.


----------



## Moyano Jonathan (Sep 12, 2010)

No hay drama hay mil formas de hacer lo que necesitas pero todo depende del conocimiento de programación que tengas. Ahora tu forma de hacerlo es muy elegante pero quizas se pueda hacer más en menos lineas de código....como te dije es cuestion de ver como a uno le es mas facil hacer las cosas.


----------



## master666 (Sep 17, 2010)

hola me gustaria saber si pudieron mejorar el codigo para que decodificara la trama que recibe del control, tengo un proyecto que es controlado por el control remoto, pero no he podido hacer que el pic responda al enviar la señal desde el control, talves me puedan ayudar, desde ya muchas gracias, espero su pronta respuesta


----------



## Moyano Jonathan (Sep 17, 2010)

Primero que nada el control que tenés que usar para poder armar este proyecto es del tipo RC5, esclusivamente funciona con ese formato. Ahora lo que estoy viendo es de un código de aprendizaje para que funcione con otros controles remotos ...pero no está entre mis planes inmediatos.


----------



## minichiello (Oct 14, 2010)

Hola, te hago una pregunta...
estuve mirando tu codigo y queria saber si sabias como puedo comenzar mi programa pero para hacerlo con un micro jl3 de motorola. la idea es controlar el volumen y el encendido de un amplificador de sonido.
Ya estuve midiendo la señal que envia el control, y la señal que recepciona el receptor que estoy usando. aparentemente es la enbolvente de el codigo manchester y hasta ahora, lo que he hecho del programa es crear un retardo en los dos primeros bits para no leerlos ya que siempre son iguales y ahora lo que pienso hacer es leer el estado de cada bit una vez. El problema es que no se como arrancar a escribir el software... si me podrias ayudar te lo agradeceria mucho. saludos!


----------



## Moyano Jonathan (Oct 14, 2010)

Mirá no conozco mucho sobre el código manchester pero te paso este link donde el tema del infrarojo lo explican muy bien: http://picmania.garcia-cuervo.net/experimentos_ir.php#RecTramas


----------



## minichiello (Oct 14, 2010)

el codigo manchester es el que rige en la norma rc5, por eso te preguntaba como habias iniciado tu programa... leyendo la señal embolvente o como? eso es lo que te queria preguntar!


----------



## Moyano Jonathan (Oct 14, 2010)

El programa lo hice filtrando la trama ...es decir fui mirando bit por bit pero para no hacerlo de manera continua puse este código:

```
for(i=0;i<13;i++)       // Recoje los 13 bits de datos y los guarda...
      {
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D1=D1*2+input(IR_RECEPTOR);   // lee los datos...
         delay_us(mediobit);   // espera el tiempo de medio bit 880uS.
         D0=D0*2+input(IR_RECEPTOR);   // lee los datos pero invertidos...
         
      }
```

Entonces leo la trama completa ....luego leo la trama invertida....luego hago la operacion XOR para comparar igualdad y por ultimo con multiples operaciones AND voy filtrando los datos....no me base en el protocolo manchester.


----------



## minichiello (Oct 14, 2010)

claro, solo que ahora voy a ver que hago para hacerlo con el jl3 de motorola, pero muchas gracias por la info! saludos!


----------



## Moyano Jonathan (Oct 14, 2010)

Motorola no tiene Codewarrior ¿? Tendrías que aplicar el mismo código y tendría que funcionar salvo las diferencias propias de cada compilador.


----------



## minichiello (Oct 19, 2010)

amigo te hago una pregunta porque no estoy muy familiarizado con el codewarrior. de donde tomas los datos que van del receptor al micro?
yo pensaba tomarlos desde algun puerto, y de ahi comenzar todo el ciclo de comandos para leer el dato y despues voy a interpretarlo. seria asi:

include 'jl3regs.inc'
org direccion
org comando

brclr 3,pta,borra 11
bra salta 11
brset 3,pta, comando


----------



## snakewather (Oct 19, 2010)

hola Moyano gracias por compartir la informacion la checare para ver si me sale algun proyectillo no he manejado controles de tv con pic Me viene de perlas tu aporte.


----------



## Moyano Jonathan (Oct 19, 2010)

Yo en mi caso los datos los tomo de un control remoto RC5 a través de un IRM8601 usando la interrupción RB0


----------



## snakewather (Oct 21, 2010)

Moyano Jonathan dijo:


> Yo en mi caso los datos los tomo de un control remoto RC5 a través de un IRM8601 usando la interrupción RB0




OK. adjunto Datasheet de los integrados usados para los que se animen a expirementar


----------



## yulian (Oct 27, 2010)

hola Moyano, me parecio genial ver tu proyecto funcionando ya que realmente es mi sueño hacerlo tambien. ultimamente me e estado documentando sobre el protocolo RC5 y luego de leer y probarlo realmente comprendi como funciona. Ahora quiero seguir tus pasos, y decodificar , el problema es que trabajo con un microcontrolador motorola GP32 y no se como empezar. Necesito ayuda, aun sigo analizando el codigo para PIC, pero no soy muy bueno con las interrupciones, porfavor ayuda.  Gracias por la inspiracion.


----------



## Moyano Jonathan (Oct 27, 2010)

Decime exactamente que micro estás usando por que el codewarrior tiene diferentes IDE según el procesador utilizado. Ahora tenés que investigar nomás no es muy complejo el código....buscate algún manual sencillo de las instrucciones del codewarrior y sus librerías para ver como funciona y luego empezá a crear el programa.

Yo también lo estoy portando para AVR mediante WinAVR y te digo que se me ha complicado un poco por los tiempos exactos que se requieren...pero investigando a fondo todo se puede.

Saludos !


----------



## josb86 (Dic 21, 2010)

hola moyano una pregunta para que utilizas en 74hc595?


----------



## Moyano Jonathan (Dic 21, 2010)

Solo para ampliar las salidas del PIC, si quieres se lo puedes sacar...es modificar 5 líneas de código.


----------



## johenrod (Jul 31, 2011)

Cordial saludo, 
en mi caso en particular, deseo hacer un control para controlar el radio del auto, se que se puede comprar pero deseo hacerlo con un pic, podrias decirme como enfocar el proyecto? pues tengo estas dudas.
Cada marca parece llevar un codigo diferente, ademas quisiera saber si hay alguna aplicacion que se instale en el pc, y poder observar el efecto o el valor binario o hex de cada tecla y asi hacer una base de datos.
gracias..


----------



## Moyano Jonathan (Jul 31, 2011)

Hola johenrod, como estás.

Interesante proyecto, mirá mi librería no contempla la decodificación de cualquier protocolo. Tengo una librería para Arduino o AVR - C++..que quizás las puedas portar a lenguaje C para PIC.
Si elejís usar un control RC5..tipo PHILIPS....podés usar mi librería.



> Cada marca parece llevar un codigo diferente, ademas quisiera saber si hay alguna aplicacion que se instale en el pc, y poder observar el efecto o el valor binario o hex de cada tecla y asi hacer una base de datos.
> gracias..



Yo uso el hyperterminal para ver los datos...y los datos los guardo en una hoja de datos de excel.

Te dejo el código de C++ para ver que podés hacer...con el mismo podés decodificar cualquier código por que es universal.


```
/*
 * IRremote
 * Version 0.11 August, 2009
 * Copyright 2009 Ken Shirriff
 * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
 *
 * Interrupt code based on NECIRrcv by Joe Knapp
 * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
 * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
 */

#include "IRremote.h"
#include "IRremoteInt.h"

// Provides ISR
#include <avr/interrupt.h>

volatile irparams_t irparams;

// These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging.
// To use them, set DEBUG in IRremoteInt.h
// Normally macros are used for efficiency
#ifdef DEBUG
int MATCH(int measured, int desired) {
  Serial.print("Testing: ");
  Serial.print(TICKS_LOW(desired), DEC);
  Serial.print(" <= ");
  Serial.print(measured, DEC);
  Serial.print(" <= ");
  Serial.println(TICKS_HIGH(desired), DEC);
  return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);
}

int MATCH_MARK(int measured_ticks, int desired_us) {
  Serial.print("Testing mark ");
  Serial.print(measured_ticks * USECPERTICK, DEC);
  Serial.print(" vs ");
  Serial.print(desired_us, DEC);
  Serial.print(": ");
  Serial.print(TICKS_LOW(desired_us + MARK_EXCESS), DEC);
  Serial.print(" <= ");
  Serial.print(measured_ticks, DEC);
  Serial.print(" <= ");
  Serial.println(TICKS_HIGH(desired_us + MARK_EXCESS), DEC);
  return measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS);
}

int MATCH_SPACE(int measured_ticks, int desired_us) {
  Serial.print("Testing space ");
  Serial.print(measured_ticks * USECPERTICK, DEC);
  Serial.print(" vs ");
  Serial.print(desired_us, DEC);
  Serial.print(": ");
  Serial.print(TICKS_LOW(desired_us - MARK_EXCESS), DEC);
  Serial.print(" <= ");
  Serial.print(measured_ticks, DEC);
  Serial.print(" <= ");
  Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);
  return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS);
}
#endif

void IRsend::sendNEC(unsigned long data, int nbits)
{
  enableIROut(38);
  mark(NEC_HDR_MARK);
  space(NEC_HDR_SPACE);
  for (int i = 0; i < nbits; i++) {
    if (data & TOPBIT) {
      mark(NEC_BIT_MARK);
      space(NEC_ONE_SPACE);
    } 
    else {
      mark(NEC_BIT_MARK);
      space(NEC_ZERO_SPACE);
    }
    data <<= 1;
  }
  mark(NEC_BIT_MARK);
  space(0);
}

void IRsend::sendSony(unsigned long data, int nbits) {
  enableIROut(40);
  mark(SONY_HDR_MARK);
  space(SONY_HDR_SPACE);
  data = data << (32 - nbits);
  for (int i = 0; i < nbits; i++) {
    if (data & TOPBIT) {
      mark(SONY_ONE_MARK);
      space(SONY_HDR_SPACE);
    } 
    else {
      mark(SONY_ZERO_MARK);
      space(SONY_HDR_SPACE);
    }
    data <<= 1;
  }
}

void IRsend::sendRaw(unsigned int buf[], int len, int hz)
{
  enableIROut(hz);
  for (int i = 0; i < len; i++) {
    if (i & 1) {
      space(buf[i]);
    } 
    else {
      mark(buf[i]);
    }
  }
  space(0); // Just to be sure
}

// Note: first bit must be a one (start bit)
void IRsend::sendRC5(unsigned long data, int nbits)
{
  enableIROut(36);
  data = data << (32 - nbits);
  mark(RC5_T1); // First start bit
  space(RC5_T1); // Second start bit
  mark(RC5_T1); // Second start bit
  for (int i = 0; i < nbits; i++) {
    if (data & TOPBIT) {
      space(RC5_T1); // 1 is space, then mark
      mark(RC5_T1);
    } 
    else {
      mark(RC5_T1);
      space(RC5_T1);
    }
    data <<= 1;
  }
  space(0); // Turn off at end
}

// Caller needs to take care of flipping the toggle bit
void IRsend::sendRC6(unsigned long data, int nbits)
{
  enableIROut(36);
  data = data << (32 - nbits);
  mark(RC6_HDR_MARK);
  space(RC6_HDR_SPACE);
  mark(RC6_T1); // start bit
  space(RC6_T1);
  int t;
  for (int i = 0; i < nbits; i++) {
    if (i == 3) {
      // double-wide trailer bit
      t = 2 * RC6_T1;
    } 
    else {
      t = RC6_T1;
    }
    if (data & TOPBIT) {
      mark(t);
      space(t);
    } 
    else {
      space(t);
      mark(t);
    }

    data <<= 1;
  }
  space(0); // Turn off at end
}

void IRsend::mark(int time) {
  // Sends an IR mark for the specified number of microseconds.
  // The mark output is modulated at the PWM frequency.
  TCCR2A |= _BV(COM2B1); // Enable pin 3 PWM output
  delayMicroseconds(time);
}

/* Leave pin off for time (given in microseconds) */
void IRsend::space(int time) {
  // Sends an IR space for the specified number of microseconds.
  // A space is no output, so the PWM output is disabled.
  TCCR2A &= ~(_BV(COM2B1)); // Disable pin 3 PWM output
  delayMicroseconds(time);
}

void IRsend::enableIROut(int khz) {
  // Enables IR output.  The khz value controls the modulation frequency in kilohertz.
  // The IR output will be on pin 3 (OC2B).
  // This routine is designed for 36-40KHz; if you use it for other values, it's up to you
  // to make sure it gives reasonable results.  (Watch out for overflow / underflow / rounding.)
  // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
  // controlling the duty cycle.
  // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
  // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
  // A few hours staring at the ATmega documentation and this will all make sense.
  // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.

  
  // Disable the Timer2 Interrupt (which is used for receiving IR)
  TIMSK2 &= ~_BV(TOIE2); //Timer2 Overflow Interrupt
  
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW); // When not sending PWM, we want it low
  
  // COM2A = 00: disconnect OC2A
  // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted
  // WGM2 = 101: phase-correct PWM with OCRA as top
  // CS2 = 000: no prescaling
  TCCR2A = _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS20);

  // The top value for the timer.  The modulation frequency will be SYSCLOCK / 2 / OCR2A.
  OCR2A = SYSCLOCK / 2 / khz / 1000;
  OCR2B = OCR2A / 3; // 33% duty cycle
}

IRrecv::IRrecv(int recvpin)
{
  irparams.recvpin = recvpin;
  irparams.blinkflag = 0;
}

// initialization
void IRrecv::enableIRIn() {
  // setup pulse clock timer interrupt
  TCCR2A = 0;  // normal mode

  //Prescale /8 (16M/8 = 0.5 microseconds per tick)
  // Therefore, the timer interval can range from 0.5 to 128 microseconds
  // depending on the reset value (255 to 0)
  cbi(TCCR2B,CS22);
  sbi(TCCR2B,CS21);
  cbi(TCCR2B,CS20);

  //Timer2 Overflow Interrupt Enable
  sbi(TIMSK2,TOIE2);

  RESET_TIMER2;

  sei();  // enable interrupts

  // initialize state machine variables
  irparams.rcvstate = STATE_IDLE;
  irparams.rawlen = 0;


  // set pin modes
  pinMode(irparams.recvpin, INPUT);
}

// enable/disable blinking of pin 13 on IR processing
void IRrecv::blink13(int blinkflag)
{
  irparams.blinkflag = blinkflag;
  if (blinkflag)
    pinMode(BLINKLED, OUTPUT);
}

// TIMER2 interrupt code to collect raw data.
// Widths of alternating SPACE, MARK are recorded in rawbuf.
// Recorded in ticks of 50 microseconds.
// rawlen counts the number of entries recorded so far.
// First entry is the SPACE between transmissions.
// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
ISR(TIMER2_OVF_vect)
{
  RESET_TIMER2;

  uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);

  irparams.timer++; // One more 50us tick
  if (irparams.rawlen >= RAWBUF) {
    // Buffer overflow
    irparams.rcvstate = STATE_STOP;
  }
  switch(irparams.rcvstate) {
  case STATE_IDLE: // In the middle of a gap
    if (irdata == MARK) {
      if (irparams.timer < GAP_TICKS) {
        // Not big enough to be a gap.
        irparams.timer = 0;
      } 
      else {
        // gap just ended, record duration and start recording transmission
        irparams.rawlen = 0;
        irparams.rawbuf[irparams.rawlen++] = irparams.timer;
        irparams.timer = 0;
        irparams.rcvstate = STATE_MARK;
      }
    }
    break;
  case STATE_MARK: // timing MARK
    if (irdata == SPACE) {   // MARK ended, record time
      irparams.rawbuf[irparams.rawlen++] = irparams.timer;
      irparams.timer = 0;
      irparams.rcvstate = STATE_SPACE;
    }
    break;
  case STATE_SPACE: // timing SPACE
    if (irdata == MARK) { // SPACE just ended, record it
      irparams.rawbuf[irparams.rawlen++] = irparams.timer;
      irparams.timer = 0;
      irparams.rcvstate = STATE_MARK;
    } 
    else { // SPACE
      if (irparams.timer > GAP_TICKS) {
        // big SPACE, indicates gap between codes
        // Mark current code as ready for processing
        // Switch to STOP
        // Don't reset timer; keep counting space width
        irparams.rcvstate = STATE_STOP;
      } 
    }
    break;
  case STATE_STOP: // waiting, measuring gap
    if (irdata == MARK) { // reset gap timer
      irparams.timer = 0;
    }
    break;
  }

  if (irparams.blinkflag) {
    if (irdata == MARK) {
      PORTB |= B00100000;  // turn pin 13 LED on
    } 
    else {
      PORTB &= B11011111;  // turn pin 13 LED off
    }
  }
}

void IRrecv::resume() {
  irparams.rcvstate = STATE_IDLE;
  irparams.rawlen = 0;
}



// Decodes the received IR message
// Returns 0 if no data ready, 1 if data ready.
// Results of decoding are stored in results
int IRrecv::decode(decode_results *results) {
  results->rawbuf = irparams.rawbuf;
  results->rawlen = irparams.rawlen;
  if (irparams.rcvstate != STATE_STOP) {
    return ERR;
  }
#ifdef DEBUG
  Serial.println("Attempting NEC decode");
#endif
  if (decodeNEC(results)) {
    return DECODED;
  }
#ifdef DEBUG
  Serial.println("Attempting Sony decode");
#endif
  if (decodeSony(results)) {
    return DECODED;
  }
#ifdef DEBUG
  Serial.println("Attempting RC5 decode");
#endif  
  if (decodeRC5(results)) {
    return DECODED;
  }
#ifdef DEBUG
  Serial.println("Attempting RC6 decode");
#endif 
  if (decodeRC6(results)) {
    return DECODED;
  }
  if (results->rawlen >= 6) {
    // Only return raw buffer if at least 6 bits
    results->decode_type = UNKNOWN;
    results->bits = 0;
    results->value = 0;
    return DECODED;
  }
  // Throw away and start over
  resume();
  return ERR;
}

long IRrecv::decodeNEC(decode_results *results) {
  long data = 0;
  int offset = 1; // Skip first space
  // Initial mark
  if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) {
    return ERR;
  }
  offset++;
  // Check for repeat
  if (irparams.rawlen == 4 &&
    MATCH_SPACE(results->rawbuf[offset], NEC_RPT_SPACE) &&
    MATCH_MARK(results->rawbuf[offset+1], NEC_BIT_MARK)) {
    results->bits = 0;
    results->value = REPEAT;
    results->decode_type = NEC;
    return DECODED;
  }
  if (irparams.rawlen < 2 * NEC_BITS + 4) {
    return ERR;
  }
  // Initial space  
  if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) {
    return ERR;
  }
  offset++;
  for (int i = 0; i < NEC_BITS; i++) {
    if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) {
      return ERR;
    }
    offset++;
    if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE)) {
      data = (data << 1) | 1;
    } 
    else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) {
      data <<= 1;
    } 
    else {
      return ERR;
    }
    offset++;
  }
  // Success
  results->bits = NEC_BITS;
  results->value = data;
  results->decode_type = NEC;
  return DECODED;
}

long IRrecv::decodeSony(decode_results *results) {
  long data = 0;
  if (irparams.rawlen < 2 * SONY_BITS + 2) {
    return ERR;
  }
  int offset = 1; // Skip first space
  // Initial mark
  if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) {
    return ERR;
  }
  offset++;

  while (offset + 1 < irparams.rawlen) {
    if (!MATCH_SPACE(results->rawbuf[offset], SONY_HDR_SPACE)) {
      break;
    }
    offset++;
    if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) {
      data = (data << 1) | 1;
    } 
    else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) {
      data <<= 1;
    } 
    else {
      return ERR;
    }
    offset++;
  }

  // Success
  results->bits = (offset - 1) / 2;
  if (results->bits < 12) {
    results->bits = 0;
    return ERR;
  }
  results->value = data;
  results->decode_type = SONY;
  return DECODED;
}

// Gets one undecoded level at a time from the raw buffer.
// The RC5/6 decoding is easier if the data is broken into time intervals.
// E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
// successive calls to getRClevel will return MARK, MARK, SPACE.
// offset and used are updated to keep track of the current position.
// t1 is the time interval for a single bit in microseconds.
// Returns -1 for error (measured time interval is not a multiple of t1).
int IRrecv::getRClevel(decode_results *results, int *offset, int *used, int t1) {
  if (*offset >= results->rawlen) {
    // After end of recorded buffer, assume SPACE.
    return SPACE;
  }
  int width = results->rawbuf[*offset];
  int val = ((*offset) % 2) ? MARK : SPACE;
  int correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;

  int avail;
  if (MATCH(width, t1 + correction)) {
    avail = 1;
  } 
  else if (MATCH(width, 2*t1 + correction)) {
    avail = 2;
  } 
  else if (MATCH(width, 3*t1 + correction)) {
    avail = 3;
  } 
  else {
    return -1;
  }

  (*used)++;
  if (*used >= avail) {
    *used = 0;
    (*offset)++;
  }
#ifdef DEBUG
  if (val == MARK) {
    Serial.println("MARK");
  } 
  else {
    Serial.println("SPACE");
  }
#endif
  return val;   
}

long IRrecv::decodeRC5(decode_results *results) {
  if (irparams.rawlen < MIN_RC5_SAMPLES + 2) {
    return ERR;
  }
  int offset = 1; // Skip gap space
  long data = 0;
  int used = 0;
  // Get start bits
  if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;
  if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return ERR;
  if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;
  int nbits;
  for (nbits = 0; offset < irparams.rawlen; nbits++) {
    int levelA = getRClevel(results, &offset, &used, RC5_T1); 
    int levelB = getRClevel(results, &offset, &used, RC5_T1);
    if (levelA == SPACE && levelB == MARK) {
      // 1 bit
      data = (data << 1) | 1;
    } 
    else if (levelA == MARK && levelB == SPACE) {
      // zero bit
      data <<= 1;
    } 
    else {
      return ERR;
    } 
  }

  // Success
  results->bits = nbits;
  results->value = data;
  results->decode_type = RC5;
  return DECODED;
}

long IRrecv::decodeRC6(decode_results *results) {
  if (results->rawlen < MIN_RC6_SAMPLES) {
    return ERR;
  }
  int offset = 1; // Skip first space
  // Initial mark
  if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) {
    return ERR;
  }
  offset++;
  if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) {
    return ERR;
  }
  offset++;
  long data = 0;
  int used = 0;
  // Get start bit (1)
  if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return ERR;
  if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return ERR;
  int nbits;
  for (nbits = 0; offset < results->rawlen; nbits++) {
    int levelA, levelB; // Next two levels
    levelA = getRClevel(results, &offset, &used, RC6_T1); 
    if (nbits == 3) {
      // T bit is double wide; make sure second half matches
      if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return ERR;
    } 
    levelB = getRClevel(results, &offset, &used, RC6_T1);
    if (nbits == 3) {
      // T bit is double wide; make sure second half matches
      if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return ERR;
    } 
    if (levelA == MARK && levelB == SPACE) { // reversed compared to RC5
      // 1 bit
      data = (data << 1) | 1;
    } 
    else if (levelA == SPACE && levelB == MARK) {
      // zero bit
      data <<= 1;
    } 
    else {
      return ERR; // Error
    } 
  }
  // Success
  results->bits = nbits;
  results->value = data;
  results->decode_type = RC6;
  return DECODED;
}
```

De por si...es un poco compleja la implementación...vas a tener que leer bastante.


----------



## rody257 (Sep 13, 2011)

hora esta bueno tu proyecto pero mi problema es. q dispondo de un pic 16f877 ze podria adaptar ese codigo para este pic. por q este trabaja con un oscilador de 4Mhz nada mas.


----------



## Moyano Jonathan (Sep 13, 2011)

> hora esta bueno tu proyecto pero mi problema es. q dispondo de un pic 16f877 ze podria adaptar ese codigo para este pic. por q este trabaja con un oscilador de 4Mhz nada mas.



Si usas CCS es perfectamente portable, solo tendrías que cambiar las definiciones de procesador y algunas definiciones pero se puede adaptar.

Un saludo !


----------



## rody257 (Sep 13, 2011)

Moyano Jonathan dijo:


> Si usas CCS es perfectamente portable, solo tendrías que cambiar las definiciones de procesador y algunas definiciones pero se puede adaptar.
> 
> Un saludo !



el pic 16f877a tambien funciona con oscilador de 20Mhz?



			
				rody257 dijo:
			
		

> el pic 16f877a tambien funciona con oscilador de 20Mhz?



o´ como lo modifico para q fucione con un oscilador de 4 Mhz


----------



## J2C (Sep 13, 2011)

Rody257

Pues sacate tus dudas mirando la datasheet ( http://ww1.microchip.com/downloads/en/DeviceDoc/39582b.pdf ) del mismo en la pagina oficial de MicroChip!.

Saludos, JuanKa.-


----------



## rody257 (Sep 14, 2011)

J2C dijo:


> Rody257
> 
> Pues sacate tus dudas mirando la datasheet ( http://ww1.microchip.com/downloads/en/DeviceDoc/39582b.pdf ) del mismo en la pagina oficial de MicroChip!.
> 
> Saludos, JuanKa.-




ok. gracias  por todo. 
saludos desde LIMA-PERU


----------



## juan21 (Sep 22, 2011)

Hola tengo un problema al adaptar tu codigo del decodificador RC5 moyano, me preguntaba si me puedes explicar algunas partes de del programa que no comprendo. El pic que estoy utilizando es un 16f628a ya arme el circuito solo que sin el otro integrado que utilizas, como dije arme el circuito y lo probe con un control philips que supuestamente maneja ese protocolo pero no logro obtener las salidas que deseo.


----------



## biker2k3 (Sep 23, 2011)

juan21 dijo:


> Hola tengo un problema al adaptar tu codigo del decodificador RC5 moyano, me preguntaba si me puedes explicar algunas partes de del programa que no comprendo. El pic que estoy utilizando es un 16f628a ya arme el circuito solo que sin el otro integrado que utilizas, como dije arme el circuito y lo probe con un control philips que supuestamente maneja ese protocolo pero no logro obtener las salidas que deseo.



Hola yo hice un decodificador muy simple con pic 16f628 o 12f629 sin ningun integrado extrerno, del sensor al pic. Te dejo la parte mas importante..

pausa = 1710                      ;Tiempo ke dura un cilo "01" o "10"

Senal:
Command = 0
if pinIR=0 then
Command.bit13 = 1                 ;bit 13  start bit
pauseus 2066                      ;primer pausa para ke kede en medio del sig bit
;pauseus 1300
else : goto senal :endif

if pinIR=1 then
Command.bit12 = 0 : Else : Command.bit12 = 1 : endif : pauseus pausa ;pauseus 1874 Start bit
if pinIR=1 then
Command.bit11 = 0 : Else : Command.bit11 = 1 : endif : pauseus pausa ;pauseus 1693 toggle bit
if pinIR=1 then
Command.bit10 = 0 : Else : Command.bit10 = 1 : endif : pauseus pausa ;pauseus 1693
if pinIR=1 then
Command.bit9 = 0  : Else : Command.bit9 = 1  : endif : pauseus pausa ;pauseus 1714
if pinIR=1 then
Command.bit8 = 0  : Else : Command.bit8 = 1  : endif : pauseus pausa ;pauseus 1718
if pinIR=1 then
Command.bit7 = 0  : Else : Command.bit7 = 1  : endif : pauseus pausa ;pauseus 1711
if pinIR=1 then
Command.bit6 = 0  : Else : Command.bit6 = 1  : endif : pauseus pausa ;pauseus 1666
if pinIR=1 then
Command.bit5 = 0  : Else : Command.bit5 = 1  : endif : pauseus pausa ;pauseus 1766
if pinIR=1 then
Command.bit4 = 0  : Else : Command.bit4 = 1  : endif : pauseus pausa ;pauseus 1640
if pinIR=1 then
Command.bit3 = 0  : Else : Command.bit3 = 1  : endif : pauseus pausa ;pauseus 1762
if pinIR=1 then
Command.bit2 = 0  : Else : Command.bit2 = 1  : endif : pauseus pausa ;pauseus 1671
if pinIR=1 then
Command.bit1 = 0  : Else : Command.bit1 = 1  : endif : pauseus pausa ;pauseus 1620
if pinIR=1 then
Command.bit0 = 0  : Else : Command.bit0 = 1  : endif

if Command.bit12 = 0 then           ;Si la señal viene invertida la arregla
command = command ^ %01111111111111 ; invierte el estado del bit 0 de B0
endif


----------



## D@rkbytes (Sep 23, 2011)

Saludos. 
Aqui les dejo algo que tenia por ahi sobre el RC5 de PHILIPS
Lo acabo de compilar para ver que todo estubiera bien.
Esta en ASM y viene completo. BY4NOW


----------



## juan21 (Sep 23, 2011)

biker2k3 dijo:


> Hola yo hice un decodificador muy simple con pic 16f628 o 12f629 sin ningun integrado extrerno, del sensor al pic. Te dejo la parte mas importante..
> 
> pausa = 1710                      ;Tiempo ke dura un cilo "01" o "10"
> 
> ...






Estoy interesado en tu codigo podrias explicarme como funciona o ponerlo completo esque llevo algo de tiempo tratando de hacer funcionar un decodificador de ese protocolo


----------



## biker2k3 (Sep 23, 2011)

juan21 dijo:


> Estoy interesado en tu codigo podrias explicarme como funciona o ponerlo completo esque llevo algo de tiempo tratando de hacer funcionar un decodificador de ese protocolo



Todavia se puede mejorar mucho igual, la verda no profundise mucho en el RC5 porque tengo mas controles NEC32. 
 Tengo puesto un circuito para prender y apagar la luz de mi piesa y tb para manejar la PC con el mismo control asi me tiro en la cama apago la luz y pongo pelis 

Aca te dejo un video de un ejemplo que hice, decodifica el NEC32 y muestra en el LCD la tecla presionada. 




Si queres pasame tu mail por privado y te ayudo con el proyecto.


----------



## juan21 (Sep 23, 2011)

biker2k3 dijo:


> Todavia se puede mejorar mucho igual, la verda no profundise mucho en el RC5 porque tengo mas controles NEC32.
> Tengo puesto un circuito para prender y apagar la luz de mi piesa y tb para manejar la PC con el mismo control asi me tiro en la cama apago la luz y pongo pelis
> 
> Aca te dejo un video de un ejemplo que hice, decodifica el NEC32 y muestra en el LCD la tecla presionada. http://www.youtube.com/watch?v=p3y2olnjM1A
> ...




Lamentablemente aun no puedo mandarte un mensaje privado pero podemos platicar aqui en el foro.
El programa que pusiste esta en ccs? o en que lenguaje algunas instrucciones se me hacen conocidas como a visualBasic pero no estoy seguro. En estos momentos estoy utilizando el ccs
ya trate de hacer un codigo con la logica que vi de tu programa pero tuve algunos problemitas 
con el manejo de los bits y con las operaciones logicas, obtuve un codigo muy largo ya que la operacion de XOR la tuve que hacer bit por bit. Me falta probarlo o si tienes alguna sugerencia
sea bienvenida!!!


----------



## biker2k3 (Sep 23, 2011)

juan21 dijo:


> Lamentablemente aun no puedo mandarte un mensaje privado pero podemos platicar aqui en el foro.
> El programa que pusiste esta en ccs? o en que lenguaje algunas instrucciones se me hacen conocidas como a visualBasic pero no estoy seguro. En estos momentos estoy utilizando el ccs
> ya trate de hacer un codigo con la logica que vi de tu programa pero tuve algunos problemitas
> con el manejo de los bits y con las operaciones logicas, obtuve un codigo muy largo ya que la operacion de XOR la tuve que hacer bit por bit. Me falta probarlo o si tienes alguna sugerencia
> sea bienvenida!!!



Mmm yo no use operaciones XOR ni nada raro, lo programe en Picbasic pro con el Microcode Studio, pero sino te recomiendo el IDE de Proton que es muy similar pero un poco mejor.


----------



## juan21 (Sep 25, 2011)

biker2k3 dijo:


> Mmm yo no usé operaciones XOR ni nada raro, lo programe en Picbasic pro con el Microcode Studio, pero si no te recomiendo el IDE de Proton que es muy similar pero un poco mejor.




Oye. ¿Puedes decirme como hacerlo en picBasic? Es que ese programa ya lo tengo instalado en mi maquina y he estado trabajándolo junto con visual basic.
Trate de hacer el programa pero creo que necesito un archivo extra porque solo puedo trabajar con el pic 18f4550 y no aparece otro. ¿Que compilador debo elegir??

La operación Xor me refería a la instrucción 
command = command ^ %01111111111111 ; invierte el estado del bit 0 de B0
endif

Según yo cuando colocas "^" es porque quieres aplicar la operación XOR, pero puedo equivocarme.
Esta instrucción no la comprendo del todo. ¿Por qué hacerla y que función tiene?
Y si no la hago tendrá alguna consecuencia? 

El código que pasé en Mplab utilizando el compilador ccs es el siguiente.
Me basé en tu lógica o en la parte de programa que pusiste anteriormente.


```
struct empaquetado {                    ///Todo esto es para tratar de hacer lo mismo que tu
    unsigned int bit0:1;         /// con la variable comando, creo una estructura 
    unsigned int bit1:1;                  /// empaquetado con 14 variables las cuales 
    unsigned int bit2:1;                  /// corresponden a cada bit de la señal del control
    unsigned int bit3:1;
    unsigned int bit4:1;
    unsigned int bit5:1;
    unsigned int bit6:1;
    unsigned int bit7:1;
    unsigned int bit8:1;
    unsigned int bit9:1;
    unsigned int bit10:1;
    unsigned int bit11:1;
    unsigned int bit12:1;
    unsigned int bit13:1;
    
    
} paquete;

///////////////////////////Dentro de la funcion principal tengo el sig. codigo basado en el tuyo

    Senal:                              //Etiqueta del goto
    paquete = 0;                    //Todas las variables de la estructura a cero
    if (!input(IR_RECEPTOR))    // Pregunto si la entrada del pin es cero
    {
    paquete.bit13=1;              // Pongo el bit13=1,,para acceder a cada bit de la 
                                          // estructura debo poner paquete.bitx=
    delay_us(1330);               //primer pausa para ke kede en medio del sig bit
    if(paquete.bit13)              //segun yo el valor es 1330 en el retardo y no 2066
    {
            codigo(); //funcion donde pregunto por los demas bits



              }

///////////////////////////////Función código
//Esta parte del código va checando la trama mandada por el control de tal forma que checa cada bit de
// la trama compuesta por 14 bits, los retardos son los adecuados para que separe a cada bit 
// si al checar cae en un uno es porque es un uno y en caso contrario si cae en un cero corresponde a un cero, en esto según yo como estoy tomando la salida de un receptor donde
// la señal de salida siempre sera un uno al recibir la señal de control se hace cero
// y obtendremos una señal invertida de como la muestran normalmente
/////////////////////////////////////////////////////////////////////////////////////////////////
//
    
int codigo()
{
if (input(IR_RECEPTOR)){     paquete.bit12 = 1;}//Asigno valor a cada bit dependiendo de la
else{                        paquete.bit12 = 0;}// entrada
delay_us(pausa);

if (input(IR_RECEPTOR)){    paquete.bit11 = 1;}
else{            paquete.bit11 = 0;}
  delay_us(pausa) ;

if (input(IR_RECEPTOR)){    paquete.bit10 = 1;}
else{            paquete.bit10 = 0;}
  delay_us(pausa);

if (input(IR_RECEPTOR)){    paquete.bit9 = 1;}
 else{                     paquete.bit9 = 0 ;}
 delay_us(pausa);

if (input(IR_RECEPTOR)){    paquete.bit8 = 1;}
 else {            paquete.bit8 = 0;}
delay_us(pausa);

if (input(IR_RECEPTOR)){    paquete.bit7 = 1;}
 else {            paquete.bit7 = 0;}
delay_us( pausa) ;

if (input(IR_RECEPTOR)){    paquete.bit6 = 1;}
else{            paquete.bit6 = 0;}
delay_us (pausa );

if (input(IR_RECEPTOR)){    paquete.bit5 = 1;}
else {            paquete.bit5 = 0;}
delay_us( pausa );

if (input(IR_RECEPTOR)){    paquete.bit4 = 1;}
else         {    paquete.bit4 = 0;}
delay_us( pausa );

if (input(IR_RECEPTOR)){    paquete.bit3 = 1;}
 else{            paquete.bit3 = 0;}
delay_us( pausa );

if (input(IR_RECEPTOR)){    paquete.bit2 = 1;}
else {                     paquete.bit2 = 0;}
delay_us( pausa );

if (input(IR_RECEPTOR)){    paquete.bit1 = 1;}
else {            paquete.bit1 = 0;}
delay_us (pausa) ;

if (input(IR_RECEPTOR)){    paquete.bit0 = 1;}
else {            paquete.bit0 = 0; }

///////////En esta parte no se como hacer la operación que hiciste la de invertir los bits
/////lo puedo hacer uno por uno pero es muy largo 
if (paquete.bit12) ;//Si la señal viene invertida la arregla

if (paquete.bit13){     paquete.bit13 = 0;}//Por ejemplo para invertir el estado del bi13
else{                        paquete.bit13 = 1;}//pregunto si es uno si es cierto lo pongo a 
                                                                    // cero y si es cero lo pongo a uno y así para 
                                                                    // todos los bits bit12,bit11,bit10,....bit0
// Depués regresaríamos a donde fue llamada la función tecla y en ese espacio checaría los 
// últimos bits para saber la tecla que fue presionada y hacer algo por ejemplo mostrarlo en 
// el lcd prender un led con el peso correspondiente a la tecla o activar un motor,etc.
```

 Bueno hasta aquí mis problemas, espero y puedas ayudarme o seguir aconsejándome como lo
has hecho, esperando que comprendas lo que trato de hacer en mi código y las explicaciones que en él doy.
Sin nada más me despido.


----------



## biker2k3 (Sep 25, 2011)

juan21 dijo:


> Oye puedes decirme como hacerlo en picBasic es que ese programa ya lo tengo instalado en mi maquina y he estado trabajándolo junto con visual basic, trate de hacer el programa pero creo que necesito un archivo extra porque solo puedo trabajar con el pic 18f4550 y no aparece otro y que compilador debo elegir??
> 
> La operación Xor me refería a la instrucción
> command = command ^ %01111111111111 ; invierte el estado del bit 0 de B0
> ...



Perdóname, ni me acuerdo porque puse esa operación OR.
El otro día revisando el código, me preguntaba; ¿para que puse eso?


----------



## juan21 (Sep 27, 2011)

Otra preguntilla, tubiste problemas con los tiempos?, quiero decir al comparar los tiempos del protocolo teorico con el practico, para dar los retardos con el valor que pusiste.
He estado probando un control philips y el tiempo que tiene la señal varia un poco el ciclo alto dura mas que el bajo que el periodo es el mismo. En mis mediciones el ciclo alto es de 1ms aprox y el bajo como de 725us aprox. Quiciera saber si tubiste un problema asi


----------



## biker2k3 (Sep 28, 2011)

juan21 dijo:


> Otra preguntilla, tubiste problemas con los tiempos?, quiero decir al comparar los tiempos del protocolo teorico con el practico, para dar los retardos con el valor que pusiste.
> He estado probando un control philips y el tiempo que tiene la señal varia un poco el ciclo alto dura mas que el bajo que el periodo es el mismo. En mis mediciones el ciclo alto es de 1ms aprox y el bajo como de 725us aprox. Quiciera saber si tubiste un problema asi



En este protocolo un 1 es una señal asi.. 1-0 y un cero es 0-1, osea que midiendo el tiempo que esta en cero no se puede decodificar bien porque si tenes por ejemplo un cero y un uno, la señal seria 0110, si medis el tiempo va a parecer un 1 largo, pero en verdad la mitad de ese 1 es de un bit y la otra mitad del bit siguiente.


----------



## juan21 (Sep 28, 2011)

biker2k3 dijo:


> En este protocolo un 1 es una señal asi.. 1-0 y un cero es 0-1, osea que midiendo el tiempo que esta en cero no se puede decodificar bien porque si tenes por ejemplo un cero y un uno, la señal seria 0110, si medis el tiempo va a parecer un 1 largo, pero en verdad la mitad de ese 1 es de un bit y la otra mitad del bit siguiente.





MMMMMMMMMM eso me ha llevado a cambiar de control y me he decidido por un sony ya que sy protocolo es mas facil de decodificar segun yo.Ahora  solo intento medir el tiempo que dura el estado alto ya que este protocolo un 1 se define como un nivel bajo de 600us y un nivel alto de 1200us, el 0 se define como un nivel bajo de 600us y un nivel alto de 600us.
EL nivel alto es la clave ya que si es 1200us es un 1 y si es 600us es un cero.
Mis pruebas ahora estan concentradas en eso ahora gracias por los consejos que me has dado me han hayudado


----------



## johenrod (Sep 29, 2011)

cordial saludo,,,
dado que esto de los protocolos y los tiempos de duracion de los pulsos y bits son tan rapidos se ve uno en la necesidad de visualizarlos,, por casualidad saben de un programita que vaya acompañado de un circuito para hacer un analizador digital, pues los que venden son costositos,,,
gracias.......


----------



## biker2k3 (Sep 29, 2011)

johenrod dijo:


> cordial saludo,,,
> dado que esto de los protocolos y los tiempos de duracion de los pulsos y bits son tan rapidos se ve uno en la necesidad de visualizarlos,, por casualidad saben de un programita que vaya acompañado de un circuito para hacer un analizador digital, pues los que venden son costositos,,,
> gracias.......



Compra el TSOP1738, conectalo a la placa de sonido y grabalo con el GoldWave, yo hice asi y me ayudo muchisimo.

Tambien podes hacer el circuito para conectarlo al puerto serial y usar el winlirc


----------



## ArArgonath (Nov 5, 2011)

Holas a todos.

He estado leyendo este hilo e intente adaptar el código de Moyano a Proton IDE, pero me ha resultado muy dificil, bueno es mas que nada por que no me manejo muy bien en ccs y el tema de las interupciones no las se usar. Entonces me preguntaba si es que me podrian ayudar a corregir los errores que cometo, si es con ejemplos mejor aun.

Bueno el codigo que he escrito:


```
'****************************************Configuración inicial************************************
 
 Device = 16F877                'Usamos el pic16f877a
 Xtal = 4                       'Con un cristal de 4 mhz
 
 OPTION_REG = %00000000
 INTCON = %10010000
 
 '*********************************Definimos la conexión del lcd***********************************
 
 LCD_DTPin = PORTB.4       
 LCD_RSPin = PORTB.3
 LCD_ENPin = PORTB.1
 LCD_Interface = 4
 LCD_Lines = 2
 LCD_Type = 0
 
 '*************************************Declaramos variables****************************************
 
 Dim Datos As Word
 Dim i As Byte
 Dim D0 As Byte
 Dim D1 As Byte
 Dim Resultado As Byte
 Dim flag As Bit
 
 '*************************************Constantes del sistema**************************************
 
 Symbol Cuartodebit = 440
 Symbol Mediobit = 880
 Symbol Receptor = PORTB.0
 Symbol Ledtrama = PORTC.5
 
 '****************************************Seteamos puertos*****************************************
 
 TRISB.0 = 1
 TRISC.5 = 0
 
 '***********************************Inicializamos interrupción************************************
 
 On Interrupt GoTo Decodifica_rc5
 
 '******************************Comienza el lazo de funcionamiento*********************************
 
 Lazo:
 
  DelayMS 1
  
  Ledtrama = 0
  If Resultado > 0 Then
   Datos = Resultado
   Datos = Datos & $007F
  End If
  Ledtrama = 0
  If flag = 0 Then
   Cls
   flag = 1
  End If
  Print At 1, 1, "Comando ", Dec Datos
  
  GoTo Lazo
  
 '*************************************Rutina de interrupción**************************************
 
 Disable
 Decodifica_rc5:
 
  D0 = 0
  D1 = 65535
  
  While Receptor = 0
   DelayUS Cuartodebit
   For i = 0 To 13
    DelayUS Mediobit
    D1 = D1 * 2 + Receptor
    DelayUS Mediobit
    D0 = D0 * 2 + Receptor
   Next
  Wend
  If (D0 ^ D1) = $3FFF Then
   Resultado = (D1 & $3FFF)
   Ledtrama = 1
  Else
   Resultado = 0
  End If
  
  INTCON = %10010000
 
 Resume
 Enable
```

Nota: Cuando lo pruebo en el pic 16f877 real, el programa no hace nada solo muestra en la lcd el número 65

Estoy usando un IRM8601 conectado al pin RB0 y el led de trama esta conectado al pin RC5


----------



## ArArgonath (Nov 14, 2011)

Hola a todos he estado trabajando en el código de Moyano y lo he simulado en Proteus y todo ha funcionado de maravillas, pero el codigo en ccs asi como esta no me sirve, necesito pasarlo a Proton IDE para poder implementarlo en otro codigo de un pre-digital. 

Bueno, lo he pasado a Proton IDE pero ese no me hace nada. Es este:

```
Device = 16F877
Xtal = 20

Symbol Cuartodebit = 440
Symbol Mediobit = 880
Symbol GIE = INTCON.7          ' Global Interrupt Enable
Symbol INTEDG = OPTION_REG.6   ' Interrupt Edge Select bit
Symbol INTE = INTCON.4         ' RB0/INT External Interrupt Enable bit
Symbol INTF = INTCON.1         ' RB0/INT External Interrupt Flag bit 

Dim Decodifica_rc5 As Word

On_Hardware_Interrupt GoTo Ext_isr

GoTo Main

Ext_isr:
        GoSub FDecodifica_rc5
        PORTA.0 = 1
        INTF = 0
        Context Restore
        
FDecodifica_rc5:
                Dim D0 As Word
                D0 = 0
                Dim D1 As Word
                D1 = 65535
                Dim i As Byte
                If PORTB.0 = 0 Then
                   DelayUS Cuartodebit
                   For i = 0 To 13
                       DelayUS Mediobit
                       D1 = D1 * 2 + PORTB.0
                       DelayUS Mediobit
                       D0 = D0 * 2 + PORTB.0
                   Next i
                   If (D0 ^ D1) = 65535 Then
                      Decodifica_rc5 = (D1 & $3fff)
                   Else
                      Decodifica_rc5 = 0
                   End If
                EndIf
                Return
                
Main:
     TRISB = %00000001
     TRISA = %00000000
     TRISC = %00000000
     PORTA.0 = 0
     GIE = 0
     INTEDG = 0
     INTE = 1
     GIE = 1
     PORTC = 0
     
Loop:
           Dim Dato As Word
           Dato = Decodifica_rc5
           Dato = Dato & $007f
           If Dato = 1 Then PORTC = $01
           If Dato = 2 Then PORTC = $02
           If Dato = 3 Then PORTC = $04
           If Dato = 4 Then PORTC = $08
           If Dato = 12 Then PORTC = $00
           PORTA.0 = 0
           GoTo Loop
```

Es caso es que no se que es lo que me esta faltando para que funcione, o se si es que estoy implementado mal la interrupción o otra cosa.

Nota: la estructura del programa la saque de la ayuda de Proton IDE


----------



## josb86 (Feb 13, 2012)

tengo una pregunta para que utilizan exactamente  el comando XOR en el primer ejemplo?
es algo asi como para comprobar que se allan tomado bien las muestras de señal osea todo tiene que ser contrarios entre si?


----------



## Moyano Jonathan (Feb 13, 2012)

> Hola a todos he estado trabajando en el código de Moyano y lo he simulado en Proteus y todo ha funcionado de maravillas, pero el codigo en ccs asi como esta no me sirve, necesito pasarlo a Proton IDE para poder implementarlo en otro codigo de un pre-digital.



Mirate estos 2 hilos: 

http://www.mikroe.com/forum/viewtopic.php?t=5497

http://www.mikroe.com/forum/viewtopic.php?t=6996



> tengo una pregunta para que utilizan exactamente el comando XOR en el primer ejemplo?
> es algo asi como para comprobar que se allan tomado bien las muestras de señal osea todo tiene que ser contrarios entre si?



Exacto el comando sirve para detectar muestras erroneas comprobando el contenido de 2 buffers.


----------



## miborbolla (Mar 13, 2012)

Hola compañeros. Dejo aquí como utilizar en proton la FUNCION SONYIN:

Esta función viene implementada en la versión 3.5.2.7



```
'****************************************************************
'*  Name    : DECSONYIR.BAS                                      *
'*  Author  : Miguel Angel Borbolla Bonomi                      *
'*  Notice  : Copyright (c) 2012 CIBERTLAN                      *
'*          : All Rights Reserved                               *
'*  Date    : 06/03/2012                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************

Device = 18F2550 
Xtal = 48 

Declare Sonyin_Pin = PORTB.0  ' se asigna el pin RB0 (pin 21) para recibir datos del receptor Infrarojo
Dim SONYIN_WORD As Word ' Se crea una variavle de "palabra completa" para recibir el tren de datos
' Se hace un ALIAS de el BYTE BAJO que contiene los comandos de la variable SONYIN_WORD
Dim SONY_COMMAND As SONYIN_WORD.LowByte
' Se hace un ALIAS de el Byte ALTO que contiene el tipo de systema de la variable SONYIN_WORD
Dim SONY_SYSTEM As SONYIN_WORD.HighByte

' Se crean alias del puerto B (Pin 22 al 28) con el nombre LEDX respectivamente

Symbol LED1 PORTB.1
Symbol LED2 PORTB.2
Symbol LED3 PORTB.3
Symbol LED4 PORTB.4
Symbol LED5 PORTB.5
Symbol LED6 PORTB.6
Symbol LED7 PORTB.7



All_Digital = On ' se asignas todas las entradas como digitales

While 1 = 1 ' Se crea un Loop Infinito
Repeat
SONYIN_WORD = SonyIn ' Se recive el tren de datos del receptor infrarojo
Until SONY_COMMAND<> 255 ' Se queda repitiendose la recepcion hasta que el byte bajo (comandos) sea diferente a 255

'Se procesa la informacion del comando recibido y se prende el led correspondiente

If SONY_COMMAND=0 Then High LED1
If SONY_COMMAND=1 Then High LED2
If SONY_COMMAND=2 Then High LED3
If SONY_COMMAND=3 Then High LED4
If SONY_COMMAND=4 Then High LED5
If SONY_COMMAND=5 Then High LED6
If SONY_COMMAND=6 Then High LED7

DelayMS 1000  ' espera 1 segundo
PORTB=0       ' Se borra el contenido del puerto B y se repite el Loop para recibir otro dato.
Wend
```




Reciban Saludos.



Nota.- Por otro lado, en Proton existe la función RC5in que es el protocolo en comento de este post, yo en particular no la he utilizado ya que no cuento con algún transmisor con el protocolo RC5, sin embargo es muy similar al programa que comparto y el circuito seria el mismo,  recuerden que este programa sirve para controles SONY o un universal programandolo como si fuera para un televisor SONY.  Estas funciones (SONYIN y RC5in vienen implementadas en la versión de proton 3.5.2.7)


----------



## Moyano Jonathan (Mar 13, 2012)

Quiero decirles que a todos lo que quieran decodificar los protocolos IR usando BASIC o similares...van a tener que hacerlo por timer's e interrupciones...por que las rutinas de delay de dichos compiladores no genera tiempos exactos..por lo que les va a resultar muy complejo tratar de portar mi programa de manera directa...

Un saludo !

PD: Si no hagan lo que dice miborbolla:





> Estas funciones (SONYIN y RC5in vienen implementadas en la version de proton 3.5.2.7)


----------



## miborbolla (Mar 13, 2012)

Hola Moyano, al igual que tu,  estoy mudando el código que expones a un AVR, tu código el cual me ha funcionado muy bien en PIC´s no a sido tanto rollo, aunque ando aprendiendo, todavía yo lo estoy mudando a codevision que se me hace un excelente compilador y tengo mis detalles que a bien no entiendo que sucede, la idea es hacer una libreria .H que se pueda incluir en cualquier programa, si lo logro compartiré esta librería y como se usa con todos ustedes.

Saludos


----------



## johenrod (Abr 17, 2012)

cordial saludo, quisiera preguntar,,
este protocolo tambien lo manejan los controles de los radios instalados en los carros?? de marcas como sony pionner jvc kenwwood etc,,
gracias de antemano...


----------



## Moyano Jonathan (Abr 17, 2012)

> cordial saludo, quisiera preguntar,,
> este protocolo tambien lo manejan los controles de los radios instalados en los carros?? de marcas como sony pionner jvc kenwwood etc,,
> gracias de antemano..



No precisamente, para poder decodificar ese tipo de protocolo, vas a tener que leer este articulo: 
http://picmania.garcia-cuervo.net/experimentos_ir.php#RecTramas
http://picmania.garcia-cuervo.net/experimentos_ir.php#DecoProt
http://picmania.garcia-cuervo.net/experimentos_ir.php#ProcCom

Saludos !


----------



## johenrod (Abr 18, 2012)

Agradezco ampliamente el que te hayas tomado la molestia de reponderme, estudiare los enlaces,, crees que por este medio puedas ayudarme con mi proposito, hago pequeños programas en ASM.
lo que intento es con un pic reemplazar el contro de estos radios de carro.
saludos...y gracias.


----------



## Moyano Jonathan (Abr 18, 2012)

> crees que por este medio puedas ayudarme con mi proposito, hago pequeños programas en ASM.


Yo te puedo ayudar con los programas para C. En ASM no lo manejo de manera fluida; ahora para que podamos ayudar, vas a tener que ponerte a investigar como es el protocolo de tu control y ver la forma de poder decodificarlo. Luego te podremos ayudar con dudas puntuales.
Saludos !


----------



## david23 (May 28, 2012)

miborbolla dijo:


> Hola comapñeros dejo aqui como utilizar en proton la FUNCION SONYIN:
> 
> Esta función viene implementada en la version 3.5.2.7
> 
> ...





me puedes pasar el diagrama del proyecto la verdad me interesa y me gustaria implementarlo muchas gracias


----------



## miborbolla (May 29, 2012)

Mi estimado david23: implementarlo es de lo mas simple, sin embargo y a petición tuya dejo anexado un pequeño tutorial que realice para otro foro, pero al ser de mi autoria los comparto por aquí sin mas...espero te sirva

http://www.4shared.com/office/Hu146NmS/decodificador_sony.html

Solo te comento que el programa listado en el archivo pdf tiene una pequeña linea o comando, y que es:

Declare PROTON_START_ADDRESS = $1000

Debes quitarla, ya que en el ejemplo que dejo anexado, esta pensada para usarse con el bootloader de microchip, así que simplemente elimina esta linea y te funcionara de maravilla o puedes usar el ejemplo que deje anexado en este foro y al que haces referencia.....que finalmente es el mismo listado sin la linea en comento. De la misma manera puedes omitir el conector USB que encontraras en el diagrama, ya que en este ejemplo no se utiliza para nada.


Saludos


----------



## ArArgonath (May 31, 2012)

hola a todos se me olvidaba decir que yo también implemente mi propia rutina para decodificar protocolo rc5, esta escrita con el compilador proton ide y solo necesita conectar el receptor de infra-rojos a la patita de interrupción externa del pic:


```
'****************************************************************
'*  Name    : Control remoto .BAS                               *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2011 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 20-11-2011                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************

Optimiser_Level = 2              ' Activa la optimización de código en Proton IDE
                                 ' 0 = Desactivado ; 1 = pic12f family ; 2 = pic16f family ; 3 = pic18f family
Device = 16F88
Xtal = 10

Symbol INTF   = INTCON.1         ' RB0 External Interrupt Flag
Symbol INTE   = INTCON.4         ' RB0 External Interrupt Enable
Symbol GIE    = INTCON.7         ' Global Interrupt Enable
Symbol INTEDG = OPTION_REG.6     ' Flag = 0 Flanco bajada. Flag = 1 Flanco subida.

Symbol Pausa = 888
Symbol Espacio = 88

On_Interrupt GoTo Interrupcion   ' Interrupción por Hardware (es la más rápida).

GIE    = 1                       ' Activa interrupciones generales.
INTE   = 1                       ' Activa la interrupción externa RB0/INT.
INTEDG = 0                       ' Hace que inicialmente la interrupción se dispare
                                 ' por flanco de bajada.

TRISA = 0                                                                              
TRISB.0 = 1
DelayMS 500 'Espero medio segundo
           
Dim decodifica_rc5 As Word
Dim dato As Byte
 
While 1=1                        ' |------ Programa Principal ------|
   
   GoSub conversion
   If dato = 1 Then
      PORTA = $01
      decodifica_rc5 = 0
      dato = 0
   End If
   If dato = 2 Then
      PORTA = $02
      decodifica_rc5 = 0
      dato = 0
   End If
   If dato = 3 Then
      PORTA = $03
      decodifica_rc5 = 0
      dato = 0
   End If
   If dato = 4 Then
      PORTA = $04
      decodifica_rc5 = 0
      dato = 0
   End If
   If dato = 12 Then
      PORTA = $00
      decodifica_rc5 = 0
      dato = 0
   End If
   

Wend                             ' |--------------------------------|

conversion:
           dato = decodifica_rc5
           dato = dato & $007f
           Return
             
End                              

    
Interrupcion:                 '-------- Decodificador de RC5 --------------
       
    Context Save              ' Salva en contexto de los registros antes de operar con la interrupción.

If INTE = 1 And INTF = 1 Then ' Nos aseguramos que la interrupción sea externa y no otra.

 While PORTB.0 = 0         'Start bits
  decodifica_rc5.13 = 1
  DelayUS (2 * Pausa)
  If PORTB.0 = 0 Then
   decodifica_rc5.12 = 1
   DelayUS Pausa
  End If                   'Toggle bit
  If PORTB.0 = 0 Then
   decodifica_rc5.11 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.11 = 1
  DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then      'MSB direction bit
   decodifica_rc5.10 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.10 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then
   decodifica_rc5.9 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.9 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then
   decodifica_rc5.8 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.8 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then
   decodifica_rc5.7 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.7 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then      'LSB direction bit
   decodifica_rc5.6 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.6 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then      'MSB command Bit
   decodifica_rc5.5 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.5 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then
   decodifica_rc5.4 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.4 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then
   decodifica_rc5.3 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.3 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then
   decodifica_rc5.2 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.2 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then
   decodifica_rc5.1 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.1 = 1
   DelayUS (2 * Pausa)
  End If
  If PORTB.0 = 0 Then      'LSB command Bit
   decodifica_rc5.0 = 0
   DelayUS (2 * Pausa)
  Else
   decodifica_rc5.0 = 1
   DelayUS (2 * Pausa)
  End If
  DelayMS Espacio   
 Wend
     
    INTF = 0                  ' Borra el "flag" de la interrupción RB0/INT
End If
     
                              ' para poder permitir la siguiente interrupción.
    Context Restore           ' Restablece el contexto de los registros tal como estaban antes de la
                              ' interrupción.
```


----------



## electrobicho (Jun 2, 2012)

Se ven interesantes para realizar comunicaciones IR, probare con sus ejemplos, desde ya se les agradece, una pregunta, que IR debo usar para protocolo RC5, tengo un TSOP 1736, pero no se si sea el adecuado, saludos desde Salina Cruz, Oaxaca


----------



## david23 (Jun 2, 2012)

miborbolla dijo:


> Mi estimado david23: implementarlo es de lo mas simple, sin embargo y a petición tuya dejo anexado un pequeño tutorial que realice para otro foro, pero al ser de mi autoria los comparto por aquí sin mas...espero te sirva
> 
> http://www.4shared.com/office/Hu146NmS/decodificador_sony.html
> 
> ...


te agradesco amigoo


----------



## crpalza (Nov 16, 2013)

hola una consulta, el proyecto tambien funcionaria con un PIC 18F4550???


----------



## D@rkbytes (Nov 16, 2013)

crpalza dijo:


> hola una consulta, el proyecto tambien funcionaria con un PIC 18F4550???


Obviamente si. De hecho muchos programas para PIC pueden funcionar en otros PIC, si este cuenta con los requisitos del programa (Puertos, Módulos, Registros, etc.)
El PIC18F4550 es incluso demasiado grande para este tipo de proyectos.

Saludos.


----------



## crpalza (Nov 17, 2013)

Tengo en cuenta eso D@rkbytes. Lo q*ue* sucede es q*ue* estoy realizando este proyecto para un taller y la condición es q*ue* utilice el pic18f4550 y tenga salida a 8 focos (ganas de molestar del ingeniero a cargo) pero bueno la cuestión es q*ue* si es aplicable, ¿sólo tendría q*ue* cambiar las líneas de código de entrada como de salida verdad? Gracias.


----------



## D@rkbytes (Nov 17, 2013)

crpalza dijo:


> Tengo en cuenta eso D@rkbytes. Lo q*ue* sucede es q*ue* estoy realizando este proyecto para un taller y la condición es q*ue* utilice el pic18f4550 y tenga salida a 8 focos (ganas de molestar del ingeniero a cargo) pero bueno la cuestión es q*ue* si es aplicable, ¿sólo tendría q*ue* cambiar las líneas de código de entrada como de salida verdad? Gracias.


Puedes cambiarlas o dejarlas como están. El PIC18F4550 tiene 5 puertos, puedes usar el que más se adapte a lo que quieres hacer.

¿A que proyecto te refieres? Se han posteado varios.


----------



## crpalza (Nov 17, 2013)

Al primer proyecto, el q*ue* está publicado por moyano. Tengo q*ue* hacer lo mismo solo q*ue* con el PIC18F4550 y en  lugar de led's deben ser focos.


----------



## D@rkbytes (Nov 17, 2013)

crpalza dijo:


> Al primer proyecto, el q*ue* está publicado por moyano. Tengo q*ue* hacer lo mismo solo q*ue* con el PIC18F4550 y en  lugar de led's deben ser focos.


Pues no tendrás problemas. Te repito, el PIC18F4550 hasta te quedará grande para ese proyecto.

Algo que debes tener en cuenta es la configuración adecuada de los registros y sobre todo la palabra de configuración que usarás para hacer funcionar correctamente al PIC18F4550.

Suerte.


----------



## crpalza (Nov 17, 2013)

gracias, los mantendre al tanto y ayudare con mi aporte sobre la implementacion de mi proyecto, una ultima pregunta el lenguaje de programacion y software utilizado para el codigo es mikroC pro u otro? gracias.


----------



## D@rkbytes (Nov 17, 2013)

crpalza dijo:


> Una última pregunta. ¿El lenguaje de programación y software utilizado para el código es mikroC pro u otro? Gracias.


El lenguaje de programación es C y el programa usado para ese proyecto es CCS C Compiler.


----------



## johenrod (Nov 17, 2013)

cordial saludo, he querido saber como hacen para medir estas señales, pues se necesitaría un analizador lógico para mirar como se componen estos trenes de pulsos, acaso hay un programa que pueda instalarse en el pc y poder visualizar estas señales? gracias de antemano


----------



## D@rkbytes (Nov 18, 2013)

johenrod dijo:


> cordial saludo, he querido saber como hacen para medir estas señales, pues se necesitaría un analizador lógico para mirar como se componen estos trenes de pulsos, acaso hay un programa que pueda instalarse en el pc y poder visualizar estas señales? gracias de antemano


Posiblemente te sirva este programa: *IR Protocol Analizer*

Suerte.


----------



## johenrod (Nov 18, 2013)

te lo agradezco mucho voy a construir el sensor de entrada a ver que sale,, gracias.
saludos,jorge.


----------



## asherar (Sep 25, 2016)

Para cualquier proyecto con controles inalámbricos.

Enlace a un documento con la descripción de los trenes de pulsos. 

Incluye el diseño de un emisor y un receptor con un conocido formato.

http://unicarlos.com/unicarloscvf/arduino/proyectos/6InfrarrojosProtocoloRC5/pdf/pdf.pdf


----------

