Btw, just to be clear for folks, the 26ms that you divided by in your IRcarrier() function is THE PERIOD of the 38Khz. Freq = 1/Period, which means Period = 1/Freq = 1/38Khz = 0.0000263157 sec = 0.0263157msec = 26.3157usec, which is roughly 26usec. So, your code wanted 9000usec of 38Khz carrier freq means that "how many periods of 26usecs do I need to generate?", which means 9000usec/26usec = 346 periods, that is, 346 iterations of the loop in your IRcarrier() function. That's how the 38Khz carrier frequency is generated with an I/O pin.
Dave R Good idea indeed but there's a limitation. The standard audio cards are made to sample from around 20Hz to 20000 Hz. That's not enough to see the actual carrier frequency, but its totally good enough to decode each button code. I just made this a couple of days ago, and I was able to decode every single button :D. Btw I used a free software that plots the mic input and lets you visualize interesting stuff like frequency gains.
I just did this, as my receivers did not make a proper capture of the signal. using a standard sound card was able to clearly see the codes with a simple ir receiver (2 pin on mic input). my air conditioner had a 36-bit code, so I made a few modifications to the code posted here, adjusted the initial timings (assumed a 38khz carrier) and bam! working fine! captured the output to match the original remote, and from there I refined the timings. (i did not have an oscilloscope). an arduino pro mini 3.3v did the job perfectly
I have been experimenting a LOT with this crap. It's a real pain in the butt to get enough documentation to know what the heck to do. I have spent a lot of time accumulating documentation. I'm doing it with a PIC chip. Specifically a PIC16F1503. I'm so close I can taste it. I have a handheld Qunda IR Remote Control Decoder. It sees and decodes my PIC's IR output but the TV is not. More tweaking needed. One thing I noticed is that you assume is that the 38Khz duty cycle is 100%. ie., 50% ON, 50% OFF. It's not. 33% on time is more like it. Keeps LED's from burning up. They are usually pulsed at some insanely high currents. I could write a book. Argh. Thanks for the video!
mike94560 I’m also working on a project that deals with a PIC16F883 and IR , how far did you get !? Can I see your results and how you got to where you wanted
great work Dave. i'm an electrical engineer who has been out of the technical loop for 25 years. your videos are perfect for bringing somebody like me up to date.
As I pointed out to countless people, yes the previous hack was much simpler and faster, that's why I did it originally. But this isn't too hard, even if you have to write your own IR library as I showed, but yes, you need at least some programming knowledge. You can just cut'n'paste code though of course.
Yes, but then the code wouldn't be as portable, or usable on chips without available PWM, or as understandable to beginners. Bit bang is always a nice way to explain it first IMO.
So that people can just cut'n'paste setup routine into other code, it's more portable. setup is an Arduino specific thing. The while loop at the end stops it from running more than once. It's example code.
The other fix would be to replace Arduino's digitalWrite routine with one that optimizes down to the single machine instruction it should be. Considering the "digitalwritefast" implementation is entirely source compatible and has been around for years, I've no idea why the Arduino team hasn't already included it.
An Arduino sketch IS in native C. It's just calling an abstracted routine to write to the IO pin. You can simply bypass that if you want and the sketch will give you the exact same speed as AVR studio.
IR LED's draw as much current as you give them, they don't "take" or "draw" current. You force the required current into them with a suitable dropper resistor.
I recently made a remote control and IR receiver for dimming six leds individually. Used a timer to create the carrier signal and used the UART with a baud rate of 2400 to send the information, worked liked a charm :D Each transfer consisted of four bytes, the first and last byte are address bytes, I hardly get any bit error :)
What I enjoyed about this video is not the programming, although that is always instructive, but the reverse engineering of the raw pulses into a carrier freq., pulse codes, NEC standard... Big thumbs up video for newbie hackers and those who just want to understand how things work! Are there many major IR coding standards besides NEC?
Another very well known one is RC-5 (wikipedia.org/wiki/RC-5). It runs offically on a carrier of 36kHz, but a lot of manufacturers used 38 due to being misinformed or lazyness. It works anyhow. The bits are a fixed lenght where the direction (rising or falling) of the slope in the middle defines it's value. The toggle bit Dave talks about is used for ch+ and ch- for example. It prevents to skip 5 channels if you keep the button a bit to longue.
Excellent video. You even managed to review some code!! ;-) Great complete implementation of a smart solution to your specific need. But yeah I'm always a bit wondering as how fast these Arduino can actually deal with "real time" processing.
a) I would have used a PWM signal to generate at least the clock signal, so you don't have to tweak the timing. The 'professional way' would be to write the whole IR-signal generating code in the overflow interrupt of the PWM timer. But don't worry, for a demo your code is more than adequate. b) It could have used a little more cowbell.
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!
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
This is exactly how a fundamentals video should be done. Well played Dave, a great combination of theory, practical and how to salvage stuff from everyday consumer junk. I dont have enough thumbs to put up.
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
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.
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.
Wouldn't it be easier to just use PWM/Timer for the carrier freqency generation? Switching between 128 and 0 would toggle it. That has the advantages of not having program execution interfering with the generation and the frequency would be more accurate, and the power consumption would get much lower, as well.
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?
If you want to see some truly twisted IR encoding look at the MILES 2000 a.k.a. military laser tag. The older system used a relatively slow IR signal and when they decided to update things they still wanted to be able to use the old gear so they snuck in the new bits inside the existing bits. As I recall it was something like they split up the high time from one 'long' bit for the old system to many short bits for the new system. The old receivers would filter out the new fast bits and still work just fine and the new receivers would be able to 'see' the additional data. Since it did not add value to the project we were working on at the time to decode the actual MILES 2000 signals we skipped it (we were adding haptic feedback to the soldiers gear so they would feel where they were hit.)
The Arduino framework is so inefficient, hence the ~4us DigitalWrite functions that threw your code off. That's about 80 clock cycles to toggle a pin, compared to the couple cycles it should be!
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?
TLDR: Can anyone explain "if(code & 0x80000000)" ? I'm using Sony IRC protocol so It uses a 12- bit code, and it doesn't work. I've adjusted the timings and frequencies and such. I've experimented with different bit masks (which idek what bit masks do) and the one i found was best (but is still terrible) is 0x00000800. It only allows me to use 13 codes though (I should have 2^12, so... yeah). It basically turns binary 0001-0000-0000 to 0001-1111-1111, so the MSB is always follow by ones. How can i fix this?
The codes he is using are 32 bit, so 8 digits in hex. The statement checks if the msb is a one or a zero, he checks the msb, sends the code for a 1, or a 0, and then shifts the next bit beside it to the msb position and checks if this bit is a zero or a one. It's just an AND operation to mask out any other bit (AND with zero) and leave the required bit you want to check (AND with one). If the msb is a 0 then (code & ox80000000) is gonna be 0 (well, eight zeros) and the statement wont execute, the 'else' part will, on the other hand if the msb is one, the and operation will give a one at the msb position and then statement within the if will execute. In your case for a 12 bit code it would be, if(code & 0x800)
No, this is a misconception: While the Arduino "IDE" is written in Java, using the "processing" framework, the "sketches" and libraries that they use are written in pure C and C++. The Arduino platform is not only the harware but a combination of it together with the IDE and the Arduino library that hides many details of C and the Atmega hardware under an abstraction layer that allows non-software developers to experiment with MCUs.
First: what kind of libraries are you talking about? If you talk about using and writing Arduino libraries, the Arduino website (arduino.cc) has a tutorial for installing and also for writing libraries. If you talk about libraries in general, they are just a collection of functions/macros written for a certain purpose (e.g. a I²C library for communicating with I²C devices) , bundled together in one or more files.
I was just trying to capture the IR codes for some obscure DVD player (an ugly cyan/silver colored beast from RITECH). Just about no info online and you NEED the remote. I have the non-functional remote, but the stale-cheese looking resonator for the mystery COB's clock and IR carrier generation is dead. Did find it uses 36kHz carrier online... Maybe capture the data to the driving NPN's base (carrier freq is wrong, but should be able to scale it) then hand feed to LIRC for decoding. Hopefully!
The library _is_ slow. The reason is, that you can do analogWrite on a digital pin. It's setting up PWN on that pin. So if you do a digitalWrite, the library needs to check first, if PWM has been used before, reset the PWM timer, create the bitmask and so on. The Arduino library keeps everything incredibly simple: No need to read the Atmel datasheet, no need to understand the different ways to access standard and extended I/O ports. If you want to be fast, you need to roll your own...
I don't know how easy this is to do on the Arduino as I've never really used one, but I'd have used a hardware timer in up/down mode with the right capture/control register value for half the period, either implement PWM or use the hardware PWM depending on the chip. Then just enabled and disabled it, or flip the duty cycle between 0.5 and 0. Now code execution isn't a factor. Totally overkill for this project. :-D
Wait, what? Changing a pinstate on Arduino takes nearly 4 µs? What the hell are they spending all that time on? I mean, setting a bit on an IO-register or the entire register to a constant valuen on an AVR takes two clock cycles, which on an Arduino, running at 16 Mhz would translate to 0.125 µs. Seriously, what the fuck?
Really, it doesn't to be honest... I'm just tired of seeing countless unnecessarily used arduinos or raspberry pis for projects. "Want to blink an LED? Why not use an arduino!!". Because of their overuse, they annoy me a little bit. A plain AVR or PIC would have been nicer (and much less overhead so perhaps the subroutine delay would have been less/not noticable?)
@bcsupport Dave programmed his Arduino with a 'sketch' written in the "processing" language (roughly speaking a subset of Java which is compiled to byte code and then interpreted on the device) - it's not ANSI C. It's possible to program the Arduino with pure C but mostly not necessary.
yipee very good tutorial, but i would have like to learn about reverse engineering with simpler tools cause not every body has a ossiloscope or logic analyser yeah i know its like asking too much but its just opinion. I enjoyed like every time i do. thnks again
CC BY means you have to specify the "author" of whatever you're using with that has that license, which is pointless on this piece of code. Don't you think ? I would have prefered nothing to be honest. Next time I'll code a NEC protocol I'll add you as author. (just kidding)
I don't think that it's the compiler to blame here. Since avr-gcc, for example, compiles (with the usual size optimization enabled) "PORTB=0x55;" into "ldi r24, 0x55; out 0x18, r24;", which is the optimal form. So it seems to be the Arduino library having some absurdly slow IO-routines.
Wouldn't usage of Arduino SDK instead of AVR SDK make it already non-portable enough? Serious question as I've never used Arduino SDK so I don't know if the code can be compiled for AVRs other than used on Arduino boards. I've even used AVR SDK with Arduino board I've borrowed from a friend of mine.
Where is the Double LIKE / Double Thumb UP button ? :) I need to discover the code for a function of the remote and had not a clue how to do it. You saved me hours of head scratching. An now i know to emulate the command. Thank you !
The digital read and write functions on the Arduino are slow. They do a bunch of checking and eat up time. He could have used PORTD |= _BV(PD2); and PORTD &= ~_BC(PD2); to write pin 2 high and low much faster.
Dave thank you for this video, I just got my first oscilloscope and this made my day for another semi beginner! The protocol explanation was great it helps me put what I have learned about protocols into real world examples! Thanks again!
Though the length of '1' and '0' is not the same, the NEC protocol defines that you should send an inverted message as well, so the length of the whole transmission is constant., 67.5mS
for an arduino at that carrier frequency (>38khz), doing something so simple as toggling a pin i would opt for raw port manipulation, much fewer clock cycles than digitalWrite();
Bit banging is sometimes cheap and effective. In non-critical applications like consumer remotes, I'd say slamming signals out of a GPIO is perfectly acceptable.
Hi. Any way to hack a SEGA Saturn's light gun (which I believe uses an IR sensor) that only works with the usual 15hz refresh rate CRT tv to work with a 60hz PC CRT monitor? Could the sensor be overclocked or something using resistors or transistors? Thank you. God bless, Proverbs 31
If those "ppl" needed Dave's instruction here to do that, they probably won't be able to tell the hood from the trunk of a car. So don't worry, mate :)
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 :-)
Hey gemis94. I thought you are a great AVR guy. I'd like to ask you what the "if (code & 0x80000000) //get the current bit by masking all but the MSB" mean. David have made the comment. But I only understand It is a "bit mask 'and'", and the number begin with "0x" means "Hex" number, "MSB" stands for "Most significant bit". But the total meaning I still not get the idea. >__
yup... awesome is the word... one thing Dave, It seems quite obvious, but just so as to clarify my understanding: the signal (waveform) at the IR receiver output is exactly inverse of the signal that is fed into IR transmitter. Is that right?
Thanks a lot. I followed your declaration and did a small research. I do understand the Idea now. Thanks. If you want. I still have a small question: I know "code
By far one of the best explanations of IR signaling I've ever seen or read ... I definitely understand it 50% better than I did before watching the video ... but I am still uncertain how this knowledge can be applied to different protocols such as Sanyo, Sony etc. I'm going to power up the scope and see what I can figure out. Thank you for once again producing a quality electronic tutorial.
Dave you should have used DigitalWrite(IRLEDpin, 1) instead of using HIGH. It is considerably quicker than HIGH. That way you would not need to guesstimate the delay like you did. Give it a go and see if it helps... I suspect it would be much quicker.