0% found this document useful (0 votes)
45 views13 pages

Understanding Philips RC-5 Protocol

The document outlines the Philips RC-5 remote control protocol, detailing its structure, encoding, and transmission characteristics. It describes the frame composition, including bits for addressing and commands, and provides guidance on implementing the protocol in projects using Arduino. Additionally, it includes circuit design suggestions for both the transmitter and receiver, along with programming examples for sending and receiving commands.

Translated by

ScribdTranslations
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views13 pages

Understanding Philips RC-5 Protocol

The document outlines the Philips RC-5 remote control protocol, detailing its structure, encoding, and transmission characteristics. It describes the frame composition, including bits for addressing and commands, and provides guidance on implementing the protocol in projects using Arduino. Additionally, it includes circuit design suggestions for both the transmitter and receiver, along with programming examples for sending and receiving commands.

Translated by

ScribdTranslations
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

The protocol of remote controls:

PhilipsRC-5
Often in the development stage of a project, we think that it would be useful to use a
remote control. The most commonly used type of control is the remote control through
infrared, like that used in any television or audio equipment.

We have two alternatives: either we develop our communication protocol from scratch (and the
hardware of the transmitter) or we adopt one of the existing ones in the market.

Perhaps the most widespread and about which more information can be found is the one used by
Philips, called 'RC-5'. This protocol has been adopted by many other manufacturers, so it is
It is possible to find 'generic' remote controls for very little money.

This document contains the necessary information for us to decode the messages.
sent by these remote controls in our projects.

Features:
The most outstanding features of this protocol are summarized in the following lines:

5 bits for addressing and 6 bits for the command (7, in the case of RC5X)
Manchester encoding (Bi-phase coding)
Carrier frequency of 36KHz.
Constant time for each bit, of 1.778ms (64 cycles at 36KHz).

Most remote controls implement this protocol.

The protocol:
The protocol consists of a train of square pulses at 36kHz (the so-called 'carrier'). Each '1'
is encoded as 889 microseconds of pulses, and 889 microseconds of 'silence'. The '0' is
encode as 889 microseconds of 'silence' and 889 microseconds of pulses. The total length of
"0" and "1" are identical, and they are 1778 microseconds (or 1.778 milliseconds). The following graph illustrates
clearly this:
Within a bit, exactly 64 pulses fit if the carrier is 36KHz. That is, the period of
A 36KHz signal has a period of 1/36,000 = 27.78125... µs, which, when multiplied by 64, gives exactly 1778.
µs. This is a good piece of information to consider for the design of our receiver's software.

In order for the receiver to know what the remote sender is 'saying', it must be able to interpret the 'frames'.
of zeros and ones that it sends. Each frame is a command and is composed of 14 bits (15 in the
case of the RC5X). Of those 14 bits, the first 2 bits are for 'start': they are always '1'. The
the third bit is inverted each time a key is pressed and released again, in order to distinguish if
a key is held down or has been pressed more than once. The following 5 bits
correspond to the address of the receiving device, and the last 6 to the transmitted command. This
allows the use of the same remote control to command different devices, simply by assigning to
each one a different address code.

A complete RC5 plot.

There is a variation of the RC5 code called RC5X that has 7 bits to determine the command.
which allows 128 different commands vs. the 64 commands of the traditional RC5). The shape of the frame
it is the same, but the second start bit (S2) is used as the command bit 7.

Both in direction and in command, the most significant bit (MSB) is transmitted first and by
least significant bit (LSB)

The full length of the frame is equal to 14 * 1.778 us = 24.892 us. If the key is kept pressed
stressed, the plot is continuously forwarded, but with a pause equivalent to 50 bits (50 x
1.778 us = 88.900 us) between one transmission and another. As we mentioned before, looking at the status of the third bit
we can determine whether it is successive keystrokes of the same key (the bit would change) or of a
same "long" pulse (the bit remains in the same state)

Time diagrams for a complete transmission.


Pre-defined commands
Si estamos creando nuestro propio control remoto, podemos adoptar cualquier dirección y comando
for the functions we implement. But most likely we want to use a control
remote control of some unused device or even a new 'generic' remote control, which will surely
it will cost us less than making one ourselves.

In that case, we should consult the following tables to know what the commands are.
predefined by Philips:

Addresses. Those that are blank are not available. List of assigned commands for TV and VCR by
assigned, and it's a good idea Philips.
use them for our projects.
We start from this theoretical part to program the reception of a command and the sending with RC-5 protocol.

Analysis of a logical '0' or a logical '1'

TRAMA RC5

1 1 0 0 0 1 0 1 0 0 0 0 0 1

