How to capture and reverse engineer an infrared IR code and use an Arduino or other microcontroller to replay the command.
Oscilloscope and logic analyser capture, coding, troubleshooting, tounge angle, it's all here.
In this instance Dave captures the NEC (Japanese) code from his Canon video camera remote control on the digital oscilloscope, figures out all the bits and encoding, and writes an Arduino library to replay the code back, and verifies it with his Saleae Logic logic analyser.
Previous simple hack video: http://www.youtube.com/watch?v=vOzaDQmAW0g
CODE: http://gist.github.com/EEVblog/6206934
Forum: http://www.eevblog.com/forum/blog/eevblog-506-ir-remote-control-arduino-protocol-tutorial/'>http://www.eevblog.com/forum/blog/eevblog-506-ir-remote-control-arduino-protocol-tutorial/
EEVblog Main Web Site:
http://www.eevblog.com
EEVblog Amazon Store:
http://astore.amazon.com/eevblogstore-20
Donations:
http://www.eevblog.com/donations/
Projects:
http://www.eevblog.com/projects/
Electronics Info Wiki:
http://www.eevblog.com/wiki/

Hi. In a previous video, I showed a very rudimentary hack of one of these infrared learning remote controls and how you could, uh, hack in and directly drive one of the buttons which you can pre-program from something like an Arduino microcontroller or anything else. It could be some other external switch or some other external circuitry and that was incredibly, uh, simple and rudimentary hack. But there were quite a few people who wanted to know uh, how to do that directly from a microcontroller like an Arduino for example itself, instead of having to hack a remote control.

why can't we just can, we just put an infrared LED on one of the output pins of the microcontroller and transmit the code directly. Well, yes, we can do that, and uh, it's not entirely difficult. uh at all. So that's what I'm going to show you today: how we're actually going to receive a Uh code from my Canon uh, wld d89 uh, remote control for my video camera here, and how we're going to, uh, capture that on our oscilloscope and then program it into this Uino.

Now, there are, of course, many different ways to skin this cat. I Mean you don't have to use an oscilloscope like we're going to use today. You could use a logic analyzer like this uh s uh, logic analyzer Or you could use the Arduino itself. For example, you can get libraries that actually read in infrared code from an infrared receiver and play it back.

We've got a Uh INF USB dangerous prototypes USB infr red uh Toy IR toy here which we're actually going to be using to capture the data, but that can stream it to a PC and then you can analyze the data on the PC and know exactly what it is. And you can get all sorts of Open Source libraries on the Uh PC. To do that, you just hook up an infrared uh receiver to it and uh, there's you know, many, many different ways to do this, but we're going to do it um, the oldfashioned way. We're going to actually, uh, get our digital scope and we're going to capture the waveform coming out of the IR receiver.

We're going to get the individual bits from it and the timing. and then we're going to program that into our microcontroller so that then we can spit out the IR code. Now there's two devices you can actually use to receive the infrared code from the remote control. One is just your basic Uh Photo diode, infrared photo diode, SL photo transistor and they can either come in uh, two lead or three lead configurations like this one here and these are fairly are't limited devices.

but what they allow you to do is to get the actual raw carrier frequency out of the infrared remote control as we'll see. But there's also these other three pin devices which are these, uh, proper infrared receiving modules and they've actually got circuitry in there that uh, decode and demodulate the carrier frequency and give you a direct data out and we'll see this on the oscilloscope in a second. So um, the good thing about this USB infrared? Uh Toy We can actually uh, probe both of these sensors and see the different types of data coming out. Now the good thing about these little uh infrared modules is that you pretty much never have to buy them because you should have them in your junk bin because pretty much any bit of surplus consumer gear.
For example, I've got a Um set toop box uh PVR one of those PVR recorders here. and if you're you know any old bit of gear, an old CD player or anything that you Salvage we'll have one of these in it. Check it out, rip it out, reuse it. Not a problem, and just be aware that there are different uh, carrier frequency modules.

but uh, the most common type that you're going to deal with is the 38 khz carrier frequency and we'll actually be able to measure that cuz we'll be getting the raw uh data carrier data d uh out of this photo diode here. Okay, we're going to use our Ccope to capture first of all, on Channel One. here. we're going to capture the output data from the IR module.

