0
0
Arduinoprogramming~10 mins

Non-blocking code architecture in Arduino - Step-by-Step Execution

Choose your learning style9 modes available
Concept Flow - Non-blocking code architecture
Start loop()
Check time elapsed?
NoDo other tasks
Repeat loop()
Perform action
Update last action time
Do other tasks
Repeat loop()
The loop checks if enough time has passed to do an action without stopping other tasks, then performs the action and continues running other code.
Execution Sample
Arduino
unsigned long previousMillis = 0;
const long interval = 1000;

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    // action code here
  }
  // other code here
}
This code runs an action every 1000 milliseconds without stopping other code from running.
Execution Table
StepcurrentMillispreviousMillisCondition (currentMillis - previousMillis >= interval)ActionOutput
1000 - 0 >= 1000 ? FalseSkip actionNo action
25000500 - 0 >= 1000 ? FalseSkip actionNo action
3100001000 - 0 >= 1000 ? TrueUpdate previousMillis=1000; perform actionAction performed
4150010001500 - 1000 >= 1000 ? FalseSkip actionNo action
5200010002000 - 1000 >= 1000 ? TrueUpdate previousMillis=2000; perform actionAction performed
6250020002500 - 2000 >= 1000 ? FalseSkip actionNo action
ExitN/AN/ALoop repeats indefinitelyLoop continuesNo stop
💡 The loop runs forever, checking time and performing actions only when interval passes.
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3After Step 4After Step 5After Step 6Final
previousMillis00010001000200020002000
currentMillis0050010001500200025002500
Key Moments - 3 Insights
Why doesn't the code use delay() to wait for the interval?
Using delay() would stop all code and block other tasks. The execution_table shows the loop keeps running and checking time without stopping.
How does the code know when to perform the action?
It compares currentMillis and previousMillis to see if the interval passed, as shown in the Condition column of the execution_table.
What happens to previousMillis after the action runs?
It updates to currentMillis to reset the timer, so the next action waits for the full interval again (see Step 3 and Step 5).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at Step 3. What is the value of previousMillis after the action?
A500
B0
C1000
D1500
💡 Hint
Check the 'Action' and 'previousMillis' columns at Step 3 in the execution_table.
At which step does the condition become true for the first time?
AStep 3
BStep 2
CStep 1
DStep 4
💡 Hint
Look at the 'Condition' column in the execution_table to find when it first becomes true.
If interval was changed to 500, how would Step 2's condition change?
A500 - 0 >= 500 would be False
B500 - 0 >= 500 would be True
CCondition would not change
DCondition would be invalid
💡 Hint
Compare the condition formula with the new interval value in the execution_table.
Concept Snapshot
Non-blocking code uses millis() to check elapsed time.
Avoid delay() to keep code responsive.
Use variables to track last action time.
Perform actions only when interval passes.
Loop keeps running other tasks smoothly.
Full Transcript
This example shows how to write Arduino code that does not stop running other tasks while waiting. Instead of delay(), it uses millis() to check if enough time passed since the last action. If yes, it performs the action and updates the timer. Otherwise, it continues running other code. The execution table traces each step, showing how variables change and when actions happen. This method keeps the program responsive and able to do many things at once.