This article shows how to build a 5-channel IR remote control system. The system consists of a simple, low-power IR (infrared) remote control transmitter and a simple but yet powerful receiver. The remote control transmitter is based on a PIC12F617 microcontroller and the receiver is based on the popular PIC16F84A. The system uses the RC5 transmitting protocol which is probably the most used by hobbyists due to its simplicity.
Infrared radiation is the region of the electromagnetic spectrum which lies between microwaves and visible light. In general, discussions on infrared ranges refer to near, medium and far infrared radiation. Near infrared light is closest in wavelength to visible light and far infrared is closer to the microwave region of the electromagnetic spectrum.
The shorter waves (near infrared) are the ones used by remote controls. Information is transmitted and received using electromagnetic energy, without using wires. The information is encoded by using light pulses. The receiver detects the light pulses, which are processed to retrieve/decode the information they contain.
There are many popular infrared protocols used to transmit data via infrared light, such as RC5, RC6, SIRC, NEC, IrDA ...
Since infrared (IR) remote controls use light, they require line of sight to operate the destination device. The signal can, however, be reflected by mirrors, just like any other light source. If operation is required where no line of sight is possible, many brands of IR extenders are available for this on the market.
RC5 IR transmission protocol
The RC-5 protocol was developed by Philips in the late 1980s as a semi-proprietary consumer IR (infrared) remote control communication protocol for consumer electronics. RC-5 is possibly the most used protocol by hobbyists, probably because of the wide availability of low cost remote controls.
RC5 IR transmission protocol uses bi-phase modulation (or so-called Manchester encoding) on a 36 KHz carrier (in many cases, 38 KHz or 40 KHz are used instead, because IR detectors operating at these frequencies tend to be more common). The data are transmitted in a 14bit bit stream. Each bit takes 1.778ms to be transmitted, with half of this time filled with a burst of the 36kHz carrier and the other half being idle. This specific 1.778ms interval is known as the symbol period. A logical “0” is represented by a burst in the first half of the symbol period. A logical “1” is represented by a burst in the second half of the symbol period. The pulse/pause ratio of the 36kHz carrier frequency is 1/3 or 1/4 which reduces power consumption.
One cycle of the 36 kHz carrier frequency is 27.778 μs, and each bit is transmitted on exactly 64 cycles. Thus, the high half of each symbol (bit) of the RC-5 code word contains 32 carrier pulses, which is 32 x 27.778 μs = 889μs. The duty cycle used for the carrier is 25% and because of this, a carrier pulse having duration of 6.944μs is transmitted during a carrier cycle.
The whole bit stream, also known as the complete RC-5 code word, consists of 14 bits (symbols) and takes 24.889 ms to be transmitted. The code word is repeated every 113.778 ms (4096 / 36 kHz) as long as a key remains pressed. However, we may say that these timings are not strictly followed by all manufacturers. This is due to a lack of widespread distribution of accurate information on the RC-5 protocol and more often due to hardware limitations at specific implementations.
Each pulse burst is 889us in length and logical bits are transmitted as follows:
- Logical '0' – an 889us pulse burst followed by an 889us space, with a total transmit time of 1.778ms
- Logical '1' – an 889us space followed by an 889us pulse burst, with a total transmit time of 1.778ms
When a key is pressed on the remote controller, a frame is transmitted which consists of the following 14 bits, in order:
- two Start bits (S1 and S2), both logical '1'*
- a Toggle bit (T). This bit is inverted each time a key is released and pressed again. The main purpose of this bit is for the receiver to be able to distinguish a double - click from a long press.
- the 5-bit address for the receiving device. This set of 5 bits represents the device ID (address) that each remote control addresses to. This way, many devices can use the RC5 protocol in the same room, independently.
- the 6-bit command. These bits are used to carry all the possible commands that the remote controls can address on a specific device.
* Philips also introduced an extended version of RC5 protocol when they realized that 64 commands (6-bits command) are just not enough. To maintain compatibility with the original RC5 protocol they decided to use S2 bit as a 7th command bit. This way the RC5-extended protocol has 128 commands (7 bits) and the S2 bit is used as MSB of a command. So, care must be taken though with this bit in case of using the extended version of RC5.
The above figure illustrates that it takes:
- 5.333 ms to transmit the Start and Toggle bits (S1, S2 and T). Notice that, as the first half-bit of S1 is a space, the receiver will only notice the real start of the message frame after 889us.
- 8.889 ms to transmit the 5 bits for the address
- 10.667 ms to transmit the 6 bits for the command
- 24.889 ms to fully transmit the actual message frame.
The Toggle bit (T) is used by the receiver to distinguish weather the key has been pressed repeatedly, or weather it is being held depressed. As long as the key on the remote controller is kept pressed, the message frame will be repeated every 114ms. The Toggle bit will retain the same logic level during all of these repeated message frames. It is up to the receiver software to interpret this auto-repeat feature of the protocol.
The infrared transmitter
Although there are many RC5 low cost remote controls transmitters available on the market, building our own transmitter is something we wish to do just for fun. Moreover the satisfaction of having built something yourself is incalculable.
The remote control transmitter uses Pulse-Width Modulation (PWM) to create a Pulse Code Modulation (PCM) signal that is transmitted via an infrared LED. PCM involves transmission of a carrier frequency that can be easily discerned from the background noise. This signal is then band-pass filtered and demodulated by the receiver to recreate the transmitted digital waveform. In the official RC5 transmitting protocol, a 36 KHz carrier is used.
Our transmitter uses a 38 KHz carrier instead, because IR detectors operating at this specific frequency tend to be more common. This can be considered as a misuse of the RC5 protocol, whoever it is quite common and even most commercial remote controls supporting RC5 use different carrier frequency than 36KHz. Frequencies at the range 32 kHz to 39 kHz are very popular. Modifying this project to use different carrier frequency requires just some minor code modifications.
The transmitter remains in sleep mode most off the time for saving battery power. The microcontroller wakes-up when a button is pressed, transmits data by sending an appropriate PCM signal to an infrared LED and then goes back to the sleep state. The basic operation of the remote control transmitter is shown below:
The PWM module is used to create a 38 kHz signal, and this is then gated (enabled or disabled) to produce bursts for PCM. The modulation is controlled in software and a 14-bit frame is produced according to RC5 protocol at every button press. Using the PWM allows flexibility for creating different frequencies, while controlling the signal through code allows for the generation of a variety of signal formats. This way, the specific hardware can be used as a starting point for all-kind of low-power remote control transmitters and not only for RC5.
As shown in the schematic the circuit uses PIC12F617 as infrared encoder. We use two IR LEDs, driven by a separate NPN transistor. The use of two IR LEDs was intentionally selected in order to achieve longer effective transmitting range. With this configuration, the transmitter was able to send commands to our remote receiver from as far as 20 meters.
Τhe infrared LEDs used in the prototype are two x TSAL6100 - High Power Infrared Emitting Diodes at 940 nm from Vishay. For optimum performance, light detection at the same wavelength (940nm) must be used at the receiver end.
GP2 is used as PCM output and GP0, GP1, GP3, GP4 and GP5 are used for the buttons. We use internal pull-ups for GP0, GP1, GP4 and GP5. There isn’t any internal pull-up available for GP3, so we use R2 as external pull-up.
The current consumption of the circuit is around 35nA and 20mA, during sleep and transmitting, respectively. This way, for normal use, 3xAAA batteries will last quite some years.
The infrared receiver
The receiver uses a 38KHz IR detector. IR detectors are little modules with a photocell that are tuned to detect infrared light. The detector has a demodulator inside that looks for a modulated IR at 38 KHz. It has an output pin which is normally high (5V). When it detects an IR signal (burst), the output becomes low (0V). At the output pin of the detector, a transition from 1 to 0 (falling edge), indicates that the transmitter sends a burst after being idle from a while. A transition from 0 to 1 (rising edge) indicates that the transmitter goes idle after being active (burst mode) from a while.
Actually, the IR detector inverts the RC5 data stream. Idle becomes high (logic 1) and burst becomes low (logic 0), and this way the detector produces an exact inverse version of the original transmitted frame.
To recognize each bit of the RC5 frame, we use a PIC16F84A microcontroller. A digital input pin of the microcontroller is connected directly at the detectors output pin and we use the output signal from the detector to trigger an interrupt event at every falling edge. The microcontroller runs an interrupt driven state-machine to decode the RC5 data using bit lengths.
The first state of the state machine is used to calibrate the receiver on every received transmission. Calibration actually refers to a mechanism for detecting the actual time each bit takes to be transmitted. This is critical due to the fact that RC5 official timing is not expected to be strictly followed by a typical transmitter. In every transmission, we expect to have some tolerance which must be taken into consideration.
RC5 official timing is not strictly followed by all manufacturers, and moreover many IR handsets use ceramic resonators that are temperature sensitive and drift over time. Each transmission is expected also to suffer from jitter (phase noise) and not all transmitted bits will have the exact same timings. So, we use a detection algorithm which takes into consideration a degree of tolerance of about 12%.
Bit timing and the tolerance are calculated from the actual timing of the first two bits of the frame (bits S1 and S2). Since, the first two bits of a standard RC5 transmission are always logic-1, we use a timer to measure bit length. We use the timer_0 module of the microcontroller to measure the time between the first two interrupts taking place at the first two falling edges of the frame. This specific time interval is equal to the actual time each bit takes to be transmitted (bit length). Then, we consider a tolerance of about 12% by right shifting by 3 (being equivalent of dividing by 8), the measured bit length.
After the first two falling edges of the frame, the state machine goes to the next states, to decode the next 12 bits of the frame. The actual state of the machine is determined by the value of a counter variable which is incremented after each bit decoding.
The decoding process refers to the recognition of each individual bit by implementing bi-phase demodulation (or so-called Manchester decoding). We use a decoding algorithm based on bit length recognition. The specific algorithm goes as follow:
Using interrupts at the negative edge of an inverted RC5 frame (the actual frame delivered from the detector) there will be three possible pulse lengths, (the time between two consecutive interrupts); 1 bit length, 1.5 bit length and 2 bit lengths. Timer_0 is used to count the time between negative edges. The timer count is stored and then, the timer is being reset. The pulse length is determined from the timer count and by knowing the previous bit received, the actual bit is decoded and added to the received buffer queue.
- If the time between two consecutive interrupts equals to 1 bit length, then the actual bit is the same as the previous one.
- If the time between two consecutive interrupts equals to 1.5 bit length, then the actual bit is the inverse of the previous one (toggle).
- If the time between two consecutive interrupts equals to 2 bit length then the last bit determined was a “1” followed by two consecutive toggles ( one “0” and one “1”bit).
When the last bit on the RC5 data stream happens to be a '0', there will be no last falling edge and timer_0 will overflow after some milliseconds. In that case, we check the counter-variable to be sure that the correct number of bits has been detected. If so, a ‘0’ is added to the end of the data stream. After the last bit being received, address and command are decoded and the state machine goes back to its first state.
The microcontroller uses the address and command to control a set of 5-relays, thus implementing a 5-channel infrared remote control system.
Commands and address used in this project
Our IR receiver recognizes 7 commands. Since there are only 5-channels (five relays), the five commands are used for toggling each individual relay. The rest 2 commands are used for turning on or off all relays, respectively.
Choosing the best set of supported commands based on the concept of compatibility. We wished to design a receiver that would be able to recognize basic commands supported by most widely available RC-5 transmitters. Thus, we purchased a 7-buttons commercial transmitter (a basic TV -remote control), for 5$ and we used the same commands that are used in it.
By decoding its stream, we found that the commercial product uses commands 21h, 20h, 11h, 10h, 0Dh, 0Ch, 01h for its seven buttons and 00h for its address. So, we decided to use this specific set of commands and address for our receiver too. These specific command and address values are declared in code as typical constants and once you have the source code, they can be easily changed to whatever you like.
Although our receiver uses 7 commands, the transmitter in this project has only 5 buttons and supports only the first 5 commands for toggling the relays.
The source code for our receiver is written in C, and the 7 supported commands are implemented as 7 separate if – statements in the main routine. So implementing a remote control receiver which would support more than 7 commands would be only a matter of adding some more if-statements in the main routine.
Building the infrared remote control system
To build the IR transmitter and the receiver, first you must purchase the required components from your local electronic components store. Then you must assemble the circuits on circuit boards. You can use either general purpose circuit boards or a circuits – breadboard. You can also print your own printed circuit boards according to the designs provided below for the transmitter and the receiver PCBs, respectively.
After assembling the circuits, you‘ll have to program the microcontrollers by using an appropriate PIC programmer and the firmware provided in hex files (machine code). For “burning” the code into prototypes, we used PICKIT 3 programmer – debugger from Microchip.
Normally, you do not need to download the source code in order to build this project. However, you’ll definitely need to download the source code in case you wish to make changes in the initial design or if you wish to build your own version with any possible set of commands, addresses, channels and buttons.
Printed circuit board and assembly guide for the transmitter
Printed circuit board and assembly guide for the receiver
Infrared Transmitter firmware (hex file - machine code). Use this firmware to program the PIC12F617
Infrared Receiver firmware (hex file - machine code). Use this file to program the PIC16F84A
Source code in C for infrared transmitter (paid download)
Source code in C for the infrared receiver (paid download)