so this is the one that has the demodulator built in. It'll take out the carrier frequency as you'll see and we'll just get the Raw One Z data out of it. Now What you want to do? This is a 5vt one. so you want to set it to 1 volt uh, per division? roughly? Let's put it down here.

Uh, you want to set it maybe 50 milliseconds per division? a fairly um, you know, slowish uh time base So we can capture the entire packet and then zoom in later And this is where an oscilloscope with deep memory is going to come in. So you know you don't want to use an old school oscilloscope with, you know, 2K of uh, sample memory or something like that. A nice good deep memory uh scope, especially if you're capturing more than one uh packet. So we'll take a look at that.

But here we go: I've got my infrared remote control I got Channel One hooked up to the output of that IR module which you can salvage from any bit of uh gear you want and I'm going to push my uh start stop button which is the one I want to capture and bingo there it is. We've captured that I had it set to single shot mode of course triggering is somewhere in the middle there and uh, let's there it is and uh, we can zoom in and we can see the data coming out of that Bingo We've captured that packet now. look what happens if I do that again and I press the button for a bit longer, hold it down for a bit. There we go.

Look, We actually captured five uh packets there, because if you hold down the button, it will ually send uh, the packet and then uh, your product that you're actually um, you know, pointing this out can actually decode that you've pressed that button for like 3 seconds or something like that. For example, like uh, to go into the playback mode on my video camera I've got to push this button here for like 3 seconds, hold it down, and then it will go into playback mode So it just sits there counting those packet, decodes them, and counts it, and it knows I've pushed that for 3 seconds. Now, as you can see here here, the output of the module is normally high and then it goes low like this. so we're getting a zero out of that.
But what that means that zero is that it's actually receiving uh, because it's a logic low output. When it receives a carrier frequency, we'll see this in a second when we probe our photo diode directly. So there's that means that the infrared when this is low, when our signal is low, it means our infrared uh, lead is transmitted. So when we decode this data and program it into our micro controller, decode the ones and zeros A zero here means switch on the LED at the carrier frequency rate.

And likewise, when we've got a logic one up here, then that means the lead is Switched Off it's receiving nothing now. What I'm going to do is switch on Channel two here and I've got Channel 2 hooked up to the other the photo transistor down there, which is going to give us the direct uh data from the transmitter here here. And of course, we still got Channel One hooked up to our uh infrared module there. So here we go: I'm going to press the same button again and we'll capture that data packet.

There we go. So as you can see Channel Two here from that infrared photo transist, there's a big block there and what that is is the carrier frequency. we can zoom in on that see. It's practically identical and almost lined up as we'll see.

So let's zoom in on that. So let's move our position over here and zoom in on that first bit. It goes low. Bingo There's our carrier frequency and if we check out our frequency down here, it's decoded That there you go.

38.4 khz. It's going to vary. It's not going to be uh, spot on, but it's roughly that 38 khz carrier frequency. So when we program that into our microcontroller, we need our microcontroller to not just go low and turn on the lead or go high and turn on the lead.

It needs to generate that 38 khz carrier frequ frequency. For that amount of time, you'll notice it's done exactly the same thing over here. Exactly the same carrier frequency. And you'll also note that the this blue waveform here is the raw data coming out of our trans infrared transmitter here.

so you can see that it starts uh, transmitting and it takes a few cycles for that infrared receiver module to actually decode that and then give our low output and it extends past there as well. But it's basically the same time period as that, uh, whole packet there. so that's just two ways at looking at the same data. so it doesn't matter where whether you've got just a photo diode, photo transistor, or whether or not you've got one of the proper um, infrared receiver modules.

If you got just got the module here, just assume that the carrier frequency is in there when that's low, and when it's high, you get nothing. And if you got the carrier frequency, uh, if you just got the uh infrared diode, well, you can just decode it exactly the same way and you notice the time of our burst there. There we're on. 5050 microc per division is just over 550 microc so we can get that exact value.
It's It doesn't have to be absolutely spoton, but it should be close so we'll measure that as accurately as we can. And I've used both my cursors there and I'm measuring 562 micros for that burst and you'll notice that the Dead period there where it's well, high, but it's actually Switched Off is exactly the same 562 microc. Now, you could be mistaken for thinking that these are individual one one0 bits in here and then you've actually got three zeros here. because if you actually go in there and measure it, this period here is actually yes, it is precisely three times that length there.

