I've been using the pulseIn() function for processing PWM-based binary data encoding. It works well for distinguishing pulses which are significantly different lengths, e.g. 500us vs. 1500us. That makes it more than sufficient for handling typical IR remotes.

However, I want to make my own IR system which can use more than 2 pulse lengths, so that data transfer can occur faster. Ideally, I'd like to use 8 different pulse lengths for octal encoding (e.g. 200us, 400us, 600us, etc.).

I've noticed quite significant variations in the values returned by pulseIn() though (+/- 10%). I expect at least some of it is introduced by the IR transmitter and receiver modules, but I don't have good enough equipment to verify that.

Assuming I can mitigate that external error, is pulseIn() likely to be precise enough to distinguish such similar pulses?

2 Answers 2


The pulsein() function is very lossy, in that it is a hard loop and returns a number * the assumed clock cycles it takes for per loop

// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask) {
  if (numloops++ == maxloops)
    return 0;

// convert the reading to microseconds. The loop has been determined
// to be 20 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
return clockCyclesToMicroseconds(width * 21 + 16); 

The most accurate method for capturing the timing of a PIN is use the INPUT CAPTURE FEATURE. Look at the this example . It enables the input capture at 1x of CPU for max resolution and each edge of the input pin captures the timer's clock value for reading from the generated Interrupt service. It also enables the timer overflow interrupt to as to maintain large absolute time, to be capture. Since the 1x will roll rather quickly. The captures store the time into an array for reading by the main loop.

Where for signals over IR the typical library to use is shirriff/Arduino-IRremote library. Where it has several demo's that will read and send the IR from a demodulated signal. To allow one to build a sketch of their own design. This code originally creates a timer interrupt that polls the input pin at a rate determine by

#define USECPERTICK 50  // microseconds per clock interrupt tick

in the IRremote.h file. For my purposes I have change it to 25 us. Where I find this still can be intermittently missing pulse streams.

Note the demodulation is best accomplished within the IR receiver, which in turn outputs this signal of interest. Where to add some background. Using the typical 38KHz modulation, equates to a minimum resolution of 26.3uS per pulse's cycle. sherriff's library shows typically most bauds or bits are in the order of 10+ pulses. Which appear to meet your desired timings.

microtherion/Arduino-IRremote fork of shirriff's work improves the reception by replacing the timer interrupt polling of the pin with the use of PinChangeInterrupts. Which I have merged into my own mpflaga/Arduino-IRremote fork, that adds several other features.

So you could use any of the above libraries. Or create your own app that uses either of the below to capture edges.

  1. polls on a Timer event (e.g. 50uS)
  2. captures the micros() on a PinChangeInterrupt
  3. uses Input Capture Interrupts to grab the exact time
  • 1
    Brilliant answer. The Arduino-IRremote is a very high quality library. Easily readable, and has a lot of well thought out design that means it is very reliable. Feb 21, 2014 at 8:35

Here is some test data of a pulseIn test. One Arduino sent what were supposed to be 14us pulses, and the other spat out this data:


As you can see, the pulses are by no means accurate. The time would be more accurate if the sending and recieving ends were written in assembly, or even offloaded to their own processors.

Your Answer

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

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