Hacking and Controlling NEC-IR Devices
In this tutorial you will learn how to ascertain the protocol of most NEC-IR devices, and then use an Arduino to replicate signals and thus control said device(s).
There are a lot of devices like this: TV/DVD/etc Remote Controllers, a whole whack of toys (if your toy uses IR, it likely uses NEC-IR), and even cameras.
So for this tutorial I will go through hacking two different toys: one with discrete buttons (Inchworm), and one with ‘throttle-sticks’ (S107). Covering those covers any type of controller I know (what’s different than buttons and sticks right?).
Here is a quick video of the final result (only really a proof of concept).
********************************
********** Quick Links ***********
********************************
IRToy Arduino Code
(to control either, or both, the Inchworm and the S107 Helicopter via Serial CMDs)
IRToy GUI Processing Code
(Very basic code to send the Serial CMDs)
IR Recorder Arduino Code
(to capture IR signals)
****************************************************
*************** Recording and Hacking ****************
****************************************************
NEC-IR is pretty easy to record, the value zero and one are differentiated by the duration of a standard pulse pattern.
For example, say the pulse frequency is 38KHz (most stuff is), and the pulse duration is 300us (micro-seconds). Then Zero could be a 38KHz pulse ON for 300us and then OFF for 300us, and the One could be a 38KHz (frequency never changes between zero and one, it is more like a constant) pulse ON for 300us and then OFF for 600us. So by being off for 600us as opposed to just 300us, we know that means ONE.
The other part to NEC-IR is the concept of a header and footer (lots of communication protocols use these to align to the data; makes for a more robust design). So there will be a header pulse ON for 2-4ms (milli seconds), followed by OFF for likely a shorter length. The footer will be the opposite, ON for a shorter time and then OFF for 2-4ms (I normally just say off for 65ms, that way you can just send CMDs constantly).
I took some code from here and augmented it for my setup and also to capture windows (that link also has more info on NEC-IR).
Here is my RecorderCode and a pic of my dead easy setup:
You can buy IR detectors almost anywhere nowadays, but here’s one that seems good (I used a: GP1UM26XK00F). Also, you may want to note that I used a 40KHz receiver to detect 38KHz signals, they are so close, the only thing that might happen is attenuation (so if you use a freq != to the LED, just be sure they are close [~10cm] , maximizing signal amplitude).
My code assumes PIN2=Vout, PIN3=GND, and PIN4=VCC (also seen in the above pic).
I setup the code to capture a window when armed, so once you program your Arduino and startup the serial monitor (Shift+Ctrl+M), all you have to do is send: ‘Arm_’ to arm it, and ‘clc_’ to clear (actually the _ can be any non-alpha character).
Once the thing is armed it will say so and spit out some GARBAGE data, next you push the button.
The easy way (that might mess up) is just push the button.
The more accurate way is to gather LOTS of data, so when pushing the button, cover the transmitting LED with your hand before pushing, and use your hand like a shutter on a camera. ‘Expose’ until you see the phrase “Ring Buffer Looped”, that means you filled up the memory (and likely caught the entire frame).
Recording the Inchworm toy:
So for this toy, the output for the ‘up’ button was:
Ready to be Armed! Armed! (Here's the garbage data you ignore) Received: (TimeON TimeOFF)usec 400 100 300 100 ... more lines 260 100 220 100 260 0 (Now I push the button) Ring Buffer Looped Ring Buffer Looped Ring Buffer Looped Ring Buffer Looped Ring Buffer Looped Received: (TimeON TimeOFF)usec 260 360 420 500 460 480 ... more numbers, and then a pattern seems to emerge 2040 380 2040 860 460 1440 480 480 480 480 460 500 460 500 480 480 480 1420 480 1420 480 1420 480 1420 480 42604 2040 380 2040 860 480 1420 480 480 480 480 480 480 480 480 480 480 480 1420 480 1440 460 1440 460 1440 460 42604 2040 380 2040 860 480 1420 480 480 480 480 480 480 480 480 480 480 480 1420 480 1420 480 1440 460 1440 460 42604 2040 380 2040 860 460 1440 460 500 460 500 460 500 460 500 480 480 460 1440 480 1420 480 1420 480 1420 480 42584 and more numbers.. The window is very large.
So if you look closely, you can see the most common pattern is:
2000 400 header (note that you will need to add 2ms, so it's really: 4000 400) 2000 800 header 400 1400 1 400 500 0 400 500 0 400 500 0 400 500 0 400 500 0 400 1400 1 400 1400 1 400 1400 1 400 1400 1 400 big# footer
And that’s the code (1000001111)!
(For sending, skip ahead to the next section)
Recoding the S107 Helicopter:
This is different because we know that there are a whole range of CMDs that can be sent. So we change our thinking from finding single codes to finding WHERE the numbers are in the code.
So when you record, be sure to have the joy sticks at max positions (and again with them at min), collecting until the buffer fills. And again, be sure to cover the transmitting LEDs before releasing/setting the joy stick (otw you will send all the commands in-between or after).
After looking over a few recordings, covering all controls at max and at min (took me quite a few runs), you should notice that there’s clearly 4 8-bit values with a header and footer making:
4ms ON, 2ms OFF (header), 4×8 bit values with One (300us ON, 600us OFF) and Zero (300us ON, 300us OFF), and a footer of: 360us ON, 65ms OFF.
The 4 8-bit values are (in time):
first: Yaw Adjust (0->127, with 63–>zero adjust)
second: Throttle (0->126, and the MSB is the Channel, in case you have two S107s)
third: Pitch (0->127, with 63–>zero pitch)
forth: Yaw (0->127, with 63–>centred yaw)
All the complete details are found in the Arduino Code for the IRToy.
****************************************************
******************** Controlling *********************
****************************************************
I whipped up some code for controlling the two toys above, so you have a reference and something to plug and chug.
Note the Arduino Code has the option of burst or not (the difference is burst means flash pins 8-11 instead of just flashing 8), burst is on by default (because if you don’t use the output pin, no current flows, so you’re not wasting anything).
Arduino IRToy Code, Processing GUI IRToy Code (Very basic, mostly just does the serial for you)