so you might think it's one and then 0, 0, 0. But that's not the case because I Happen to know that this thing looks precisely like the Japanese protocol or sometimes better known as the NEC uh protocol. Now, the unusual thing about the NEC protocol is it doesn't have a fixed bit length for both one and zero. It actually changes between those.

So let's take the example of like it's ordinarily high. So let's say the start of the bit is here. it goes low for that one. We'll call that one time period there, then it goes back high.

Uh, like that, and that represents a zero. but A1 is represented by it going low like that for that one time period and then go high again for three time periods like that. so that in there so that from there to there is a zero and from there to there is a one. So it's quite unusual.

but that's the NEC protocol and you don't have to think of it like that. Of course, if you're actually, uh, programming this into your microcontroller, then you could think of it as you know: 1, 1, 0, 0 if you really wanted to. But and you could actually program it and implement it successfully that way. But that just wouldn't be the correct way to do it.

cuz what we're going to find here is that in the total of all this, we're going to actually have four bytes for a total of 32 bits. Now of course, to decode that on your scope. Some scopes of course have serial protocol decoding, but I have never seen one that actually has the NEC protocol built in. and if your scope or your logic analyzer or whatever happen to have a custom protocol uh, decoder for example, then you might just be able to set that up to actually decode it and turn those, um, different Tim length periods into zero and ones for you and spit out that 4 byte code that the NEC control code actually has.

But uh, we don't um, have that capability here. So we're just going to decode this manually. So what we can do is go in here after our idle period and that's the start of our first bit there. and we can see that that first first one is a one because it's one time period with three, uh, blank time periods after that.
So that's a one one and then 0, 0, 0, 0 and that's called our pulse length encoding. uh technique. So we can go in there and just manually decode these. Not a problem whatsoever and we should get total out of that.

four different bites and I've gone through and manually decoded that and this is what we get. We get our four 8bit bytes there and the first two bytes are the address. so there we go, sends those, then it sends the command here and then the inverse of the command like that. So you should if you've decoded it right.

This last bite should be an inverse of that one. and that's exactly what we see on a bit by bit basis. So now we've got this data, we can program it into our micro. Beauty Now to throw a real spanner in the works.

Something like the Uh Phillips Rc5 IR protocol. For example, each time you press the key, it can actually toggle that bit each time. So what? I'm what I've set up here is I've captured this waveform and there's the I've stored it as a reference waveform here. So now I'll press it again and see if we get get an identical waveform.

Let's have a look. Does it look identical? It does. So I'll do that one more time. No, we don't have any toggled bits, so it looks like it repeats the exact same code every time.

You've just got to be careful there. Otherwise, uh, you know that could really, uh, ruin your day and changes the equation on how you're uh, going to write your IR driver and stuff like that. and here's the source code. The sketch I've written for this: uh yeah, I could have just used an off-the-shelf uh Library IR code Library Some of them are quite simple, some are quite, uh, complex.

There are a lot out there that do support the NEC protocol where actually after and a lot of them complete ones that receive codes and do all sorts of stuff. Um, but I wanted to write my own because, well, that's the spirit of this thing. And as it turns out, it's very, very simple. So I wrote it from.

load the source code for this from a link down below the video here. So I'll be very brief on this: I've set up my uh lead and my infrared lead on uh pin. you can just Define which uh pin of the Arduino you've got I've got my bit time 562 micros as we saw on the oscilloscope and then I Define the infrared code that I want to send. uh in this case, it's that four uh, 32bit code that we retrieve reverse engineered from the oscilloscope.

so in binary form. I've got it as one big 32-bit word there so that's all set up. You could have multiple codes for any command button that you wanted to send. This one is just the reverse engineer code for my Canon remote control uh, record, stop, record button and then I've got a simple setup routine here that just uh sets up The pin as an output for the LED and then it Uh switches the lead off to start with and I've got two simple routines and that's the entire code right there.
Just in those two routines almost fit on that one screen. a couple of dozen lines of code. The first one is the IR carrier and that generates 38 khz carrier frequency. All you do is pass it the time in microsc seconds that you want the carrier frequency to go for and then it just goes through a for Loop and turns the lead off and on there.

