The Arduino core uses hardware Timer0 with its ISR (Interrupt Service Routine) for timekeeping. While delayMicroseconds() directly uses the value of the hardware timer, delay() and millis() are handled by the ISR. It will be called regularly.

If the ISR is getting executed during your measurement, then the execution time of the ISR will add to the execution time of your measured code. Thus you get a higher count occasionally.

To prevent this you can either deactivate all interrupts (via noInterrupts()) or deactivate this specific interrupt, either by stopping Timer0:

TCCR0B &= ~( (1 << CS02) | (1 << CS01) | (1 << CS00) );

or by letting the timer run, but deactivating its interrupts:

TIMSK0 = 0;

For details about this have a look at the datasheet of the Atmega328p, which is the microcontroller on the Arduino Uno.

Answer from chrisl on Stack Exchange
🌐
Arduino
docs.arduino.cc › language-reference › en › functions › time › delayMicroseconds
delayMicroseconds() | Arduino Documentation
June 5, 2025 - delayMicroseconds will perform precisely for smaller delay times. Larger delay times may result in a very brief delay. delay() micros() millis() The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.
🌐
Arduino Forum
forum.arduino.cc › projects › general guidance
Delay vs DelayMicroseconds - General Guidance - Arduino Forum
October 10, 2018 - Hi all, I'm quite new at this so sorry if I am asking silly questions. I am trying to create a pulse simulator for a microcontroller. The simulator uses 2 parallel pulses (A and B), when A is on B is off and viceversa. I Set/Clear them at regular intervals using the delay command and when I connect them to the microcontroller I read a frequency (Hz).
Discussions

Repeating delayMicroseconds(max_value) to get a longer delay?
Yes that's fine for what you're doing. More on reddit.com
🌐 r/arduino
19
3
March 7, 2017
arduino mega - Can I make delayMicroseconds more accurate? - Arduino Stack Exchange
I'm trying to bit bang DMX data and that requires 4us pulses. Not having much luck with the results I'm checking to see how good the Arduino is at delaying... Seems to be pretty terrible at it. He... More on arduino.stackexchange.com
🌐 arduino.stackexchange.com
April 22, 2017
EEVblog Captcha
EEVblog Captcha · We have seen a lot of robot like traffic coming from your IP range, please confirm you're not a robot · This security check has been powered by · CrowdSec More on eevblog.com
🌐 eevblog.com
May 27, 2017
Delay microseconds wit Atmega328P barebones working at 1MHz 1.8V
Hi, guys. Rencently, I want to use Atmega328p barebones @1MHz powered by 1.8V to control MOSFET for switching function. When a interrupt signal comes, a digital pin of 328p outputs a high voltage for about 40us. I have tried the function delayMicrosecond(), but the result measured through ... More on forum.arduino.cc
🌐 forum.arduino.cc
0
0
February 26, 2020
People also ask

Can I pass a variable to delayMicroseconds()?
Yes. The parameter is an unsigned integer, so you can pass a variable: delayMicroseconds(pulseWidth). Make sure the variable is unsigned int or a value that fits within the valid range.
🌐
controllerstech.com
controllerstech.com › home › arduino › core tutorials › delaymicroseconds() tutorial
Arduino delayMicroseconds() Tutorial: Precise Timing, Pulses & ...
What is the difference between delay() and delayMicroseconds()?
delay() takes milliseconds. delayMicroseconds() takes microseconds. 1 ms = 1,000 µs. Use delayMicroseconds() when you need pauses shorter than 1 ms.
🌐
controllerstech.com
controllerstech.com › home › arduino › core tutorials › delaymicroseconds() tutorial
Arduino delayMicroseconds() Tutorial: Precise Timing, Pulses & ...
Why does delayMicroseconds(1) not actually delay 1 µs?
At 1–2 µs, the function's own setup overhead is larger than the requested delay. The minimum reliable delay is around 3 µs. Use direct port manipulation and NOP instructions for sub-3-µs timing if needed.
🌐
controllerstech.com
controllerstech.com › home › arduino › core tutorials › delaymicroseconds() tutorial
Arduino delayMicroseconds() Tutorial: Precise Timing, Pulses & ...
🌐
ControllersTech®
controllerstech.com › home › arduino › core tutorials › delaymicroseconds() tutorial
Arduino delayMicroseconds() Tutorial: Precise Timing, Pulses & Alternatives
May 29, 2026 - On a 16 MHz Arduino (UNO, Nano, Mega), one clock cycle is 62.5 nanoseconds. A 10 µs delay requires 160 clock cycles. The function calculates this count based on the board’s clock frequency and loops exactly that many times.
🌐
Reddit
reddit.com › r/arduino › repeating delaymicroseconds(max_value) to get a longer delay?
r/arduino on Reddit: Repeating delayMicroseconds(max_value) to get a longer delay?
March 7, 2017 -

Hello!

Noob to Arduino and C here.

I'm working with a stepper motor to control the Right Ascension axis on my telescope.