First bit Always at '1'. Starting bit of RC5 and RC5X

Second bit Start bit of RC5 (to '1'). In RC5X it is used as command bit 7.

Third bit Its value is inverted every time a key is pressed. (0 1 0 1 …)

4th, 5th, 6th, 7th and 8th (5 bits) Addresses. In this case it is worth 00101 = 5 HEX VCR

9th, 10th, 11th, 12th, 13th and 14th (6 bits) Command. In this case 000001 = 1 HEX Key 1

In hexadecimal it would be: 0x3141 11 0001 0100 0001

Example of use of TV1 and PROG+ button 0x3021 11 0000 0010 0001

1 1 0 0 0 0 0 0 1 0 0 0 0 1

If I press the PROG+ key again 0x3821 111000 0010 0001 (In blue, the bit that changes)

1 1 1 0 0 0 0 0 1 0 0 0 0 1

If we hold down a key, the same frame is sent at intervals of about 114 microseconds.

Circuit design sender infrared

We connect:

GND 220 Ohm resistor Cathode Infrared diode Anode pin 5 PWM.

We put two buttons and an infrared EMITTER diode as seen in the graph.
Left button (pin 12) Send a burst to raise a channel (prog+).

Right button (pin 11) Send a burst to lower a channel (prog-)

FUNDAMENTAL

Raise or lower the channel by pressing one button or another, sending the information via the emitting infrared LED.

HOW TO PROGRAM THE ARDUINO?

The greatest difficulty is sending a burst (frame) of information, with RC5 protocol, so that a TV or VCR can...
interpret correctly.

We are going to create a function called pulses to generate the 32 cycles of impulses. Each pulse has about 18.52.
high level microseconds and about 9.26 low level microseconds.

NOTE: Each instruction of the program takes about 8 microseconds to execute, so it is necessary to keep that in mind.
take into account when making our function.

The total duration has to be about 889 microseconds.

