This is something I'm struggling with for a while and fail to find solid solution. The Arduino IR library provides method for recording arbitrary IR code and re-sending it. This gave me different results every time I recorded the IR remote, so I wrote a little code, based on interrupts, that try to record the IR rise/fall as accurately as possible. I am working with ATTiny85 running at 8Mhz on internal oscillator.

Here is the code:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(4,3);

const int dataSize = 40;
int data[dataSize];
int dataLength[dataSize];

void setup() {
  pinMode(0, OUTPUT); // 0 is IR receiver pin
volatile unsigned long prev = micros();
volatile unsigned long curr = -1;
volatile unsigned short index = 0;
volatile bool rising = true;
void IR_ISR()
  if (!rising)
    dataLength[index] = micros() - curr;
    rising = !rising;

  curr = micros();

  data[index++] = (int)curr-prev;

  prev = curr; 
  rising = !rising;

void loop() {

  for (int i=1; i<dataSize; i++)
    mySerial.print("; ");
  index = 0;

Problem is that the milliseconds alter on each record of the remote control, here is an example of the output of 3 attempts of clicking at the same button of the remote control (I pasted only the first 5 IR modulations to avoid too much text, total is about 39):


14104(9496); 1184(672); 1184(616); 1160(656); 1176(672); ...

14096(9480); 1184(664); 1208(568); 1136(616); 1184(664); ...

14096(9384); 1216(576); 1136(616); 1184(664); 1208(560); ...

The format is: [microseconds from previous falling edge](microseconds from rise to fall);

As you can see, the results vary. According to the arduino.cc website, the micros() function has a 8 microseconds resolution on 8Mhz AVR's, but the difference between reads is bigger than that.

This is not reliable enough for me to solidly duplicate a remote control, and I'm looking for a resolution that will provide accurate results, as the magnitude of every deviation increases when the voltages are low (for example, with a 3v 2032 coin battery half discharged).

  • While the AVR is 8MHz, there is latency to service the ISR. Hence your observed differences.
    – mpflaga
    Commented Aug 6, 2014 at 14:53
  • This is true that ISR has some delay and does not provide real time values, but if what you say is correct, I should have measured the same deviation on every attempt, and this is not happening.
    – Omer
    Commented Aug 6, 2014 at 16:36

2 Answers 2


The exact duration of the pulses don't matter much. In your example, you see that in all three recorded samples that's

about 14000 (about 9400); about 1200 (about 600); about 1200 (about 600) etc.

What matters is that nowhere you have pulses of about 900 : in other words if the receiver detects a 672 pulse it will know that it's definitely a 600, not a 1200.

So if you send exactly those values, the receiver will recognize it.

  • That's an interesting observation; do you have a thumb rule about the rounding?
    – Omer
    Commented Aug 6, 2014 at 9:06
  • 1
    I use 412-712 for detect a zero, and 1187-2187 for detecting a one. 412-712 for the ir-burst between them. It looks like the remote is using the NEC protocol. I actually used excel to convert the raw data into a number, and to test if the boundaries were sufficient. I actually had to increase the boundaries a few times to catch the IR signal reliably. The values above are what I ended up with.
    – Gerben
    Commented Aug 6, 2014 at 14:46
  • I used NEC remote for the post, but my intention is to reliably adjust to any custom protocol. Hence I am not sure that NEC values will suite me. Also, my final goal is to make the entire processing dynamically on the AVR itself, making it a real adjustable remote control, thus excel is not an option here :) I'll try to play with the rounding using code, see if that helps (if it will do the trick, I'll accept your answer).
    – Omer
    Commented Aug 6, 2014 at 16:35
  • Just sample n times the same code, and record the averages of pulse lengths. If you reemit that, you'll be sure you sent the same code. The way that code is interpreted by the receiver (NEC, rc-6, whatever) is irrelevant.
    – Nicolas D
    Commented Aug 8, 2014 at 5:19
  • Eventually I decided not to use ATtiny85 since, even if using PROGMEM, it's just not up to the job of being a 'universal remote control', memory wise. But this is indeed the correct answer to my question.
    – Omer
    Commented Feb 14, 2015 at 18:41

I often see where people have problems with decoding IR signals from time to time, but very few say how they are attempting to do that? The first thing you really need to know is what is the carrier frequency? if you are using a TSOP IR DEMODULATOR, They come in several flavors and if you have the wrong one your results may not be all that rock solid. There are one or two ways to determine this. have a digital storage scope and a fast photo diode (photo transistors are slow) which does no demodulation, just gives you raw IR . Once you determine your carrier frequency, then purchase a IR demodulator TSOP that is closest to your carrier frequency, then your results will be more stable no doubt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.