I've found that between two steps, I need a delay of 25.882 milliseconds. Now, delay() only takes integers, but I need a higher resolution. Looking at delayMicroseconds(), it states that for this delay, a maximum of 16383 microseconds is possible for accurate timing. Obviously, I need 25882 microseconds, which is above that limit.

What I'm wondering, is: Can I do two consecutive delayMicroseconds() with half my target delay? This means that I'll do

delayMicroseconds(target_half) // target_half = 12941 < 16383
delayMicroseconds(target_half)

Here's a code exerpt:

float millisbetweenSteps = 25.882; // milliseconds - calculated - lower is faster
int microsbetweenSteps = millisbetweenSteps * 1000; // microseconds

...

void runStepper(boolean run) {
  if (run == true) {
    digitalWrite(enablePin, HIGH);
    digitalWrite(directionPin, LOW);

    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pulseWidthMicros); // needed?
    digitalWrite(stepPin, LOW);

    delayMicroseconds(microsbetweenSteps/2); //Because delayMicroseconds max value is 16383micros
    digitalWrite(ledPin, !digitalRead(ledPin));
    delayMicroseconds(microsbetweenSteps/2); 
  }
}  


void loop() {
  runStepper(true);  
}

Looking at the stepper, it looks as if I'm getting the desired result, but I'm not sure.

Cheers!

Find elsewhere
🌐
Stanford CCRMA
ccrma.stanford.edu › ~fgeorg › 250a › lab2 › arduino-0019 › reference › DelayMicroseconds.html
Arduino - DelayMicroseconds
This could change in future Arduino releases. For delays longer than a few thousand microseconds, you should use delay() instead. ... int outPin = 8; // digital pin 8 void setup() { pinMode(outPin, OUTPUT); // sets the digital pin as output } void loop() { digitalWrite(outPin, HIGH); // sets ...
Top answer
1 of 5
9

As explained in the previous answers, your actual problem is not the accuracy of delayMicroseconds(), but rather the resolution of micros().

However, to answer your actual question, there is a more accurate alternative to delayMicroseconds(): the function _delay_us() from the AVR-libc is cycle-accurate and, for example

_delay_us(1.125);

does exactly what it says. The main caveat is that the argument has to be a compile-time constant. You have to #include <util/delay.h> in order to have access to this function.

Note also that you have to block the interrupts if you want any kind of accurate delay.

Edit: As an example, if I were to generate a 4 µs pulse on PD2 (pin 19 on the Mega), I would proceed as follows. First, notice that the following code

noInterrupts();
PORTD |= _BV(PD2);   // PD2 HIGH
PORTD &= ~_BV(PD2);  // PD2 LOW
interrupts();

makes a 0.125 µs long pulse (2 CPU cycles), because that's the time it takes to execute the instruction that sets the port LOW. Then, just add the missing time in a delay:

noInterrupts();
PORTD |= _BV(PD2);   // PD2 HIGH
_delay_us(3.875);
PORTD &= ~_BV(PD2);  // PD2 LOW
interrupts();

and you have a cycle-accurate pulse width. It is worth noting that this cannot be achieved with digitalWrite(), as a call to this function takes about 5 µs.

2 of 5
4

Your test results are misleading. delayMicroseconds() actually delays fairly precisely (for delays of more than 2 or 3 microseconds). You can examine its source code in file /usr/share/arduino/hardware/arduino/cores/arduino/wiring.c (on a Linux system; or on some similar path on other systems).

However, the resolution of micros() is four microseconds. (See, eg, the garretlab page about micros().) Hence, you will never see a reading between 4 microseconds and 8 microseconds. The actual delay might be just a few cycles over 4 microseconds, but your code will report it as 8.

Try doing 10 or 20 delayMicroseconds(4); calls in a row (by duplicating the code, not by using a loop) and then report the result of micros().

