Time Functions

Lesson 16 - Using delayMicroseconds() for Precise Delays

Learn microsecond-level timing for short pulses and precise signal control in Arduino and ESP32 sketches.

Progress indicator

Lesson 16 of 16

Learning Objectives

  • Understand what delayMicroseconds() does in Arduino timing.
  • Use delayMicroseconds() syntax correctly.
  • Compare microseconds and milliseconds clearly.
  • Recognize blocking behavior at microsecond scale.
  • Understand timing accuracy limits in real hardware.
  • Know when to use delayMicroseconds() and when to choose other timing methods.

Concept Explanation

What is delayMicroseconds()

delayMicroseconds() pauses code execution for a very short duration measured in microseconds (us).

It is used when millisecond-level delays are too large and you need short pulse timing.

This is common in low-level signal tasks where timing windows are very small.

delayMicroseconds() Syntax

delayMicroseconds(microseconds);

Example: delayMicroseconds(10); means wait about 10 us.

Use integer values and keep units clear in comments.

How Microsecond Delay Works

The processor waits for the specified microsecond interval before the next line executes.

In pulse generation, this determines how long a pin stays HIGH or LOW.

Because it is blocking, your program is effectively paused during this delay.

Microseconds vs Milliseconds

1000 us = 1 ms

1,000,000 us = 1 second

Microseconds are 1000 times smaller than milliseconds.

Blocking Behavior of delayMicroseconds()

Like delay(), it blocks execution. While waiting, no other line in your loop can run.

This matters when your sketch also reads buttons, sensors, or communication data.

When to Use delayMicroseconds()

  • Creating short digital pulses
  • Basic timing experiments with protocols
  • Signal testing where sub-millisecond control is needed
  • Beginner lab exercises focused on pulse width

Timing Accuracy Considerations

Real timing is close but not always exact. It can vary with CPU speed, compiler optimization, interrupts, and other code activity.

For most beginner exercises, this is acceptable. For strict timing requirements, hardware timers or dedicated peripherals are better.

Real-Life Example

Triggering an ultrasonic sensor often needs a short trigger pulse in microseconds. delayMicroseconds() is commonly used for this beginner-to-intermediate use case.

Example Code

This example creates a short HIGH pulse on a digital pin.

const int pulsePin = 2;

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

void loop() {
  digitalWrite(pulsePin, HIGH);
  delayMicroseconds(10);
  digitalWrite(pulsePin, LOW);

  delay(1); // small gap before next pulse
}

What this example teaches

  • How to produce a pulse using HIGH + microsecond wait + LOW
  • How microsecond and millisecond waits can be mixed in one loop
  • How pulse width and pulse gap affect signal repetition

Example Code Explanation

  1. pulsePin stores the output pin number.
  2. pinMode(pulsePin, OUTPUT) prepares the pin for output.
  3. digitalWrite(pulsePin, HIGH) starts the pulse.
  4. delayMicroseconds(10) keeps the pulse HIGH for about 10 us.
  5. digitalWrite(pulsePin, LOW) ends the pulse.
  6. delay(1) adds a small gap before the next pulse cycle.

Beginner reading tip

Think in two parts: pulse width (delayMicroseconds) and pulse gap (delay). Together they define repetition behavior.

Limitations of delayMicroseconds()

  • It is blocking and can pause other logic.
  • Not suitable for long waits.
  • Timing precision can vary by platform and runtime conditions.
  • Complex multitasking designs usually need timer-based approaches.

Common Mistakes with delayMicroseconds()

  • Mixing up us and ms units.
  • Using delayMicroseconds() for logic that should use timers.
  • Assuming perfect pulse timing without measuring the signal.
  • Using very large microsecond values instead of clear millisecond delays.

Best Practices for delayMicroseconds()

  • Use it only where short delays are truly needed.
  • Document timing units clearly in comments.
  • Keep pulse-generation logic simple and test incrementally.
  • Use hardware timers when precise non-blocking timing is required.

Practice Task

  1. Change pulse width from 10 us to 20 us and describe the difference.
  2. Change pulse gap from 1 ms to 2 ms and explain total cycle timing.
  3. Write the total loop cycle time in both microseconds and milliseconds.
  4. Explain one case where millis() or a timer is better than microsecond blocking delay.

Try it now

Open the simulator to practice pulse timing concepts.

Run in Simulator