What are the practical differences between using delay()
versus a while
loop with millis()
for timing in Arduino projects? I assumed both methods are blocking, but I'm not completely sure.
Example using a while
loop:
unsigned long start = millis();
while (millis() - start <= interval) {
DoSomething();
}
Example using delay()
:
StartSomething();
delay(interval);
StopSomething();
How do these methods compare in terms of blocking behavior, responsiveness, and potential trade-offs?
2 Answers 2
The first example executes DoSomething()
repeatedly until the interval expires.
The second example executes StartSomething()
, then does nothing until the interval expires, then executes StopSomething
once.
As written, they both block. But changing the while
in the first example to an if
, and including it in another loop, or in the loop()
function, will let you insert other, perhaps similar code above or below it, so that the outer loop will continuously test every condition of interest and take a specific action every time one of those conditions becomes true. It is the basis of non-blocking code, to never wait for anything, but to keep testing conditions and taking a specific action each time one of the conditions becomes TRUE.
Yes, both methods are blocking.
Using delay()
usually leads to writing less code, and the delay is
more accurate. Typically, it is only a few microseconds off. A busy loop
that calls millis()
will be one full millisecond off if start
is
initialized right before the millis()
counter gets incremented.
If you want non-blocking, you have to write something like this:
// Start something when appropriate.
if (!something_started && maybe_another_condition) {
StartSomething();
something_started = true;
time_stated = millis();
}
// Stop something when appropriate.
if (something_started && millis() - time_stated >= interval) {
StopSomething();
something_started = false;
}
if
instead ofwhile