The goal
Decode IR remote transmission, so we can build IR remote emulator to control our stereo from network.Usability
High. Can be part of intelligent house project.Hardware
Description
In this project, you can find answer, how to build IR remote emulator whitout knowing your device's IR communication standard.Introduction
IR remote controllers communicate with dedicated devices by sending infrared data sequences. Different devices (stereo, TV, CD, DVD) use different IR messages, some may use RC5 which is (was) more popular, other use their own standard developed by manufacturer. Every type of device has it's own code, so is possible to control TV and CD by one standard, because two IR remotes are sending two different device codes and one command code.Noise
IR sequences are send by turning On and Off IR diode. That kind of change drives IR receiver and on its output we can see voltage changes corresponding to IR diode off/on state. But what with interference of other sources of light, e.g. from your desk lamp or direct sunlight ?.If you plug a photoresistor into your microphone port (from your computer) and point it at your desk lamp (12v transformer and 12V halogen bulb). Then you can hear buzzing from your speakers, this is your AC frequency. Human eye will not see this, but you could clearly hear that light is generating 'light noise'.
When you put in direct sunlight, there we'll be no noise in speakers. Sunlight will 'block' in one state (conductive).
So, from above, we have two serious noise sources which would make mess in our device's IR receiver. To avoid above problems IR diode is connected to 36-38kHz generator. So when we're sending sequence e.g. On-On-On-Off-Off-On-Off-On, IR diode is sending 36kHz-36kHz-36kHz-Off-Off-36kHz-Off-36kHz in some constant amount of time.
IR receivers have filters on that frequencies and for light wave length so interferences from other sources was significantly reduced.
Decoding any IR signal
To decode IR you must have IR receiver that matches yours IR remote carrier frequency e.g. 36-38Khz.IR receiver on my Atmega32 board |
Receiver is connected to interrupt pin PD3 which triggers interrupt vector SIG_INTERRUPT1 on every falling edge of PD3 pin.
SIGNAL(SIG_INTERRUPT1) { // here is will be code for IR decoding return; }
No we have to fetch one frame from IR remote and discretize it, this will help us to prepare proper message and 'play it back'. For this we connect our IR receiver output to oscilloscope, set trigger to one shot and press any button on our IR remote.
One IR frame, one command from IR remote |
Now, we've got to find the shortest state '1' (in reverse logic = '0'). This state is very important, it will give us base to calculate proper sampling rate to 'record' and analyse data sent in IR sequence. For finding shortest state, we have to change horizontal resolution in our oscilloscope.
Shortest state is 500us |
Shortest state increased |
SIGNAL(SIG_INTERRUPT1) { char data[512]; // this should be enough unsigned short i = 0; for(i=0; i< 512; i++) { if( IS(PIND, PD3) ) // check pin PD3 - here is our receiver connected data[i] = '0'; // set in reverse logic, because receiver gives else // 5V at idle and 0V when sees 36-38kHz wave data[i] = '1'; delay_us(100); // sampling delay } data[511] = '\0'; // make sure to end string properly // this is fragment from my C++ code for atmega32 // operator is overloaded and works pretty awesome *rs << data << "\r\n"; // make sure, that only one command will be fetched delay_ms(500); delay_ms(500); return; }Above code will return something like this on our RS232 port. I use putty to connect to my /dev/ttyS0, so this is output from putty.
11111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000111100001111000011111000111110000000000001111000000000000111100000000000011110000000000001111100001111000000000000111100000000000011110000000000001111000011111000111110000111100001111000000000000111100001111000011110000000000001111100000000000011110000000000001111000011110000111100000000000011111000000000000111100000000000011110000111100001111000011110000000000001111100000000000011110000111100000000000000000000What happened here ?, for every '1' should be five '1', but only if we assume, that delay works ok and check pin state operation is timeless. But it's not, from above we assume that original shortest state was 400us instead of 500us, of course if you have always five '1' then ignore this tip.
Outputs from IR commands:
init + mute: 11111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000111100001111000011111000111110000000000001111000000000000111100000000000011110000000000001111100011111000000000000111100000000000011110000000000001111000011111000111110000111100001111000000000000111100001111000011110000000000001111100000000000011110000000000001111000011110000111100000000000011111000000000000111100000000000011110000111100001111000011110000000000001111100000000000011110000111100000000000000000000 init +VolDown: 11111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000111100001111000011111000111110000000000001111000000000000111100000000000011110000000000001111100001111000000000000111100000000000011110000000000001111000011111000111110000111100001111000000000000111100000000000011110000000000001111100000000000011110000000000001111000000000000111100001111000011111000111110000111100001111000011110000111100001111000000000000111110000000000011111000000000000111100000000000000000000 init + On/Off: 11111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000111100001111000011111000111110000000000001111000000000000111100000000000011110000000000001111100011111000000000000111100000000000011110000000000001111000011111000111110000111100001111000000000000111100000000000011110000000000001111100000000000011110000000000001111000011110000111100001111000011111000111110000111100001111000011110000000000001111000000000000111110000000000011111000000000000111100000000000000000000
As you can see this message is duplicated like 4 times, this is true, because we set sampling rate to 1/4 shortest logic state. Sampling is helpful to reduce errors, because in this sequence every logic state (1 or 0 sequence) should divide by 4 without the rest.
Perfect timing for our loop will give us '1111' for every original '1' (before sampling) , so errors are easy to detect: '111' and '11111' should be '1'.
Below you can see whole IR sequence after removing errors and bringing it back to original state, that means multiplicated by 4.
mute: 111111111111111100000000101010100010001000100010100010001000101010101000101010001000100010101000100010001010101000100010100000Now sample rate for this message is 400us.
In next step we have to separate constant fragment from command, you must have many sequences to filter this out. It's better when init sequence will be ending on '0', even if you must move '1' to command sequences.
init: 111111111111111100000000101010100010001000100010100010001000101010101000In this message, we store only '1' and '0', so we can treat it like bit and put 8 bits in one byte, it's more economic like this.
const unsigned char init[] = { 0b11111111, 0b11111111, 0b00000000, 0b10101010, 0b00100010, 0b00100010, 0b10001000, 0b10001010, 0b10101000 };We're ending with two tables, one is the constant sequence which will be send every time, second table contains only dedicated command, like 'mute' or 'VolUp'.
const unsigned char init[] = { 0b11111111, 0b11111111, 0b00000000, 0b10101010, 0b00100010, 0b00100010, 0b10001000, 0b10001010, 0b10101000 }; const unsigned char mute[] = { 0b10101000, 0b10001000, 0b10101000, 0b10001000, 0b10101010, 0b00100010, 0b10000000 };
About the delay
Sometimes delay is not set properly, or operations can last longer/shorter than you've assumed, so after you write some code to send IR commands, check them on oscilloscope if they match your device's timing standard.Send sequences
To send sequence to IR device, you have to remember about your IR carrier frequency (36-38kHz). This could be generated by TimerCounter from your microcontroller.I'm sending IR sequences, by enabling/disabling timer enable flag, to send 36-38kHz carrier.
Working device and full source code you can find in IR remote emulator with attiny45
No comments:
Post a Comment