Interface for infrared remote control (18F PIC)

Discussion in 'Embedded Systems and Microcontrollers' started by takao21203, Jul 10, 2012.

  1. takao21203

    Thread Starter Distinguished Member

    Apr 28, 2012
    3,577
    463
    I have added infrared receiver from old television to my 18F TFT LCD board.
    Particulary it could be useful to enter for instance address for memory copy.

    It works so far, if I press button on the remote control, the LED blinks. This is done in hardware not via PIC.

    How can I implement interface in software (XC8, PIC 18f24j10)?

    I have some idea, but I am stuck with this. Today I have added serial RAM (32K), and just now moved the blinking LED + programmed TIMER0 interrupt.

    I plan to use TIMER0 interrupt every 167 usec.
    Using a counter to count upto 3000, I get blinking LED 2 times a second or something like this.

    Here is the protocol that is to be used, old PANASONIC format.
    Indeed the remote control can be programmed with numbers to many different formats.

    I appreciate any ideas how to implement this in software. Neither assembler or delay loops can be used.

    Also I don't want double codes in a row, so I must take care for repeated codes that are sent. Only after a new start condition, the same code can become accepted again, and only if it has been processed.

    I don't even know if the remote control will issue repeated start conditions in a row, or simply repeat the data. But this is important, I need to detect if the code is repeating, or the button was released even if only for a short while.
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    I did something like this a few years back "just because" (I had no application for it). The received code would be written to an alphanumeric LCD display. "How" I did the code is forgotten, but it isn't very difficult.

    The 18f24j10 has 3 timers on board, I would set one up to give me a nice resolution for the bit rate you get. On either a 0->1 or a 1->0 transition the timer is read and then reset so you get a 'read' on the pulse length. (A interrupt on input change would work nice here if you want this to run in the background.) Then you need to make a state machine to process this data, begin with the two START pulses, then decode the data. A timer overflow may also be used to detect when the remote stops transmitting.

    I had a nice digital scope handy when I did this so I could "see" what each button did and then hard code them into the code.
     
  3. takao21203

    Thread Starter Distinguished Member

    Apr 28, 2012
    3,577
    463
    yes this is about what I have in mind to transform into program code.

    This is what I have now:

    Code ( (Unknown Language)):
    1. void interrupt high_isr(void)
    2. {
    3.  
    4.   //  if(SSP1IF==1);
    5.    //   {
    6.    // SSP1IF=0;
    7.     //  }
    8.  
    9.       if(TMR0IF==1)
    10.       {
    11.           TMR0IF=0;
    12.           tmr_led++;
    13.           if(tmr_led==3000){tmr_led=0;
    14.           if(v_status&c_status_led0)
    15.           {
    16.            v_status&=(0xff-c_status_led0);
    17.            LB3=1;
    18.           }else
    19.           {
    20.            v_status|=c_status_led0;
    21.            LB3=0;
    22.           }}
    23.       }
    Note the serial interrupt is not used, the flag is polled directly.
    I want to use Timer0 and have programmed it to what I believe about 167uSec/each interrupt.

    And the signal from IR receiver will also trigger interrupt. The receiver is supplied from 5V, and 2.2k + green LED should reduce this to 3V. But it's inverted, isn't it, even if the LED itself would light up non-inverted?

    The LEDs is flashing up by random sometimes for very short moments, adding 1uF very close to the receiver somehow solved the problem.
     
    Last edited: Jul 10, 2012
  4. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    I suspect that you don't want to be using the serial interrupt.
    The way I'd do it:
    Use a pin that can generate an interrupt on a rising edge.
    Set the timer prescaler so it won't overflow (longer than the start period).
    On a rising edge read the timer to determine if it's a 0 or 1 and reset the timer.
    Also have a timer interrupt that will detect if transmission has stopped / been interrupted.
     
  5. takao21203

    Thread Starter Distinguished Member

    Apr 28, 2012
    3,577
    463
    OK I found some time + nerves today to work on this.

    Here is what I wrote:

    Code ( (Unknown Language)):
    1. void interrupt high_isr(void)
    2. {
    3.  
    4.   //  if(SSP1IF==1);
    5.    //   {
    6.    // SSP1IF=0;
    7.     //  }
    8.  
    9.     if(INT0IF&&(!INT0IE))
    10.     {INT0IF=0;}
    11.  
    12.     if(INT0IF&&(INT0IE))
    13.     {INT0IF=0;
    14.  
    15.     if(v_status&c_status_IR_start)
    16.     {
    17.         v_status|=c_status_IR_start2;
    18.     }
    19.  
    20.     v_status|=c_status_IR_start;
    21.  
    22.           if(v_status&c_status_led0)
    23.           {
    24.            v_status&=(0xff-c_status_led0);
    25.            LB3=1;
    26.           }else
    27.           {
    28.            v_status|=c_status_led0;
    29.            LB3=0;
    30.           }
    31.     }
    32.     if(TMR0IF&&(!TMR0IE)){TMR0IF=0;}
    33.  
    34.       if(TMR0IF&&TMR0IE)
    35.       {
    36.           TMR0IF=0;
    37.  
    38.           if(v_status&c_status_IR_start)
    39.           {
    40.               if(!(v_status&c_status_IR_start2))
    41.               {
    42.               ir_start++;
    43.               }
    44.           }
    45.  
    46.           tmr_led++;
    47.           if(tmr_led==3000){tmr_led=0;
    48.  
    49.  
    50.           if(v_status&c_status_led0)
    51.           {
    52.            v_status&=(0xff-c_status_led0);
    53.           // LB3=1;
    54.           }else
    55.           {
    56.            v_status|=c_status_led0;
    57.           // LB3=0;
    58.           }}
    59.       }
    60.  
    ir_start will increment to 41 (when I push the remote control button), if I calculate 16T * 425 uSec, and divide through 167uSec, this results in 40.7

    Somehow I need to capture the time between interrupts, and store them in an array. I want to display values numerically on the LCD, to see if the start condition is repeated, or what repeats actually.

    I know the code is not good, just barely got it working today.
     
  6. takao21203

    Thread Starter Distinguished Member

    Apr 28, 2012
    3,577
    463
    Here are some samples. It has something to do with this old Panasonic protocol, however, the inverted codes are absent, and the start condition is repeated.

    Maybe my state machine is not really fully correct, however there is different combination for each remote control key.

    Simply, when a second interrupt occurs, I store the timer int's that have elapsed. and reset the flags. Maybe it's out of phase or something.
     
Loading...