Tuesday, August 25, 2009

Sub-Microsecond Delays with Arduino

It's possible!

The Arduino delayMicroseconds() function creates the shortest delay possible from within the Arduino language. The shortest delay possible is about 2 us (microseconds). Not true - I've tried and the shortest is about 4.5 us.

For shorter delays use assembly language call 'nop' (no operation). Each 'nop' statement executes in one machine cycle (at 16 MHz) yielding a 62.5 ns (nanosecond) delay.

__asm__("nop\n\t");

__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t"); \\ gang them up like this

Really, why not a loop?

Dat's vy :

If you write a C loop, it will change into NOP instructions and compares/increments for counters. So your timing will be off. Unrolling loops is a standard practice to get rid of the compares/increments.


Verdict :

You also need to know stuff on this page :

http://arduino.cc/en/Reference/PortManipulation

If you use digitalWrite(), a single write takes 4.5 us to execute. But using

PORTB = PORTB & B11101111;
to set pin 12 low, with no intentional delay, I see a delay of about 400 ns. So much for being able to get 62.5 ns! If I put in 4 NOPs, I get the delay increasing to 620 ns. So we're on!

1 comment:

  1. You can use a loop but remember that branching and decrementing takes time itself. At a minimum you'll need to load a register with a count value, do the nop, decrement the counter, and branch on not zero. Each cycle through the loop is somewhat longer than a single NOP. You get a lower resolution of timing with it.

    If you think about it in such a piece of code you don't actually need the NOP since the decrement takes time itself. So a decrement/branch loop would be more accurate. But for very small delays multiple NOPs are more accurate still.

    ReplyDelete