void pulses()
{
// long time = micros();

for (int i=0; i < 32; i++)


{
digitalWrite(pinIROutput, HIGH); We set the pinIRSalida (pin 5) to a high level.
delayMicroseconds(11); We keep it 18.52 µs = 11 + time it takes for an instruction

digitalWrite(pinIRSalida, LOW); // We set the pinIRSalida (pin 5) to low level


delayMicroseconds(3); // We keep it at 9.26 µs = 3 + time it takes for an instruction

}
// time = micros() - time; // measures the time in µs it takes to execute the loop.
//[Link](time);

The text in red, used for debugging, displays the total time of the 32 impulses, which must be given.
approximately 889 µs.

When used for the plot, you need to put the comment // back to avoid wasting time. This would make
that the plot instead of 25 ms becomes greater, which implies that the receiver would not interpret it well.

I obtained the delays of 11 and 3 by measuring the high level time and low level time (with the text in red, but between
the two lines of each level).

Next is the commented program. It is programmed for a TV. To switch channels up and down.

Nombre del programa: emisor_infrarrojos_RC5_subir_bajar_programa.pde

// inicializo variables globales


int pinIRSalida = 5;
int button1 = 12;
int button2 = 11;
int conmuta = 0;

I establish how the pins will be.


void setup()
{
[Link](9600); // Used to check the data. It can be REMOVED when it works.
pinMode(pinIRSalida, OUTPUT); // pin through which I send the frames.
pinMode(button1, INPUT); // button to change channel up (prog+)
pinMode(pulsador2, INPUT); // button to switch down a channel (prog-)
}

function to send data (frame) to the receiver (TV or VCR)


void enviarDato(unsigned long dato)
{
int bits_to_send[14]; // local variable. To split the data into bits
unsigned long compara = 0x2000; // 10 0000 0000 0000 (14 digits)

[Link](" Data to send: "); // REMOVE


[Link](data, BIN);

for (int i=0; i < 14; i++) 14-bit frame.


{
bits_a_enviar[i] = (data & compare) ? 1:0; // Performs the 'and' function (&) between data and compare
If bit 14 of data is one, store 1 in bits_a_enviar[i]
If bit 14 of data is zero, store 0 in bits_a_enviar[i]
[Link](bits_to_send[i]); // REMOVE
[Link](" ");
[Link](compara, BIN);
compara = compara >> 1; // shifts a bit to the right: 1 0000 0000 0000
Repeat the process with bit 13, 12, 11, etc.

/* Result on screen when pressing button 2 (pin 11) for the 2nd time. */
Data to send: 11100000100001
1 10000000000000
1 1000000000000
1 100,000,000,000
0 10000000000
0 1000000000
0 100000000
0 10000000
0 1000000
1 100000
0 10000
0 1000
0 100
0 10
1 1
*/
}

long tiempo_trama = micros(); // We are going to measure the frame, which should be about 25 ms (25000 µs)
It could be REMOVED
// long tpo2 = micros(); // tpo2 measures the transmission time of the 2 start bits (1.5 actually)
// SEND the 2 start bits (The 1st part would be to send a zero for 889 µs. It would not do anything (not needed))
pulses(); // 2nd part of the first start bit. Pulse train 889 µs
space(); // 1st part 2nd start bit. Low level 889 microseconds
pulses(); // 2nd part of the 2nd start bit. End of sending two start bits. Pulse train 889 µs
// tpo2 = micros() - tpo2;
// [Link](tpo2); // Result 889+889+889 = approximately 2667.

We start sending from the third bit to the 14th.


for (int i=2; i < 14; i++)
{
//tpo2 = micros(); // tpo 2 measures the sending of a complete bit. About 1778 µs
if (bits_to_send[i] == 1)
{
highLevel();
}
else
{
lowLevel();
}
// tpo2 = micros() - tpo2;
// [Link](tpo2);
}
time_plot = micros() - time_plot;
[Link]("Frame time = ");
[Link](frame_time); // Approximate result: Frame time = 23908
}

void loop()
{
if (digitalRead(button1))
{
if (switch)
{
//data_one();
sendData(0x3020); // 0x3160 prog+ VCR
conmuta = 0; 0x3020 prog+ TV
}
else
{
sendData(0x3820); // 0x3960 prog + 2nd press VCR
conmuta = 1; 0x3820 prog+ 2 pulse TV
}
delay(100);
}
if (digitalRead(button2))
{
if (toggle)
{
//data_one();
sendData(0x3021); // 0x3161 prog- VCR
switch = 0; 0x3021 prog+ TV
}
else
{
enviarDato(0x3821); // 0x3961 prog- 2ª pulsacion VCR
conmuta = 1; 0x3821 prog+ 2 pulse TV
}
delay(100);
}

void pulses() // Deduced from a program: two high times and one low.
{
//long time = micros();
for (int i=0; i < 32; i++)
{
digitalWrite(pinIRSalida, HIGH); // Set the pinIRSalida (pin 5) to high. Pulse.
delayMicroseconds(11); We keep it at 18.52 µs = 11 + time it takes for one instruction

digitalWrite(pinIRSalida, LOW); // Set the pinIRSalida (pin 5) to low. Rest


delayMicroseconds(3); // We keep it at 9.26 µs = 3 + time taken by an instruction

}
// time = micros() - time;
//[Link](time);

void space()
{
digitalWrite(pinIRSalida, LOW); // Sets pin 5 to low level. Does not send data.
delayMicroseconds(870); // Delay of 889 µs = 870 + instruction time
}

void highLevel() // We send a 0 and 1


{
espacio();
pulses();
}

void lowLevel() // We send a 1 and 0


{
pulsos();
space();
}

Circuit design receptor infrared

We need an infrared RECEIVER diode that works well at 36KHz.

GND Anode of the infrared receiver Cathode Resistance of about 300K Vcc (5v)

From the cathode, we take an alpin 2 PWM connection. It corresponds with the 0 interruption of the Arduino.

First, we will look at an example of using interrupts.

attachInterrupt(interrupt number, function name, mode)

Arduino has two external interrupts.

Interrupt 0 on pin 2.

Interruption 1 on pin 3.
The Arduino MEGAIt has 4 more: interruption 2 (pin 21), 3 (pin 20), 4 (pin 19) and 5 (pin 18).

mode: CHANGE It triggers when the pin value changes.

LOW it triggers when the pin is in low level (LOW)

RISING it triggers when the pin goes from low to high HIGH)

FALLING it triggers when the pin goes from high to low (HIGH) LOW

int pin = 13;


volatile int state = LOW;

void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE); // Executes the blink function when it changes
level on pin 2
}

void loop()
{
digitalWrite(pin, state); // it runs continuously, but only changes when it
produce a level change on pin 2 (interrupt 0)
}

void blink() Function that is executed when the interruption occurs


{
state = !state; // changes from low to high and vice versa
}

detachInterrupt(interruption)

Deactivate the interruption that we indicate.

The use of interrupts is very good for controlling input data that should not wait in the loop.
loop and execute a function that is not in the loop.

In our case, the function of decoding a signal from a remote control will only be executed when it has been
produced the interruption, which causes a high level at pin 2 (interrupt 0).

Below is the program to receive data from a remote control using the RC5 protocol (Philips).

