Pages

Tuesday, September 20, 2016

IR Remote control transmitter and receiver using PIC12F1822 microcontroller

5-Channel IR remote control system using PIC microcontroller
This topic shows how to make a simple infrared (IR) remote control system using the microcontroller PIC12F1822. This IR system has two circuits as known: IR transmitter circuit and IR receiver circuit. Both circuit based on the same microcontroller type which is PIC12F1822.
This IR system uses NEC communication protocol. To see how the NEC protocol works read the following topic which shows how to decode this communication protocol using PIC12F1822 microcontroller.
Extended NEC Protocol Decoder Using PIC12F1822 Microcontroller

Components List:
Transmitter Circuit:
  • PIC12F1822 Microcontroller
  • IR Transmitter
  • 2N2222 Transistor
  • 5 Push Buttons
  • 10k Resistor
  • 100Ohm Resistor
  • +5V Power Source
  • Protoboard
  • Jumper Wires
Receiver Circuit:
  • PIC12F1822 Microcontroller
  • IR Receiver
  • 5 LEDs
  • 10k Resistor
  • 5 x 470 Ohm Resistors
  • 47uF Capacitor
  • +5V Power Source
  • Protoboard
  • Jumper Wires
NEC Protocol IR transmitter (Encoder) using PIC12F1822:
The following image shows the IR system transmitter circuit schematic diagram.
NEC IR remote control transmitter circuit PIC12F1822
In the circuit there 5 push buttons and each button sends a different IR signal code. The IR transmitter is the element that sends the IR signals to the IR receiver circuit.
The NPN transistor 2N2222 is used to drive the IR transmitter because the IR transmitter consumes high current and the microcontroller generally can't provide that amount of current.
PIC12F1822 internal pull-ups are enabled by the software and the internal oscillator is used as usual.
NEC Protocol IR transmitter (Encoder) using PIC12F1822 CCS PIC C code:
This is the full code of microcontroller of the NEC IR transmitter.
The NEC protocol carrier frequency is 38KHz and to generate this frequency PIC12F1822 CCP module is used as a PWM module. The floowing CCS C line is used to configure the PWM module:
#use pwm (PWM1, FREQUENCY = 38KHz, DUTY = 25, PWM_OFF)
The internal oscillator is used and set to 8MHz with PLL enabled (8 x 4 = 32MHz). The following line is used for that:
setup_oscillator(OSC_8MHZ | OSC_PLL_ON);
In the circuit there are 5 push buttons connected to RA0, RA1, RA3, RA4 and RA5 which means that pins must be configured as inputs and the PWM pin as output.
Internal pull-ups are enabled for the input pins with the following line:
port_a_pullups(0x3B);
The five buttons transmit the following signals respectively:
0x40BF00FF -- 0x40BF807F -- 0x40BF40BF -- 0x40BF20DF -- 0x40BFA05F
1s and 0s are transmitted as:
Transmit 1 : pwm_on();
Transmit 0: pwm_off();
For example the transmission of 9ms burst pulse and 4.5ms space:
// Send 9ms burst
pwm_on();
  delay_ms(9);
  // Send 4.5ms space
  pwm_off();
  delay_us(4500);

Full Code:
// Extended NEC protocol IR remote control transmitter CCS PIC C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com
// Use at your own risk

#include <12F1822.h>
#fuses NOMCLR INTRC_IO PLL_SW
#use delay(clock=32000000)
#use fast_io(A)
#use pwm (PWM1, FREQUENCY = 38KHz, DUTY = 25, PWM_OFF)