Not a problem at all. Now it's got to Uh divide that pass time by 26 micros here because 26 micros is roughly the inverse of the 38 khz carrier frequency that we got. and then all it does is it sets the Uh turns the LED on for half that period or 13 micros and then turns it off for 30 micros and it repeats as long as it needs to. And then we've got another routine which sends Uh the 32-bit code.

so you just pass it the code here as a long 32 bit long value and then we have the Uh let generate the leading pulse here as we saw on the Oscilloscope 9. Uh, 9,000 microc. We uh, turn the carrier on for that's 9 milliseconds and then we turn the carrier off for 4.5 milliseconds there. So it's we've generated our lead impulse and then all we do is we go into a full loop here and we send out all of our 32 bits or four bytes in sequence.

I'm just doing that using a mask here. So I'm just masking the most significant bit and then shifting it. Uh, one bit at a time at the end of it. That's why I did it as a 32-bit word.

It's just easier that way than say four individual bytes. Saves a few lines of code, and then of course, uh, we. Well, we start out by generating the one bit time 562 micros the carrier frequency, and then we have to determine via that maskin if our current bit is a high or a low. If it's a high, then of course we have to wait the three bit times dead time to signify a one in the Nsse protocol, but if it's a zero, then we only have to wait one extra bit time.

Very, very easy and that's it. It just repeats for all 32 bits and one thing I forgot to mention uh on the oscilloscope capture is I Also noticed a stop bit at the end of it, so it was actually had a 33rd bit on there. just a stop bit of one bit time. So I've added that in there at the end and then I've just got a main routine here.

All it does is calls, a setup, defines the pins, and then it sends my infrared code to switch the record mode of my camera on. it. Waits 5 seconds and then I send the code to stop recording. Easy and no surprises for guessing it didn't work First Go.

No, it wasn't Murphy's Law As a matter of fact, I kind of expected it it to possibly not work. First go and I'll show you why. So what I've done is I've hooked up my uh logic analyzer here because to analyze something like this, we really need to look at that code output. You can do it on an oscilloscope or but a logic analyzer is easy.
We can capture it here now. I've hooked up my Uh S logic analyzer to the LED output. I'm going to sample at 8 MHz here. uh, more than fast enough.

One Meg sample is good enough and negative. Uh Edge trigger here. So we'll start this and I'll press my reset button on my Arduino I've already downloaded the sketch and looky what we have here. We have our code that's exactly the same as what we saw on the oscilloscope and if we go in here, we can look at that carrier frequency of the leading pulse there.

and if you have a look on the right hand side I Can't move my cursor over, but it says the pulse width is 16.8 micros and the frequency is 29.9 khz. Nowhere near the 38 uh kohtz that we actually need. No wonder it doesn't work. Why? Well, it's uh, pretty obvious.

and those people who are experienced with these sort of things probably already know because in my timing Loop here my IR carrier Loop I've assumed that it's 26 micros. Okay, I've rounded that down near enough to generate the uh loop timing in here. That's not going to be a a real major issue. The major issue here is this delayed microsc.

You see, it's got 13, so we're expecting to get 13 micros delay. but look, we don't. We get 16.8 So there's another what, uh, 3.8 micros or thereabouts added to that. So it's not 13 micros, it's 16.8 Why? Because well, let's assume that the delay microsc routine is fairly accurate.

Okay, it's not going to be absolutely, you know, spoton. but it's going to be near enough. What's taking all the time? Well, the only other code in here is this digital right routine. And this digital right routine does actually take timing.

In this case, it takes a couple of microsc to execute and there's faster ways to do it, but we're just using the digital WR routine. Uh, cuz that's the basic way in the Arduino So let's compensate tweak this thing I am holding my tongue at the right angle and let's take that's let's knock that you know three or four uh micros off. Let's change that to nine micros and let's upload that we've uploaded. We can go back in here.