(We read data every 100 microseconds approximately, when an interruption occurs on pin2)

The program is commented and displays the received data on the screen in such a way that we begin to understand the
lines of code). Program name: receive_infrared_data_arduino.pde

int button1 = 12;


long result = 0; // I store the result obtained from pressing a button on the remote
int counter = 1; // Counts the times I activate button1

void setup()
{
[Link](9600);
set pin mode(pulsador1, INPUT);
// INTERRUPTION. Execute the function "receive" when pin 2 goes HIGH
attachInterrupt(0, receive, HIGH);
}
void loop()
{
When button1 is pressed, we display the result on the screen.
if (digitalRead(button1) == HIGH)
{
[Link](" PRESSED ");
Times pressed
[Link](counter);
[Link](" RESULT = ");
[Link](result, HEX);
counter++;
It stays in this loop until button1 is released.
while (digitalRead(button1) == HIGH)
{
}
delay(300);
}

void receive()
{
long times[28];
boolean overflow = 0;
boolean error = 0;
int nb = 2;
int nbtotal = 0;
boolean cambia_nivel = 1;
// I initialize the times to zero.
for (int i=0; i < 28; i++)
{
times[i] = 0;
}
When we receive a positive impulse
if (!digitalRead(2))
{

We detected the first high level. We save the data times[1], about 7
while (!digitalRead(2))
{
times[1]++;
delayMicroseconds(100);
}
// If any time is less than 700 (7*100) microseconds, it gives an ERROR.
Each level is at least 889 microseconds.
if (times[1] < 6)
{
desbordamiento = 1;
error = 1;
}
If the first data is correct, that is, high level. Time over 7.
if (!error)
{

Until a datum is greater than 25, indicate a low level 0000000...


Let's keep time low, high, low, high, etc.
while (!overflow)
{
while(digitalRead(2) == change_level)
{
times[nb]++;
delayMicroseconds(100);
}
if (times[nb] < 6) { overflow = 1; error = 1; nb = 2; }
if (times[nb] > 25) { overflow = 1; total_nb = nb - 1; }
cambia_nivel = !cambia_nivel;
nb++;
/*
while(!digitalRead(2)) { times[nb]++; delayMicroseconds(100); }
nb++;
if (times[nb] > 25) { overflow = 1; totalNb = nb - 1; }
*/
}
}
if (nb < 14) { error = 1; } // The complete frame has not been received
If there have been no more errors, we save the data in res[i]
//
if (!error)
{
times[1] over 7 indicates high level
// even times indicate low level over 7,8,9 '0' and 15,16,17,18 '00'
Odd tpos indicate a high level above 7,8,9 '1' and 15,16,17,18 '11'
cambia_nivel = 1;
int res[50];
int total_bits = 0;
for (int i=2; i < nb; i++)
{
[Link](i);
[Link](" ");
[Link](times[i]);
res[bit_totales] = cambia_nivel;
total_bits++;
if (times[i] > 12)
{
res[bit_totales] = cambia_nivel;
total_bits++;
}
cambia_nivel = !cambia_nivel;
}
//[Link](total_bits);
We take the even bits that we stored in the result (global variable)
resultado = 1;
for (int i = 0; i < total_bits - 1; i++)
{
[Link](res[i]);
if (i % 2)
{
if (res[i] == 1)
{
result = result <<= 1;
}
else { result = (result <<= 1) | 1; }
}
}
We check that the result is as desired on screen.
[Link](" Result obtained ");
[Link](result, BIN);
[Link](result, HEX);
char data_word = result & 0x3F; // We keep the last 6 bits (command)
[Link](data_word, HEX);
}
}
}

It can be done in several ways, tried, but I think this one is better refined.

I advise you to try other possibilities that you come up with. Objective: to be able to make the emitters and
detectors of other protocols like RC6, NEC, SONY, NOKIA, etc

Screen results when pressing channel 1 on a VCR remote.

27
3 10
46
5 19
66
7 10
8 15
9 18
10 15
11 18
12 6
13 10
14 7
15 10
16 6
17 10
18 6
19 10
20 15
21 10
22,834
Result obtained
11100101000001
3941
1

0 and 1 are the first start bit which is '1', otherwise we wouldn't display this screen.

The 22 is worth 834 *100 = 83400, which corresponds to the downtime between bursts.

101001011001100101010101101 It is missing the initial '0'. We take the odd numbers as the final result.

11100101000001 Resultado en binario. 11 1001 0100 0001 = 0x3941 en Hexadecimal

3941 result in hexadecimal.

1 Pulsed channel.

You might also like