void send_signal(unsigned int32 number){
  int8 i;
  // Send 9ms burst
  pwm_on();
  delay_ms(9);
  // Send 4.5ms space
  pwm_off();
  delay_us(4500);
  // Send data
  for(i = 0; i < 32; i++){
    // If bit is 1 send 560us pulse and 1680us space
    if(bit_test(number, 31 - i)){
      pwm_on();
      delay_us(560);
      pwm_off();
      delay_us(1680);
    }
    // If bit is 0 send 560us pulse and 560us space
    else{
      pwm_on();
      delay_us(560);
      pwm_off();
      delay_us(560);
    }
  }
  // Send end bit
  pwm_on();
  delay_us(560);
  pwm_off();
  delay_us(560);
}
void main() {
  setup_oscillator(OSC_8MHZ | OSC_PLL_ON);            // Set internal oscillator to 32MHz (8MHz and PLL)
  output_a(0);
  set_tris_a(0x3B);                                   // Configure RA2 pin as output and others as inputs
  port_a_pullups(0x3B);                               // Enable internal pull-ups for pins RA0,RA1,RA3,RA4 & RA5
  while(TRUE){
    while(!input(PIN_A0)){
      send_signal(0x40BF00FF);
      delay_ms(500);
    }
    while(!input(PIN_A1)){
      send_signal(0x40BF807F);
      delay_ms(500);
    }
    while(!input(PIN_A3)){
      send_signal(0x40BF40BF);
      delay_ms(500);
    }
    while(!input(PIN_A4)){
      send_signal(0x40BF20DF);
      delay_ms(500);
    }
    while(!input(PIN_A5)){
      send_signal(0x40BFA05F);
      delay_ms(500);
    }
  }
}
NEC Protocol IR receiver (Decoder) using PIC12F1822:
The NEC receiver circuit schematic is shown below.
NEC IR remote control receiver circuit PIC12F1822
In the IR receiver circuit there are 5 LEDs and IR receiver. The IR receiver receives IR signals transmitted from the IR transmitter. Each LED is remotely controlled from one button in the transmitter circuit.
PIC12F1822 internal oscillator is used and MCLR pin is configured as a digital input pin.
NEC Protocol IR receiver (Decoder) using PIC12F1822 CCS PIC C code:
As in the IR transmitter the internal oscillator of the IR receiver microcontroller is used.
Timer1 is configured to increment every 1us and it is used to measure pulses spaces duration.
SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8);
For example to check the 9ms pulse the following lines are used:
// Check 9ms pulse (remote control sends logic high)
  SET_TIMER1(0);
  while(!input(IR_Sensor) && (count < 9500))
    count = GET_TIMER1();
  if( (count > 9499) || (count < 8500))
    return FALSE;

And checking the 4.5ms space as follows:
// Check 4.5ms space (remote control sends logic low)
  SET_TIMER1(0);
  count = 0;
  while((input(IR_Sensor)) && (count < 5000))
    count = GET_TIMER1();
  if( (count > 4999) || (count < 4000))
    return FALSE;

Full Code:
// Extended NEC protocol IR remote control decoder using PIC12F1822 CCS PIC C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com
// Use at your own risk

#include <12F1822.h>
#fuses NOMCLR INTRC_IO PLL_SW
#use delay(clock=32000000)
#use fast_io(A)
#define IR_Sensor PIN_A3

unsigned int32 ir_code;
short nec_remote_read(){
  unsigned int16 count = 0;
  unsigned int8 i;
  // Check 9ms pulse (remote control sends logic high)
  SET_TIMER1(0);
  while(!input(IR_Sensor) && (count < 9500))
    count = GET_TIMER1();
  if( (count > 9499) || (count < 8500))
    return FALSE;
  // Check 4.5ms space (remote control sends logic low)
  SET_TIMER1(0);
  count = 0;
  while((input(IR_Sensor)) && (count < 5000))
    count = GET_TIMER1();
  if( (count > 4999) || (count < 4000))
    return FALSE;
  // Read message (32 bits)
  for(i = 0; i < 32; i++){
    SET_TIMER1(0);
    count = 0;
    while(!input(IR_Sensor) && (count < 650))
      count = GET_TIMER1();
    if( (count > 649) || (count < 500))
      return FALSE;
    count = 0;
    SET_TIMER1(0);
    while((input(IR_Sensor)) && (count < 1800))
      count = GET_TIMER1();
    if( (count > 1799) || (count < 400))
      return FALSE;
    if( count > 1000)                                 // If space width > 1ms
      bit_set(ir_code, (31 - i));                     // Write 1 to bit (31 - i)
    else                                              // If space width < 1ms
      bit_clear(ir_code, (31 - i));                   // Write 0 to bit (31 - i)
  }
  return TRUE;
}
void main() {
  setup_oscillator(OSC_8MHZ | OSC_PLL_ON);            // Set internal oscillator to 32MHz (8MHz and PLL)
  output_a(0);
  set_tris_a(8);
  SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8);
  while(TRUE){
    while(input(IR_Sensor));                          // Wait until IR_Sensor pin falls
    if(nec_remote_read()){
      if(ir_code == 0x40BF00FF)
        output_toggle(PIN_A0);
      if(ir_code == 0x40BF807F)
        output_toggle(PIN_A1);
      if(ir_code == 0x40BF40BF)
        output_toggle(PIN_A2);
      if(ir_code == 0x40BF20DF)
        output_toggle(PIN_A4);
      if(ir_code == 0x40BFA05F)
        output_toggle(PIN_A5);
      }
  }
}
IR Remote control transmitter and receiver using PIC12F1822 microcontroller video:
The following video shows project final result.