We can start this again. We can run, run our Arduino is running. oops, it's already captured it because I've got an auto uh start routine in there and you'll notice that the timing is different. Look at this 12.75 micros now and we're close to our 38 khz.

We're now 39.4 khz and as I said, you don't have to be spot on, but that's going to be near enough. And as it turns out, this now works and sorry about the audio and video quality now, I'm at home actually. uh, doing this I don't have my main camera so I'm SHO shooting on my old compact. it's night and uh, well, yeah, it's not going to be very good anyway.

I have my Canon camcorder here I've got my free Tronics 11 down here. I've got an infrared lead hooked up and pointed to it via a 220 ohm dropper resistor and if I press the uh reset button here, it should start recording and then 5 seconds later should send the code again to switch it off. So let's give it a go. Bingo Started recording and it won't quite go to Five because it took a second or two to Boom.
But there you go. Works A treat and just a small trap for young players here. With any sampling system like this, the resolution is going to be dependent upon your sample rate. Now we're sampling at 8 MHz here and you'll notice that it's over on the right hand side.

There, It's saying the pulse width is giving us that to three decimal places or 1 nond resolution. Well, that's obviously complete. It's saying it's 12.87 micros. It's not possible to get uh one, 1 n a second resolution on that, but 8 MHz is more than good enough.

Um, to get the timing requirement for this particular application. But let's resample that at say, a lower rate of 500 khz. Now if you invert five, let's start that, capture it. And here we go.

And if you invert 500 khz, of course, you get uh two micros. You'll notice that there we go. it's jumping between 2 and 14 micros, but still showing two decimal places. Beyond that, that's the software not knowing what it's doing, and this might be tricking in you into thinking that that pulse width is precisely 14.00 micros.

When it's not, your resolution isn't good enough to determine that. In this case, this really isn't quite good enough for this particular system. It's almost in the ball ballpark, but not quite Anyway, Just be aware of that trap for young players, so that's it. Very, very simple to write your own code.

Reverse Engineero protocol. You don't even need an oscilloscope. You can do it using very simple and basic tools a PC or whatever. So no complex test equipment required here to reverse engineer that NEC protocol and you know not much work at all.

Very, very simple. So I hope you enjoyed that There were lots of stuff involved in this Cillos Scopes reverse engineering and then uh, we had a little fail there in our source code and tweaking some logic analyzer stuff. It's all happening. Fantastic! So if you like the video, please give it a big thumbs up.

And as always, if you want to discuss it, jump on over to the EU blog forum and no correspondence will be entered into on the source code. Thank you very much. Catch you next time.

Avatar photo

By YTB

