Saturday, December 19, 2015

Infrared (IR) remote control system based on PIC12F1822

IR remote control system based on PIC microcontroller
With 2 x  PIC12F1822 microcontroller we can build a 5-channel IR remote control transmitter and receiver system.
This topic shows how to make a 5-channel IR remote control based on PIC12F1822 microcontroller.
There are two circuits: transmitter circuit and receiver circuit, both circuits use the PIC12F1822 microcontroller. The transmitter circuit sends IR signal to the receiver circuit. In this project the RC-5 protocol is used which means that the transmitter circuit works as an RC5 remote control (RC5 encoder) and the receiver circuit works as a decoder of this protocol.
Carrier frequency of the RC5 IR protocol is 36KHz and all bits are of equal length of 1.778ms.
The complete IR message can be divided into 4 parts:
Start bit (actually one bit and half) which is a property of the RC5 protocol, this bit used to detect if the received signal is RC5, this bit has a length of 2667µs.
Toggle bit: This bit is inverted every time a key is released and pressed again. This way the receiver can distinguish between a key that remains down, or is pressed repeatedly. This bit has a length of 1778µs.
Address: The next 5 bits represent the IR device address, which is sent with MSB first. This 5-bit number has a length of 8890µs.
Command: every key has its command number, this is a 6-bit number with a length of 10668.
In this project there are 5 buttons on the transmitter circuit and 5 LEDs on the receiver circuit where every button controls one LED.
Remote control transmitter circuit:
The following picture shows circuit schematic diagram of the transmitter circuit.

ir remote control pic microcontroller pic12f1822 transmitter mikroc code

The internal oscillator of the microcontroller is used at 32MHz and MCLR pin function is disabled.
Remote control transmitter mikroC Code:
The MikroC code for the transmitter circuit microcontroller is as the one below.

 // IR remote control based on PIC12F1822 (Transmitter code)
 // Written by: BENCHEROUDA Okba
 // electronnote@gmail.com
 // http://elecnote.blogspot.com/
 // Internal oscillator used @ 32MHz
 // Use at your own risk

 bit  toggle;
 unsigned short i;
 void send_signal(unsigned short address, unsigned short command){
   // Start bit
   PWM1_Start();
   delay_us(889);
   PWM1_Stop();
   delay_us(889);
   PWM1_Start();
   delay_us(889);
   PWM1_Stop();
   // Toggle bit
   toggle = ~toggle;
   if(toggle){
     delay_us(889);
     PWM1_Start();
     delay_us(889);
     }
   else {
     PWM1_Start();
     delay_us(889);
     PWM1_Stop();
     delay_us(889);
     }
   // Address
   for(i = 0x10; i > 0; i = i >> 1){
     if( address & i ){
       PWM1_Stop();
       delay_us(889);
       PWM1_Start();
       delay_us(889);}
     else {
       PWM1_Start();
       delay_us(889);
       PWM1_Stop();
       delay_us(889);}}
   // Command
   for (i = 0x20; i > 0; i = i >> 1){
     if ( command & i ){
       PWM1_Stop();
       delay_us(889);
       PWM1_Start();
       delay_us(889);}
     else {
       PWM1_Start();
       delay_us(889);
       PWM1_Stop();
       delay_us(889);
       }
     }
   PWM1_Stop();
   }
 void main() {
   OSCCON = 0xF0; // Internal oscillator 8MHz and PLL enabled (gives 32MHz)
   ANSELA = 0;      // All I/O pins are configured as digital
   ADCON0 = 0;      // Disable ADC module
   PORTA = 0;       // Initial value of port A bits
   TRISA = 0x1F;
   WPUA = 0x1F;     // Enable pull-up resistors
   OPTION_REG = 0;
   APFCON = 1;        // PWM output on RA5
   PWM1_Init(36000);   // PWM module initialization (36KHz)
   PWM1_Set_Duty(127);  // Set PWM duty cycle
   while(1){

     if(Button(&PORTA, 0, 100, 0)){
       send_signal(0, 1);
       delay_ms(300);
       }
     if(Button(&PORTA, 1, 100, 0)){
       send_signal(0, 2);
       delay_ms(300);
       }
     if(Button(&PORTA, 2, 100, 0)){
       send_signal(0, 3);
       delay_ms(300);
       }
     if(Button(&PORTA, 3, 100, 0)){
       send_signal(0, 4);
       delay_ms(300);
       }
     if(Button(&PORTA, 4, 100, 0)){
       send_signal(0, 5);
       delay_ms(300);
       }
     }
   }

Remote control receiver circuit:
The following picture shows circuit schematic diagram of the receiver circuit.

ir remote control pic microcontroller pic12f1822 receiver mikroc code

Remote control receiver mikroC Code:

 // IR remote control based on PIC12F1822 (Receiver code)
 // Written by: BENCHEROUDA Okba
 // electronnote@gmail.com
 // http://elecnote.blogspot.com/
 // Internal oscillator used @ 32MHz
 // Use at your own risk

 bit RC5, toggle;
 unsigned short i, address, command;

 unsigned short read_signal(){
   RC5 = 0;
   // Check if the received signal is RC5 protocol
   delay_us(445);
   if(!PORTA.F3)
     delay_us(889);
   else return;
   if(PORTA.F3)
     delay_us(889);
   else return;
   if(!PORTA.F3)
     delay_us(1778);
   else return;
   // Read signal data
   for(i = 0; i < 12; i++){
     if(!i){
       if (PORTA.F3) toggle = 0;
       else          toggle = 1;
       }
     else {
       if(i < 6){                   //Read address bits
         if (PORTA.F3)
           address &= ~(1 << (5 - i));  //Clear bit (5-i)
         else
           address |= (1 << (5 - i));   //Set bit (5-i)
         }
       else {                       //Read command bits
         if (PORTA.F3)
           command &= ~(1 << (11 - i)); //Clear bit (11-i)
         else
           command |= (1 << (11 - i));  //Set bit (11-i)
         }
       }
       delay_us(1778);
     }
   RC5 = 1;
   }
 void main() {
   OSCCON = 0xF0; // Internal oscillator 8MHz and PLL enabled (gives 32MHz)
   ANSELA = 0;    // All I/O pins are configured as digital
   ADCON0 = 0;    // Disable ADC module
   PORTA = 0;     // Initial value of port A bits
   TRISA = 8;     // Configure RA3 as input
   while(1){
     while(PORTA.F3);
     read_signal();
     if(RC5){     // If RC5 bit equal to one
       address &= 0x1F;
       command &= 0x3F;
       if((address == 0) && (command == 1))
         PORTA.F0 = ~PORTA.F0;
       if((address == 0) && (command == 2))
         PORTA.F1 = ~PORTA.F1;
       if((address == 0) && (command == 3))
         PORTA.F2 = ~PORTA.F2;
       if((address == 0) && (command == 4))
         PORTA.F4 = ~PORTA.F4;
       if((address == 0) && (command == 5))
         PORTA.F5 = ~PORTA.F5;
       }
     delay_ms(500);
     }
   }

Project video:
The following video has more details about this project.