What if your program could keep running smoothly while handling many timed tasks at once?
Why Multiple timed events with millis() in Arduino? - Purpose & Use Cases
Start learning this pattern below
Jump into concepts and practice - no test required
Imagine you want to turn on a light for 2 seconds, then after 5 seconds, turn on a buzzer for 1 second, and keep doing this repeatedly. You try to do this by writing code that waits and pauses for each event one after another.
Using simple delay commands to wait for each event means your whole program stops and does nothing else during those pauses. This makes it impossible to handle multiple events at the same time or respond quickly to other inputs. It's like waiting in line for your turn and missing everything else happening around you.
Using millis() lets you check how much time has passed without stopping your program. You can track multiple timers independently and trigger events exactly when their time comes, all while your program keeps running smoothly. This way, you can handle many timed events at once without freezing anything.
delay(2000); // wait 2 seconds turnOnLight(); delay(5000); // wait 5 seconds turnOnBuzzer();
if (millis() - lastLightTime >= 2000) { turnOnLight(); lastLightTime = millis(); } if (millis() - lastBuzzerTime >= 5000) { turnOnBuzzer(); lastBuzzerTime = millis(); }
You can create responsive programs that handle many timed actions at once without stopping or missing anything.
Think of a traffic light system where red, yellow, and green lights change at different times, and a pedestrian button can be pressed anytime to change the sequence. Using millis() lets the system keep track of all lights and button presses smoothly.
Using delay() pauses your whole program and blocks other actions.
millis() lets you track time without stopping your program.
This allows multiple timed events to run independently and smoothly.
Practice
millis() for timing multiple events in Arduino instead of delay()?Solution
Step 1: Understand
delay()behaviordelay()pauses the whole program, stopping all other actions.Step 2: Understand
millis()advantagemillis()returns elapsed time without stopping the program, so other tasks can run simultaneously.Final Answer:
It allows the program to run other tasks while waiting. -> Option DQuick Check:
millis()enables multitasking [OK]
delay() stops, millis() doesn't [OK]- Thinking
millis()pauses the program - Confusing
delay()with non-blocking timing - Believing
millis()resets Arduino
millis()?Solution
Step 1: Identify the correct data type for time
Sincemillis()returns an unsigned long value, the variable must be unsigned long.Step 2: Check variable initialization
Initializing to 0 is correct to mark the start time.Final Answer:
unsigned long lastEventTime = 0; -> Option AQuick Check:
Use unsigned long formillis()times [OK]
millis() [OK]- Using int which can overflow quickly
- Using float which is not precise for time
- Using char which is for characters, not numbers
millis() returns 5000 at the moment of checking?unsigned long previousMillis = 3000;
unsigned long interval = 1500;
if (millis() - previousMillis >= interval) {
Serial.println("Event triggered");
} else {
Serial.println("Waiting");
}Solution
Step 1: Calculate elapsed time
Elapsed time = 5000 (current millis) - 3000 (previousMillis) = 2000 ms.Step 2: Compare elapsed time with interval
Interval is 1500 ms. Since 2000 >= 1500, the condition is true, so "Event triggered" should print.Final Answer:
Event triggered -> Option CQuick Check:
Elapsed time 2000 >= 1500 triggers event [OK]
- Mixing up >= and > operators
- Forgetting to subtract previousMillis
- Assuming output without calculation
millis():unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval1 = 1000;
const long interval2 = 2000;
void loop() {
if (millis() - previousMillis1 >= interval1) {
digitalWrite(LED1, !digitalRead(LED1));
previousMillis1 = millis();
}
if (millis() - previousMillis1 >= interval2) {
digitalWrite(LED2, !digitalRead(LED2));
previousMillis2 = millis();
}
}Solution
Step 1: Check timing variables in conditions
The second if condition incorrectly usespreviousMillis1instead ofpreviousMillis2, causing wrong timing for LED2.Step 2: Understand impact of error
This mistake means LED2 timing depends on LED1 timing, so LED2 won't blink at its own interval.Final Answer:
Second if condition uses previousMillis1 instead of previousMillis2. -> Option BQuick Check:
Each event needs its own previousMillis variable [OK]
- Reusing the same previousMillis variable for multiple events
- Not updating previousMillis after event
- Confusing interval variables
delay(). Which approach correctly manages all three timed events using millis()?Solution
Step 1: Understand independent timing needs
Each LED needs its own timer to blink independently at different intervals.Step 2: Evaluate options
Use three separatepreviousMillisvariables and check each with its own interval insideloop(), allowing independent timing without blocking.Final Answer:
Use three separatepreviousMillisvariables and check each with its own interval insideloop(). -> Option AQuick Check:
Separate timers for each event [OK]
- Using one timer for all events causing sync issues
- Using delay which blocks other events
- Trying to calculate toggles from one millis() value without state
