Experimenting with IR Remotes using a PIC running BoostC Project
- 1 Experimenting with IR Remotes using a PIC running BoostC Project
- 1.1 Hardware
- 1.2 Command Interface
- 1.3 Microcontroller Program
- 1.4 Other Things to Try/Additions/Changes/Modification
- 1.5 Possibly useful links
- 1.6 Download
- 1.7 Comment, Questions, Contributions?
Experimenting with IR Remotes using a PIC running BoostC Project
- Name: Experimenting with IR Remotes using a PIC running BoostC Project
- Status: done, until enhanced
- Technology: PIC microcontroller, slavaged IR reciever, running with code in BoostC
- Author: russ_hensel ( where you can find an email address to reach me )
- Summary: A PIC16F877A project that reads IR remote controls. Runs with a PC running a terminal program.
- Last revision: see page history.
- Download: available, see section below.
This project describes just enough software and hardware to let you experiment with infra red remote controls to use as a jumping off point for a more complete project.
Platform: PIC16F877A using BoostC connected via rs232 to a PC running a terminal program. The PIC chip is supplemented with a slavaged IR reciever.
This code may be used as part of a user interface into a larger project. One pin supports all the buttons on a remote, and a universal remote is only about $10. and works remotely.
Taking apart old VCR's and similar devices you can often find small IR remote receivers. These are outwardly simple devices, an IR sensor looks something like a LED but perhaps hidden behind a grill or filter and 3 wires. The wires are for power ( two wires, +5 volts and ground ) and one for the signal which goes to a PIC input port. Shine the light from an IR remote control ( from a broken, or not TV, the dump or buy a universal remote ) and the output pin jumps up and down for a while. Learn what the jumping means and figure out what button was pressed on the remote. Add a whole new interface to your PIC projects using only one pin.
An IR receiver whose spec sheet is easy to Google is the GP1U58X, this will help you with the pin out. Other information on the receiver and hardware can be found by Googling for the many other projects out on the web.
For the PIC part of the project I use my favorite 16F877A set up as in PIC based Stepper Motor Dancing Analog Clock. Use input RB.0 as it has an interrupt available. Use the UART and a PC for other control of and communications with the PIC as with the Clock.
I think you can figure this out, if not take a look at another project like PIC based Stepper Motor Dancing Analog Clock
|Power supply||Not shown, 5 volts, you can use a higher voltage with a voltage regulator. There is a suitable power supply in the PIC based Stepper Motor Dancing Analog Clock|
|PIC16F877A||My favorate 16 series part, relatively lots of memory and pins. Bigger than you need, but only about 8 bucks. Try with an 18 series part, should not be hard and will leave you more up to date. Let me know. Other parts of the PIC circuit not discussed here.|
|Q = crystal||4 meg Hz is what I used. May be quite a bit faster than needed, I have not looked into this. The 4 meg crystal seems to work ok on a proto board. Note that some of the code is dependent on this frequency, but could be fairly easily changed.|
|C_BP = By Pass Cap.||Good idea to add one. A .01 to .1 mfd mica or other by pass cap, good at high frequency seems good.|
All commands ( except stop should be terminated with a carriage return ) Note that the command interface is not very smart, giving parameters that are out of range my blow the whole program up. If so reboot the PIC. Do not send a new command ( except stop ) until earlier commands have been completed ( actually you can get ahead some if you are careful )
|Command||Code||Notes, PIC Response|
|Report version||v<cr>||Version of the PIC software something like:
Serial Stepper Test ver July 4 2008
reset the counters and the log of the encoder. Response something like "Reset Count"
|Log report||l<cr>||Report the log of data. A series of binary numbers, comma delimited.|
|Report on all parameters||r||Delimited by commas something like:|
|Position of the encoder||p<cr>||report the position of the encoder, and other counts of encoder activity.|
|Stop||!||Should almost immediately stop long running commands of which there are currently none. Response Stopped.|
|Other, not understood commands||xxx||Responds with "!Bad Command = xxx" if the command is not understood.|
Notes on terminal program set up.
- Baud rate should be 19.2K 8N1
- Most terminal programs can be set to treat a carriage return as a carriage return line feed. Do it.
Some terminal programs will not transmit in lower case ( all our commands are lower case ) unless specially set to do so. Set it to allow lower case.
Design -- Polling Routine
The code in the download files is the project \IR.
If you look at the subroutine readIR( void ) you will see the heart of the IR receive. The routine loops each time checking to see if the output of the detector has changed. If it has not it adds one to the period, if it has it records the period and resets the period to 0. When the input goes quiet for a while it is taken as the end of the signal and we exit. Pretty simple.
The software logs the period of each transition at the input pin in units of the time around the receiving loop. The number of log entries is limited to about 100 due to memory limitations. Because the timing is in terms of times around the receive loop the code has been written to make this time ( roughly ) constant despite branches within the loop.
Control of readIR() is normally via an endless loop ( which the stop command breaks you out of ) which:
Listens for quiet on the IR signal, this stops us from starting to receive in the middle of a signal. Setting an interrupt to call readIR() on the next IR signal. Running readIR() Outputting the log or the received signal.
You can take the data from the log and put it in a spreadsheet to try to analyze what is going on. There is much information on IR protocols on the web.
One of my remotes seems to use the NEC protocol and I have added a version of readIR() to decode this signal, it is called readIRNec(). In this protocol there are basically two different low periods of the input, a short one is read as a 0 the long one as a 1. The code seems to work. I got the information on the protocol from .
I have tried to do a good job commenting the program, try reading them for more info. Comments on the comments, email me russ_hensel.
Note that the design blocks other activities in the software once the interrupt is triggered. This lasts about .1 seconds. I think the next itteration of the software should interrupt on each bit ( not just the starting bit ) and a timer should be used to time the bits. Then other tasks using either the main loop or other interrupts would not suffer much inpact. I will work on this at some future time ( update, I have an almost complete implementation Jan 9 09, should post fairly soon ). Do you have some code? Add your material here.
Some credit should be given to John Main  whose code I studied to aid in writing this.
Control of the software is via the serial communications library that I have described in other articles including Serial Communications Library -- BoostC and 16F877A. It yields a command driven interface with the following commands.
|!||Stop whatever is running, like read ir and and read NEC. Then you can select a new command.|
|V<cr>||Version of the software, responds something like: IR.c version = Dec 29 2008 b|
|I<cr>||Read Ir Data in a loop without decoding. Generally turn log on or you will not see much in the way of results.|
|N<cr>||Read Ir Data in a loop with NEC decoding. Generally turn log off unless you are debugging the decoding.
Response looks something like:
exit waitForNoIR() IR Data = 10001011,01110100,00000011,11111100, IR Data hex = 8B,74,03,FC, XOR = 11111111,11111111
|Ln<cr>||Turn log report on with n=1, off with n=0. The log report gives the count of periods between all tranitions.
When reported the log will look something like:
Lot Len =66,72,12,24,12,5,12,24,12,5,12,5,12,4,13,23,12,5,12,5,13,23,12,5,12,24,12,24,12,24,12,5,11,25,11, 6,11,6,11,6,11,6,11,5,12,5,12,5,12,24,12,24,12,24,12,24,12,24,11,25,11,25,11,24,12,5,12,
The first number is the number of items logged, the rest are the peiriods logged ( up to a max of about 100 )
Design -- Interrupt Driven Routine
This is similar to the design above but the IR sections have be rewritten to use interrupts. For an explanation see: A Tutorial on PIC interrupts using BoostC including Example Programs The code in the download files is the project \IIR. This version is probably much better for use in a project than the non interrupt code, but was harder to code, and may be harder to understand. It only decodes the NEC ( inc Toshiba ) codes, others are logged for timing.
Notes on the NEC Decoding
Using the  as I guide I guessed at the periods infolved in decoding 1 and 0's. The specification say that the odd numbered bytes should be the bitwize not of the next prior byte. I xor these together, if the decoding is right this should yeild a 1111111 which it seems to do. The button <1> decodes to 03 ( the third byte ). Each sucessively higher button goes up by 2. To see more codes, build the project. My transmitter was not actually a NEC but was a Toshiba which is supposed to be the same, perhaps it is. Test stuff yoursel before trusting the code too much.
The zip file contains the entire source bootst project. Unzip into a directory and open in source boost. Set the target to 16F877A. See the comments in the program header for other setup before compiling. After compiling my compiler reports something like:
Memory Usage Report
- RAM available:368 bytes, used:248 bytes (67.4%), free:120 bytes (32.6%),
- Heap size:120 bytes, Heap max single alloc:95 bytes
- ROM available:8192 words, used:1239 words (15.2%), free:6953 words (84.8%)
The program seems to be safely under the 2K free compiler limit.
Other Things to Try/Additions/Changes/Modification
- The 877A is way overkill for this project unless you make it do a bit more. Note that only 1 input pin ( with interrupt capabability ) plus the serial lines are really used.
- Make more interrupt driven.
- Decode other brands of remotes.
This program uses my: Serial Communications Library -- BoostC and 16F877A
More information on serial communications with microcontrollers: Microcontroller Serial Communications Articles
A free terminal program, I like this much better than hyperterminal: Welcome to our Free Download/New Products Page! http://www.rs485.com/psoftware.html
BoostC – I think the free version is enough to compile the program: SourceBoost Technologies http://www.sourceboost.com/
Comment, Questions, Contributions?
Email me russ_hensel, or use the talk page for this topic. All feedback is welcome.