🌐
EEVblog
eevblog.com › forum › microcontrollers › arduino-mega-tone()-messing-up-with-delaymicroseconds()
EEVblog Captcha
May 27, 2017 - EEVblog Captcha · We have seen a lot of robot like traffic coming from your IP range, please confirm you're not a robot · This security check has been powered by · CrowdSec
🌐
DeepBlue
deepbluembedded.com › home › blog › arduino delaymicroseconds() function tutorial
Arduino delayMicroseconds() Function Tutorial
July 26, 2025 - And it can be acceptable as long as it’s a few µs time delay. ... The delayMicroseconds() function pauses the program for the amount of time (in microseconds) specified as a parameter.
🌐
Arduino Forum
forum.arduino.cc › projects › general guidance
Delay microseconds wit Atmega328P barebones working at 1MHz 1.8V - General Guidance - Arduino Forum
February 26, 2020 - Hi, guys. Rencently, I want to use Atmega328p barebones @1MHz powered by 1.8V to control MOSFET for switching function. When a interrupt signal comes, a digital pin of 328p outputs a high voltage for about 40us. I have tried the function delayMicrosecond(), but the result measured through ...
🌐
Arduino Forum
forum.arduino.cc › community › general discussion
Don't use millis() or micros(), or delay() or even ...
August 2, 2022 - If you are doing a continuous use project, don't use millis() or micros(), or delay() or even delayMicroseconds() in your project, because the variable will experience a count reset (overflow), instead, use some timer or operating system. Automatically handles micros() and millis() overflows / wrap around special cases.
🌐
Arduino Forum
forum.arduino.cc › projects › programming
Which timer used on mega for delay() and delaymicroseconds()? - Programming - Arduino Forum
November 24, 2016 - Hi guys. I am working a project which used timer 2 to trigger the Timer Compare Interrupt. And I change the prescaler to 1. Then I found out time delay function delays 6.4 times faster than normal. i.e delay(6400) equals to 1 sec delay time. So is timer 2 responsible for the delay() and delaymicroseconds() on mega?
🌐
Arduino Forum
forum.arduino.cc › projects › programming
Is the delayMicroseconds() function affected by the micros ...
August 1, 2022 - Hi, I found this issue, and I noticed that in this code the delayMicroseconds() function uses micros(). On an arduino UNO (ATmega328), can the delayMicroseconds() function suffer any effect every 70 minutes? void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us) { uint32_t m = micros(); uint64_t m = (uint64_t)esp_timer_get_time(); if(us){ uint32_t e = (m + us); uint64_t e = (m + us); if(m > e){ //overflow while(micros() > e){ while((u...
🌐
Arduino Forum
forum.arduino.cc › projects › programming
delayMicroseconds does not delay - Programming - Arduino Forum
May 1, 2018 - Hi everyone, I need to delay something sub-millisecond therefore I try to use delayMicroseconds but the led I'm using to check if everything is ok tells me it's wayyyyyyy too fast. (Both codes below have been slowed 10…
🌐
Junwoo Hwang
beginnerjunwoo.wordpress.com › 2018 › 01 › 29 › reality-of-delaymicroseconds
Reality of delayMicroseconds() – Junwoo Hwang
February 5, 2018 - At around April of 2017, I was digging into Library called ‘Arduino-DHT22’. I was keep getting ‘Sync Timeout’ ERROR. Which basically meant Communication wasn’t working properly. And through Digital Oscilloscope, I could confirm that Sensor was communicating with spot-on Timing. So it must be that the Software was buggy. I was looking through the library and found the function ‘delayMicroseconds(2)’. Which was basically what Library heavily depended on as a Unit ‘2-microseconds’. And when I modified the library to output during delay, I could actually see that only 1.6[us] or so was being delayed.
Top answer
1 of 2
2

This a very partial answer. I do not know your requirements, whether or not PWM can do the job, etc... I just wanted to point out that you can make a pulse exactly 8 µs long with this:

#include <util/delay.h>
#include <util/atomic.h>

// Pulse PD3 (digital 18 on Mega 2560)
// for exactly 8 us (128 clock cycles @ 16 MHz)
static void pulse() {
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        PORTD |= 1 << 3;
        _delay_us(8 - 0.125);
        PORTD &= ~(1 << 3);
    }
}

The _delay_us() function from avr-libc is actually cycle-accurate inline assembly. The 0.125 µs I subtracted is the time needed by the actual port writes: both the sbi and cbi instructions take two cycles (0.125 µs), but that delay should only be counted once. digitalWrite() should always be avoided in time-critical code.

The 242 µs delay between pulses would be harder to generate without PWM. A timer interrupt at 4 kHz seems like the simplest option, but it is not cycle-accurate.

Edit: here is the scope trace, showing a quite accurate timing:

2 of 2
1

Unless you want program PWM timer as suggested in comment then for short delays you need calculate how many instruction cycles are needed to make such a delay based on clock/crystal frequency and make that delay in inline assembler to have code under control. To manipulate digital output use writing data to PINx (which is equal to xoring PORTx).

To satisfy exact 250ms you need compensate errors because of rounding. Arduino's delay/tick functions do it. For the long delays you need a simple scheduler not to spend all the CPU time for pulse generating.

🌐
Arduino Forum
forum.arduino.cc › projects › programming
Is it worth replacing delayMicroseconds by non blocking code? - Programming - Arduino Forum
April 28, 2013 - Hello 🙂 I am trying to write non blocking code for reading from 2x DHT22 and 2x DS18B20 sensors, because every libraries I found for these sensors, use the delay() function which I hate... (especially the DS18B20's which use a delay of 750 ms...). So I replace the delay() calls with non ...
🌐
Arduino Forum
forum.arduino.cc › projects › programming
delayMicroseconds function provides unstable pulse durations - Programming - Arduino Forum
As a part of my project I need to generate 10 microseconds pulses with 10 milliseconds intervals. I was using a separate Arduino Micro and a simplest code with delayMicroseconds() and delay() functions. To get the 10us pulse width I needed to use 8us argument for delayMicroseconds function, but the actual problem is that randomly but pretty often (roughly 10% of the time) the pulse width jumps to 18us which is completely unacceptable for my project.
Published   January 22, 2020