Learn

Arduino delayMicroseconds(): short waits, measured

Beginner

Or see every lesson.

  • 455parts on the bench
  • 43boards running now
  • 1.00xreal time, on every board
Arduino Uno: a servo driven by pulses timed in microsecondslive0.000 s 0.00x
Click to open it in the editor
The slider sets the angle; every pulse to the servo is timed with delayMicroseconds().

delayMicroseconds(us) waits for that many millionths of a second, then carries on. Use it for the short, exact waits that delay() is too coarse for: the 10 µs trigger pulse of an ultrasonic sensor, a servo’s 1 to 2 ms pulse, the step pulses of a stepper driver. For anything over about 16 milliseconds, use delay() instead: on an Uno, delayMicroseconds() cannot count that high.

The circuit above is the servo fader. Press Run and drag the slider. The servo follows, and the serial monitor prints each angle, such as "fader 1000 -> 175 degrees". The servo code underneath makes every pulse with delayMicroseconds(): 544 µs for 0 degrees, 2400 µs for 180, fifty times a second.

Below is how long it really waits, the limit and what happens past it, a servo pulse made by hand, and the mistakes people make with it, each run on an Uno with micros() timing it.

delay() or delayMicroseconds()

delay() counts in milliseconds and delayMicroseconds() in microseconds, a thousand times smaller. delay(1) and delayMicroseconds(1000) are both a millisecond: timed with micros(), they both took 1020 µs. Both stop the sketch while they wait, so neither is a way to do two things at once. That is a job for millis().

micros() itself counts in steps of 4 µs on a 16 MHz Uno, so every time below is a multiple of 4. That is also the finest step you can measure with it: to time something shorter, run it a thousand times and divide, as the short waits below do.

How long it really waits

This sketch times seven waits with micros(). It printed "10 us took 16", "100 us took 104", "1000 us took 1016" and "10000 us took 10140". The extra few microseconds are the call itself and micros(). The longer waits come out 1 to 2 percent long because the timer interrupt that keeps millis() going runs every 1024 µs and the wait does not stop for it.

Then the limit. "16383 us took 16608", and 16384 took 16612. 20000 took 3668. That is not a typo: delayMicroseconds() on an Uno counts in a 16-bit number of quarter microseconds, so anything past 16383 wraps around. 20000 is 3616 past the limit, so it waited about 3.6 ms.

Time seven waits
void setup() {
  Serial.begin(9600);
  unsigned int waits[] = {10, 100, 1000, 10000, 16383, 16384, 20000};
  for (int i = 0; i < 7; i++) {
    unsigned long start = micros();
    delayMicroseconds(waits[i]);
    unsigned long took = micros() - start;
    Serial.print(waits[i]);
    Serial.print(" us took ");
    Serial.println(took);
  }
}

void loop() {
}

Very short waits

Under about 3 µs the call itself takes longer than the wait. This sketch runs each value a thousand times. 0 took 1376 µs in total, 1 took 1380 and 2 took 1388, then 3 took 3408, 4 took 4432 and 5 took 5444. So 1 and 2 wait no longer than 0 (the few microseconds between the three are where the timer interrupt landed), and from 3 up each call is the value plus about 0.4 µs.

Mokxi’s Uno core returns at once for 0, 1 and 2, because the call alone already takes about that long; the Arduino core does the same for 0 and 1. If you need a pulse shorter than a few microseconds, write the port register directly rather than calling digitalWrite() and delayMicroseconds().

A thousand short waits
void setup() {
  Serial.begin(9600);
  for (int us = 0; us <= 5; us++) {
    unsigned long start = micros();
    for (int i = 0; i < 1000; i++) {
      delayMicroseconds(us);
    }
    Serial.print(us);
    Serial.print(": ");
    Serial.println(micros() - start);
  }
}

void loop() {
}

A servo pulse by hand

A servo reads the width of a pulse, sent about 50 times a second: about 544 µs for 0 degrees and 2400 µs for 180. This sketch makes the pulse itself, with no library. With 1500 the servo went to 94.0 degrees. With 1000 it went to 45.5 and with 2400 to 180.

1472 µs is the exact middle, and that put the servo at 91.3 degrees, not 90. The extra degree comes from digitalWrite(): each call takes a few microseconds, so the pulse comes out about 12 µs wider than the number you wrote. The Servo library allows for that, which is one reason to use it.

A servo pulse with no library
const int SERVO = 9;

void setup() {
  pinMode(SERVO, OUTPUT);
}

void loop() {
  digitalWrite(SERVO, HIGH);
  delayMicroseconds(1500);  // the pulse: 1.5 ms is about the middle
  digitalWrite(SERVO, LOW);
  delay(20);                // the gap: about 50 pulses a second
}

A square wave, and why it comes out slow

Two waits of 50 µs should make a 10 kHz square wave. A frequency counter on pin 9 read 8732 Hz. The same sketch with 500 µs waits read 980 Hz instead of 1000. The gap is the same few microseconds of digitalWrite() and loop() on every half wave, which matters more the shorter the wait.

For a steady frequency, let the hardware do it: tone() for sound and analogWrite() for PWM run on a timer and do not drift with your code.

A square wave on pin 9
const int OUT = 9;

void setup() {
  pinMode(OUT, OUTPUT);
}

void loop() {
  digitalWrite(OUT, HIGH);
  delayMicroseconds(50);
  digitalWrite(OUT, LOW);
  delayMicroseconds(50);
}

Common mistakes

Passing more than 16383. delayMicroseconds(20000) waited 3668 µs here. For the 20 ms gap between servo pulses, use delay(20); with delayMicroseconds(20000) the servo sketch above sent 194 pulses a second instead of 46.

Using it to time long things. A loop of a thousand delayMicroseconds(10) calls took 10388 µs, not 10000. The errors add up; use micros() to check the time instead of adding waits.

Expecting 1 µs to be 1 µs. The call itself is longer than that.

Using it to do two things at once. Like delay(), it blocks. Use millis() or micros() and check the time instead.

Questions

What is the maximum value for delayMicroseconds?

16383 on a 16 MHz Uno. Larger values wrap around: delayMicroseconds(20000) waited about 3.6 ms here. Use delay() for anything longer than about 16 ms.

What is the difference between delay and delayMicroseconds?

delay() waits in milliseconds and delayMicroseconds() in microseconds, a thousand times shorter. delay(1) and delayMicroseconds(1000) both wait about a millisecond. Both block the sketch while they wait.

How accurate is delayMicroseconds?

Within a few microseconds for short waits: 100 took 104 µs here. Longer waits run 1 to 2 percent long because the millis() timer interrupt keeps running, and waits of 1 and 2 µs take no longer than 0.

Does delayMicroseconds block other code?

Yes. Nothing else in loop() runs until it returns, the same as delay(). Interrupts still run, which is why long waits come out a little long.

Sources

Where the facts on this page come from

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.