Arduino RC5 IR remote control decoder

This post shows how to decode IR remote controls which use the Philips RC5 protocol with full hardware interrupt method and without using any external library.

About RC5 protocol:
The RC5 has 14 bits per 1 code transmission, the 14 bits can be divided into 4 parts:
The first 2 bits are start bits and they are always logic 1.
The third bit called toggle bit, it can be logic 1 or logic 0.
The next 5 bits are address bits, each device type has its address number for example TV address number is 0, CD player address = 20 …………
And the last 6 bits are command bits, each button has its command number.
For the same device for example TV all the remote control buttons has the same address but each button has its command.
The toggle bit changes whenever a button is pressed.
The RC5 protocol uses Manchester coding, a logic 0 is represented by a logic high in the first half and a logic low in the second half, whereas a logic 0 is represented by a logic low in the first half and a logic high in the second half. The length of each half is 889µs which means the length of 1 bit is 1778µs. The links below from Wikipedia has more details about the RC5 protocol:
RC-5

Components required:

  • Arduino board
  • RC5 IR remote control
  • 16×2 LCD screen
  • IR receiver
  • 47µF capacitor
  • 10K ohm variable resistor
  • 330 ohm resistor
  • Protoboard
  • Jumper wires

Arduino RC5 decoder circuit:
Project circuit schematic is shows below.

Arduino remote control decoder circuit

The output of the IR receiver is connected to the Arduino UNO pin 2 which is external hardware pin (INT0).

Arduino RC-5 remote control decoder code:
Note that there is no remote control library used in this example.
Before writing the C code of the decoder, I drew a simple state machine of the RC5 protocol which helped me a lot in the code. The state machine is shown below.

RC-5 protocol state machine

Where:
SP : Short Pulse (About 889µs)
LP : Long Pulse (About 1778µs)
SS: Short Space (About 889µs)
LS : Long Space (About 1778µs)

Programming hints:
Arduino external hardware interrupt (INT0 on pin 2) is used to detect the IR signals (IR receiver output goes from high to low when it starts receiving IR signal), and after the detection of the IR signal the microcontroller starts following the state machine shown above. So this is fully hardware interrupt based software.

The message of the RC5 protocol is 14-bit long, 2 start bits (always 1), toggle bit, address (5 bits) and command (6 bits). The length of 1 bit is 1778µs which can be divided into two parts of 889µs. A logic 1 is represented by 889µs low and 889µs high. A logic zero is represented by 889µs high and 889µs low.
The RC5 protocol has 4 states: start1, mid1, start0 and mid0.
The IR receiver output is logic high at idle state and when it receives a burst it changes the output to logic low.
The output of the IR receiver is connected to the external interrupt pin and every change in the pin status generates an interrupt and Timer1 starts calculating, Timer1 value will be used in the next interrupt, this means Timer1 calculates the time between two interrupts which is pulse time or space time.
Timer1 increments by 2 every 1 us, its interrupt is used as a timeout calculator (very long pulse or very long space) and interrupted it resets the decoding process.
The decoding results are displayed on 1602 LCD screen and it can be displayed on PC via serial monitor after small modifications.
Full Arduino code is the one below with commented lines.

The video below shows a simple hardware circuit of the project:

One comment

  1. Hey!

    I’m actually building something very similar, but both receiver AND transmitter. your receiver code look great(and A LOT easier than mine), but i wonder about how to transmit the data.
    I wrote something like that:

    void send_0() {
    cnt++;
    digitalWrite(CON_PIN, HIGH);
    delayMicroseconds(889);
    digitalWrite(CON_PIN, LOW);
    delayMicroseconds(889);
    }

    void send_1() {
    cnt++;
    digitalWrite(CON_PIN, LOW);
    delayMicroseconds(889);
    digitalWrite(CON_PIN, HIGH);
    delayMicroseconds(889);
    if (cnt == 14) { //the cnt parts are just to eventually turn off the IR LED after 14 bits
    digitalWrite(CON_PIN, LOW);
    cnt = 0;
    }
    }

    But it seems this doesn’t work… and I have no idea how to go about it.
    Any ideas how to do that?

    Note: transmitter and receiver are two separate Arduino UNOs

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.