Blink without delay pattern in Arduino - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
We want to understand how the time cost changes when using the blink without delay pattern in Arduino code.
Specifically, how the program's running steps grow as we keep blinking the LED.
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;
// toggle LED state here
}
}
This code blinks an LED without using delay(), checking time passed to toggle the LED.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The loop() function runs repeatedly, checking the time and condition.
- How many times: It runs continuously, many thousands of times per second.
Each time loop() runs, it does a fixed number of steps regardless of how long the program runs.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks |
| 100 | About 100 checks |
| 1000 | About 1000 checks |
Pattern observation: The number of operations grows directly with how many times loop() runs, but each run does the same small work.
Time Complexity: O(n)
This means the work grows linearly with the number of loop cycles, doing a small fixed check each time.
[X] Wrong: "The code does more work as time passes because the LED toggling slows it down."
[OK] Correct: The code always does the same quick check each loop; toggling the LED happens only occasionally and does not add extra loops.
Understanding how simple repeated checks work helps you explain efficient timing in embedded systems, a useful skill for many projects.
"What if we added a nested loop inside loop() that runs a fixed number of times each cycle? How would the time complexity change?"
Practice
Blink without delay pattern in Arduino programming?Solution
Step 1: Understand delay() limitation
The delay() function pauses the whole program, stopping other tasks.Step 2: millis() allows multitasking
Using millis() tracks time without stopping the program, so other code runs simultaneously.Final Answer:
It allows the Arduino to perform other tasks while blinking an LED. -> Option AQuick Check:
Blink without delay = multitasking [OK]
- Thinking delay() lets other code run
- Believing blink speed is faster with millis()
- Assuming millis() uses less power
Solution
Step 1: Identify correct data type for millis()
millis() returns an unsigned long value representing milliseconds.Step 2: Match variable type to millis()
To store millis() values, useunsigned longto avoid overflow and negative values.Final Answer:
unsigned long previousMillis = 0; -> Option AQuick Check:
Use unsigned long for time tracking [OK]
- Using int which can overflow quickly
- Using float which is unnecessary and imprecise
- Using boolean which can't store time
const int ledPin = 13;
unsigned long previousMillis = 0;
const long interval = 1000;
bool ledState = false;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ledState = !ledState;
digitalWrite(ledPin, ledState ? HIGH : LOW);
}
}Solution
Step 1: Analyze timing logic
The code checks if 1000 ms passed since last toggle, then flips ledState.Step 2: Understand LED toggle and output
ledState toggles true/false every second, controlling LED on/off without delay blocking.Final Answer:
The LED on pin 13 will blink on and off every 1 second without stopping other code. -> Option BQuick Check:
Millis timing toggles LED every 1 second [OK]
- Thinking bool causes compile error
- Assuming LED stays on permanently
- Confusing rapid blinking with 1-second interval
const int ledPin = 13;
unsigned long previousMillis = 0;
const long interval = 1000;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
digitalWrite(ledPin, !digitalRead(ledPin));
}
}Solution
Step 1: Check use of digitalRead on output pin
digitalRead() on an output pin is unreliable and not recommended for toggling.Step 2: Understand proper toggle method
Better to track LED state in a variable rather than reading output pin state.Final Answer:
digitalRead() cannot be used on output pins. -> Option DQuick Check:
Don't use digitalRead on output pins [OK]
- Thinking > vs >= causes major error
- Believing previousMillis type is wrong
- Assuming digitalWrite logic causes runtime error
Solution
Step 1: Understand independent timing needs
Each LED needs its own timer variable to track its blinking interval separately.Step 2: Avoid blocking delays and incorrect loops
Using delay() or nested loops blocks code and prevents independent blinking.Final Answer:
Use two separate previousMillis variables and check each interval independently in loop(). -> Option CQuick Check:
Separate timers for independent blinking [OK]
- Using one timer for both LEDs
- Using delay() which blocks code
- Trying nested loops for timing
