The Problem with delay()
delay() blocks your entire program. While delaying, the Arduino can't:
- Read buttons
- Check sensors
- Update displays
- Do anything else
The millis() Solution
millis() returns the number of milliseconds since the Arduino started. Use it to track elapsed time without blocking.
The Pattern
unsigned long previousMillis = 0;
const long interval = 1000; // 1 second
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Do your timed action here
}
// Other code runs freely here!
}
Why unsigned long?
millis() returns an unsigned long which overflows after ~49 days. The subtraction pattern (currentMillis - previousMillis) handles overflow correctly. Don't use (currentMillis >= previousMillis + interval).
Multiple Timers
You can have as many independent timers as you want:
unsigned long ledTimer = 0;
unsigned long sensorTimer = 0;
void loop() {
unsigned long now = millis();
if (now - ledTimer >= 500) {
ledTimer = now;
toggleLED();
}
if (now - sensorTimer >= 100) {
sensorTimer = now;
readSensors();
}
}