24 thoughts on “Eevblog #506 – ir remote control arduino protocol tutorial”
  1. Avataaar/Circle Created with python_avatars Claudiu Panoiu says:

    Thank you for this video, it was explained very easily and simply. 🤝

  2. Avataaar/Circle Created with python_avatars Kim-André Johansen says:

    I've been trying to control my AC for a week now, exhausted, and still can't figure it out. But I know I'm close! I will try your code now, but I'm not sure where you got your IRcode from. Did you convert Adress or Command to binary or what? Would appreciate your quick input mate, thanks alot.

  3. Avataaar/Circle Created with python_avatars John Burgess says:

    Very nice, thank you.

  4. Avataaar/Circle Created with python_avatars Jbrimbelibap says:

    I found a way to do all of this using only my phone and a dongle i made myself
    And ir sensor transmitting it's raw signal as microhpoen input through the headphone jack, and an osciloscope application

  5. Avataaar/Circle Created with python_avatars Ben Wolfe says:

    Thanks for this video Dave! Your code is much more elegant and easier to understand than any of the IR libraries online. I was able to modify it to duplicate a Sony AV remote and it worked!

  6. Avataaar/Circle Created with python_avatars Love made in Japan says:

    Thanks, the missing puzzle. Thought the receiver was a dumb photodiode, but it must do some 38kHz filtering. You would expect there is a 5V input transmitter that does the 38kHz thing as well, so you can send the yellow simple signal, and have the 38kHz magic applied on your digital output. Does anybody know if that exists?
    Try to program without delays though. Run either a 38kHz loop frequency, or use a hardware timer with an interrupt routine.

  7. Avataaar/Circle Created with python_avatars PoorMan says:

    Calibrate you’re probes

  8. Avataaar/Circle Created with python_avatars Rajh Uddin says:

    Excellent explanation, thanks for showing how things actually work by theory using the oscilloscope.

  9. Avataaar/Circle Created with python_avatars Milan Djuricic says:

    Guys, anyone has any idea how could I amplify (current only) of pulses coming to the IR led and use higher power led instead. Let's say 2-3 amps instead of 20-30 mA. Any ideas for transistor circuit?

  10. Avataaar/Circle Created with python_avatars Osvaldimar dos Santos says:

    Amigou! Amigou ! President W. BUSH JÁ AVISOU QUE ATRÁS DELE É O JAPÃO BLZ TECNOLOGIA DE PROGRAMAÇÃO BINÁRIA, CODIGO MORSE, BITS E BITS BLZ?

  11. Avataaar/Circle Created with python_avatars Bart van Gorp says:

    Thanks Dave!
    i used your code to make a AC ON/OFF control for the Dometic HB2500 Airco. As far as i known no replacement remote controls are available for this Dometic HB2500 so i am making my own to help out a neighbour. He was told to buy a new Airco for his RV when his remote control broke down.
    Greetings from the low lands 🙂

  12. Avataaar/Circle Created with python_avatars Del bandung says:

    i have dificulty apply this methode to stm32f103c8t6 blue pill,

  13. Avataaar/Circle Created with python_avatars Tonguç Endem says:

    diodee 🙂

  14. Avataaar/Circle Created with python_avatars Kevin Johansson says:

    Amazing video with some nice tips here and there. Great stuff.

  15. Avataaar/Circle Created with python_avatars grzesiek1x says:

    but without Arduino it would be quite difficult to make it…

  16. Avataaar/Circle Created with python_avatars juanmele says:

    Great video, just what I needed to understand how IR remote controls work 🙂

  17. Avataaar/Circle Created with python_avatars Stephen Arsenault says:

    David – it’s an older video but I found it really useful! I’ve been recording a custom protocol used on original Macintosh keyboards (pre ADB) and plan to do an Arduino implementation. Your segment about using the Arduino and pitfalls to be mindful of confirmed the best practices I was anticipating – thank you!

  18. Avataaar/Circle Created with python_avatars Tomos Halsey says:

    Every single Arduino project doing exactly this makes a point of stating how over complex the IR libraries are. It might be time for a re-write.

  19. Avataaar/Circle Created with python_avatars Alexander Martinsson says:

    Try this(for Leonardo so the pins may differ on Uno):

    PORTC |= (1 << 7); //13 on
    PORTC &= ~(1 << 7); // 13 off

  20. Avataaar/Circle Created with python_avatars JandroVerse Shorts says:

    Always great videos…ive watched you even before i started engineering and you're the real deal!

  21. Avataaar/Circle Created with python_avatars Gabriel St. Angel says:

    What if I wanted to completely bypass the LED and directly manipulate the receiver pins on the input device? Would I still need to worry about carrier frequency if I had literal wires connecting the Arduino to the IR receiver contacts?

  22. Avataaar/Circle Created with python_avatars Joe Porsche says:

    Wow!!!. This video is really helpful.

  23. Avataaar/Circle Created with python_avatars Me 2016jack says:

    Sir Could you please Decode an SHARP A/C (Air conditioning)Remote ???

  24. Avataaar/Circle Created with python_avatars Sumit Wankhede says:

    I want to make a remote controller on Arduino (IRrecv+IRsend+sleep). In which it should read IR data usingtsop1738 then send the desired IR data using IR transmit led. And when no data is received it should go to deep sleep to conserve battery. Because I want it to run on 3v lithium coin cell. I found many codes on the internet using Irsend + sleep or just IRsend + IRrecv. But not a combination of all the three. If you make the code for the same it will be helpful. Need for this project=== some channel nos on my tv are 4 digits. It is very difficult to press 4 keys. So my plan is to press only 1 key tv remote and my controller will send desired 4 distinct key codes to tv by sending cancel command to my 1st command press by me on my tv remote

Leave a Reply

Your email address will not be published. Required fields are marked *