TV Remote Reader
Background
This program was devised so that I could compare and analyse IR Remote signals. It started out simple and grew. It could be worse! The project uses the IR Receiver from Cool Components
http://www.coolcomponents.co.uk/catalog/product_info.php?cPath=36&products_id=169
and the Nokia 6610 LCD screen from the same source.
http://www.coolcomponents.co.uk/catalog/product_info.php?cPath=24&products_id=147
Tech Stuff
There are several signal formats used by the different manufacturers, of course. I have been using Sky+ because it is a common one and fairly simple (compared to some). The information I want from the pulse stream is the last 5 bits which are the key press data - lsb last. This is quite convenient for this reader because the simplest way to get the data is to start to sample at a time beyond the lsb and gradually step forward until the first bit is found. Getting ahead of myself here.
The format and decoding of the IR signal is covered on the web, so if you want it, you can find it - I'm not going to try and explain here!! Basically, the Remote spits out an IR pulse stream each time a key is pressed. There is a repeat function which is very useful. The pulses have a pulse width, an interval, and a meaningful location within the "word". The words are repeated having a fixed inter word gap. Naturally, all Remotes have different values for all these settings.
The detected signal from the IR Detector is high for no signal and low for a pulse. So I will stick to that format throughout otherwise it gets too confusing. The basic picture of the IR output is something like this.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ etc
A Word 1 B A Word 2 B
(well, that didn't work! Go to "Edit ths page" to find out what I intended!)
The time between pulse streams provides a high input to Mbed so the word is detected by the first high to low transition at "A". This provides a reference for everything that follows. The first read is at a predefined time after "A", identified as "B" and called "porch" in the code, with the expectation of finding a high signal. The porch is reduced for the second read and so on until a low is detected at which point the lsb of the word has been found and the time from "A" is noted. As the porch is decremented the reads will find all the bits in the word and the times they occurred. Here, only the first 8 bits are of interest, giving a max key code of 255, more than enough for the number of keys on the Remote. As each read constitutes a slice of the signal, the smaller the change in the porch, the higher the resolution of the timing but the longer it takes to get the information. The detail of the process can be determined from the code comments. I believe in lots of comments!
Photos
Here are lots of photos to illustrate what the program does. At the top of the screen is a title, vital so as not to loose track, next is a list of the pulse timings with the negative and positive transitions for each of the data pulses. At the bottom is an oscillogram of the waveform, useful for adjusting the porch to reduce time waiting for the first pulse. Necessary with tiny porch decrements or you could wait all night for a scan to complete! The only useful photo is of the "0" key as all the data bits are set to 0. Looking at the other photos will serve to mess your head so don't try and figure it out without reading this first!!
| | |
|
| | |
|
The sharp eyed will have noticed that the timing of the pulses is not that consistent between photos. I'm open to suggestions but I think that reducing the delta porch from 50us to say 10us would do a lot for the accuracy. (Also that the JVC photo indicates that this is a totally different format.) If the porch decrement is reduced to increase accuracy, then the samples per pulse will increase and the pixels in the display will increase, stretching it proportionally. I thought of compensating for this but decided that it was more useful stretched to time porch better.
Interpretation of results Refering to the Sky+-0 photo, the read timing should coincide with the centre of the low parts of the trace as this is where the bits are located. i.e. between 25000us and 24600us for the 1 bit, 24200us and 23750us for the 2 bit etc.
When reading the Remote for real, the msb will arrive before the lsb, so the first bit to be read will be the 128 bit located between 19200us and 18750us i.e. 18975us after detection of the beginning of the word. Thereafter, the pulse reads are 800us apart. Whats more, it works.
Source Code
//TV Remote Signal Interpreter Author : Andrew Young 9/11/2008 //Use this program to figure out the timing of the data bits from an IR TV Remote //for use in the Remote Decoder program. Set up using a Sky+ remote. //Note: There are many totally different signal formats. This can cope with some of them. //Also, this is not timer based so there are unquantified timing errors due to printf etc. #include "mbed.h" #include "MobileLCD.h" MobileLCD lcd(5, 6, 7, 8, 9); DigitalOut Pulse(19); // strobe out for scope DigitalIn IRin(20); // IR sensor input from Coolcomponents IR Breakout //Stuff to fiddle with for different remotes and a decent display and timing "accuracy" int porch = 26000; // time in us from first pulse edge until initial data read. // Probably the greatest difference between remote types. int porch_dec = 50; // time between read samples in us, smaller for greater accuracy int interval = 70; // approx time between pulse trains in ms (with a bit of leaway) int col = 2; // screen column, away from edge int row = 2; // screen row, data start two from top int disx = 128; // display x max coordinate int disyhi = 110; // display y coordinate for high input int disylo = 120; // display y cordinate for low input int edge = 1; // detect edges so edge timing only printed int bitval = 1; // bit position being read int main() { lcd.background(0x000000); //set screen background lcd.cls(); //clear LCD lcd.printf("Sky+ key 0"); //screen title while(bitval < 513) { //limit the prog to data pulses only if(IRin==0) { //locate the start of the pulse train // Pulse = 1; wait_us(10); Pulse = 0; //start pulse for scope use wait_us(porch); //set the time to after bit 1, last bit in //the pulse train!! // Pulse = 1; wait_us(10); Pulse = 0; //porch pulse for scope use if (IRin == 0) { //wait for input to go low lcd.pixel(disx,disylo,0xFFFFFF); //paint a white spot for low lcd.pixel(disx,disylo+1,0xFFFFFF); //make it thicker disx = disx - 1; //move to next spot location if (edge == 1) { //only print after edge lcd.locate(col,row); //move print location lcd.printf("%hu",(bitval)); //print which bit no lcd.printf("-"); //indicate -ve transition lcd.printf("%hu",porch); //print time of -ve transition bitval = bitval + bitval; //inc bit value if (bitval > 9) col = 1; //compensate for 2 digits if (bitval >99) col = 0; //compensate for 3 digits row++; //inc edge row edge = 0; //no longer an edge } } else { //if input is high lcd.pixel(disx,disyhi,0xFFFFFF); //paint a white spot for high lcd.pixel(disx,disyhi+1,0xFFFFFF); //make it thicker disx = disx - 1; //move next spot location if (edge == 0) { //only print after edge lcd.locate(10,row-1); //move print location lcd.printf("+"); //indicate +ve transition lcd.printf("%hu",porch); //print time of +ve transition edge = 1; //no longer an edge } } porch = porch - porch_dec; //move porch forward wait_ms(interval); //wait for next pulse train } } }
I set Interval, the time between words minus a little so that the word detection starts in "dead" time. If this is too short or too long, then the next word read can start in the word rather than before it. This leads to serious confusion and is why different Remotes respond differently!








