millis() for non-blocking timing in Arduino - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When using millis() for timing in Arduino, it's important to see how the program's speed changes as it checks time repeatedly.
We want to know how the time spent grows when the program runs longer or checks more often.
Analyze the time complexity of the following code snippet.
unsigned long previousMillis = 0;
const long interval = 1000;
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Do something every interval
}
}
This code checks the time repeatedly and performs an action every set interval without stopping the program.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The loop() function runs continuously, checking millis() and comparing times.
- How many times: It runs as many times as the Arduino is powered on, effectively infinite.
Each loop cycle does a fixed amount of work regardless of how long the program runs.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 checks of millis() and if-condition |
| 100 | 100 checks of millis() and if-condition |
| 1000 | 1000 checks of millis() and if-condition |
Pattern observation: The number of operations grows linearly with the number of loop cycles, but each cycle's work stays the same.
Time Complexity: O(1)
This means each loop cycle takes the same small amount of time no matter how long the program runs.
[X] Wrong: "Using millis() makes the program slower as time passes because it checks time constantly."
[OK] Correct: The check is very fast and does not get slower over time; it always takes the same small step each loop.
Understanding how millis() works for timing without stopping the program shows you can write efficient, responsive code that handles tasks smoothly.
"What if we added a nested loop inside the if-condition that runs n times? How would the time complexity change?"
Practice
millis() function in Arduino return?Solution
Step 1: Understand what
millis()measuresmillis()returns the time in milliseconds since the Arduino started running the program.Step 2: Compare options with the definition
Only The number of milliseconds since the Arduino board started running the current program correctly describes this behavior; others mention seconds, microseconds, or date/time which are incorrect.Final Answer:
The number of milliseconds since the Arduino board started running the current program -> Option BQuick Check:
millis()= milliseconds since start [OK]
- Confusing millis() with delay()
- Thinking millis() returns seconds
- Assuming millis() gives current date/time
millis() in Arduino?Solution
Step 1: Identify the correct data type for millis()
millis()returns an unsigned long value representing milliseconds.Step 2: Match the data type with variable declaration
Only unsigned long currentTime = millis(); usesunsigned long, which can hold large millisecond values without overflow.Final Answer:
unsigned long currentTime = millis(); -> Option DQuick Check:
Use unsigned long for millis() values [OK]
- Using int which can overflow quickly
- Using float or char which are incorrect types
- Not declaring variable before assignment
unsigned long previousMillis = 0;
const long interval = 1000;
void setup() {
Serial.begin(9600);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
Serial.println("Tick");
}
}Solution
Step 1: Understand the timing logic
The code checks if 1000 milliseconds have passed since last print usingmillis()and updatespreviousMillisaccordingly.Step 2: Analyze the output behavior
When 1000 ms pass, it prints "Tick" and continues looping without blocking, so it prints every second repeatedly.Final Answer:
Prints "Tick" every 1000 milliseconds without stopping the program -> Option CQuick Check:
Non-blocking timing prints "Tick" every second [OK]
- Thinking it prints only once
- Confusing with delay() causing blocking
- Assuming compile error due to variable scope
millis() for timing:
unsigned long previousMillis;
const long interval = 2000;
void setup() {
Serial.begin(9600);
}
void loop() {
if (millis() - previousMillis >= interval) {
Serial.println("Hello");
}
}Solution
Step 1: Check how previousMillis is used
The code checks the time difference but never updatespreviousMillisafter printing.Step 2: Understand the effect of missing update
Without updating, the condition stays true, so "Hello" prints repeatedly without delay.Final Answer:
previousMillis is never updated, so "Hello" prints continuously -> Option AQuick Check:
Update previousMillis to avoid continuous printing [OK]
- Forgetting to update previousMillis
- Thinking interval type causes error
- Assuming Serial.begin() is missing
millis() for this non-blocking timing?
A) unsigned long previousMillis = 0;
const long interval = 500;
void loop() {
if (millis() - previousMillis >= interval) {
previousMillis = millis();
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
// other code runs here
}
B) void loop() {
delay(500);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
C) unsigned long previousMillis = 0;
const long interval = 500;
void loop() {
if (millis() >= previousMillis + interval) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
previousMillis = millis();
}
}
D) unsigned long previousMillis = 0;
const long interval = 500;
void loop() {
if (millis() - previousMillis > interval) {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
}
}Solution
Step 1: Identify non-blocking timing usage
Correct non-blocking blink using millis() and toggling LED usesmillis()difference and updatespreviousMilliscorrectly, toggling LED without delay.Step 2: Compare other options for blocking or logic issues
The other snippets either usedelay(), which blocks other code from running, or use addition in the condition, which can cause overflow issues with large millisecond values.Final Answer:
Correct non-blocking blink using millis() and toggling LED -> Option AQuick Check:
Use millis() difference and update previousMillis [OK]
- Using delay() causing blocking
- Not updating previousMillis properly
- Using addition risking overflow bugs
