Non-blocking code lets your Arduino do many things at once without waiting. It keeps your program running smoothly and quickly.
When you want to blink an LED while reading a sensor without stopping either task.
When you need to check buttons and control motors at the same time.
When you want to keep your program responsive to inputs while doing other work.
When you want to avoid delays that freeze your Arduino and make it unresponsive.
Syntax
Arduino
unsigned long previousMillis = 0;
const long interval = 1000;
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Do something every interval
}
// Other code runs here without delay
}
millis() returns the number of milliseconds since the Arduino started.
Use if checks with millis() instead of delay() to avoid stopping the program.
Examples
Blinks the built-in LED every 500 milliseconds without stopping other code.
Arduino
unsigned long previousMillis = 0;
const long interval = 500;
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
// Other tasks can run here
}
Prints a message every 2 seconds while allowing continuous sensor reading.
Arduino
unsigned long previousMillis = 0;
const long interval = 2000;
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
Serial.println("Checking sensor...");
}
// Read sensor continuously here
}
Sample Program
This program toggles the built-in LED every second and prints a message. It never stops running, so you can add more tasks easily.
Arduino
unsigned long previousMillis = 0;
const long interval = 1000;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
Serial.println("LED toggled");
}
// Here you can add other code that runs without delay
}
OutputSuccess
Important Notes
Never use delay() if you want your Arduino to do many things at once.
Use millis() to check how much time has passed and decide when to act.
Keep your loop() running fast by avoiding long or blocking code.
Summary
Non-blocking code lets your Arduino multitask smoothly.
Use millis() and time checks instead of delay().
This keeps your program responsive and ready for many tasks.
Practice
(1/5)
1. What is the main advantage of using non-blocking code in Arduino programming?
easy
A. It uses less memory than blocking code.
B. It makes the code run slower but more stable.
C. It allows the Arduino to perform multiple tasks without waiting.
D. It automatically fixes hardware errors.
Solution
Step 1: Understand blocking vs non-blocking
Blocking code stops the program until a task finishes, while non-blocking code lets the program keep running other tasks.
Step 2: Identify the benefit of non-blocking
Non-blocking code allows multitasking and keeps the Arduino responsive.
Final Answer:
It allows the Arduino to perform multiple tasks without waiting. -> Option C
Quick Check:
Non-blocking = multitasking [OK]
Hint: Non-blocking means no waiting, so tasks run together [OK]
Common Mistakes:
Thinking non-blocking slows code down
Confusing memory use with blocking behavior
Believing non-blocking fixes hardware issues
2. Which of the following is the correct way to check elapsed time without blocking in Arduino?
easy
A. delay(1000);
B. if (millis() - previousMillis >= interval) { /* do task */ }
C. while(millis() < 1000) { /* wait */ }
D. delayMicroseconds(1000);
Solution
Step 1: Identify blocking vs non-blocking code
delay() and while loops that wait block the program, stopping other tasks.
Step 2: Recognize millis() usage
Using millis() to check elapsed time allows the program to continue running other code.
Final Answer:
if (millis() - previousMillis >= interval) { /* do task */ } -> Option B
Quick Check:
millis() check = non-blocking [OK]
Hint: Use millis() difference, not delay(), to avoid blocking [OK]
Common Mistakes:
Using delay() which blocks the program
Using while loops that wait for time
Confusing delayMicroseconds with non-blocking
3. What will be the output of this Arduino code snippet?
unsigned long previousMillis = 0;
const long interval = 1000;
void loop() {
if (millis() - previousMillis >= interval) {
previousMillis = millis();
Serial.println("Tick");
}
}
medium
A. Prints "Tick" every second repeatedly.
B. Prints "Tick" continuously without delay.
C. Prints "Tick" once and stops.
D. Does not print anything due to syntax error.
Solution
Step 1: Analyze the millis() timing check
The code checks if 1000 milliseconds (1 second) have passed since last print.
Step 2: Understand the loop behavior
When 1 second passes, it updates previousMillis and prints "Tick" again, repeating forever.
Final Answer:
Prints "Tick" every second repeatedly. -> Option A
Quick Check:
millis() timer triggers print every 1 second [OK]
Hint: millis() timer resets each print for repeated ticks [OK]
Common Mistakes:
Thinking it prints only once
Assuming continuous printing without delay
Believing there is a syntax error
4. Identify the problem in this non-blocking Arduino code and how to fix it:
unsigned long previousMillis = 0;
const long interval = 1000;
void loop() {
if (millis() > previousMillis + interval) {
Serial.println("Hello");
}
}
medium
A. It never updates previousMillis, causing continuous prints.
B. The comparison operator should be '<' instead of '>'.
C. The interval variable must be unsigned long, not long.
D. Serial.println() cannot be used inside loop.
Solution
Step 1: Check the timing logic
The code checks if millis() is greater than previousMillis + interval but never updates previousMillis.
Step 2: Understand the effect
Without updating previousMillis, the condition stays true, so "Hello" prints continuously without delay.
Final Answer:
It never updates previousMillis, causing continuous prints. -> Option A
Hint: Always update previousMillis after action to avoid repeats [OK]
Common Mistakes:
Forgetting to update previousMillis
Changing comparison operator incorrectly
Thinking Serial.println() is invalid in loop
5. You want to blink an LED every 500ms and read a sensor every 200ms without blocking. Which code structure best achieves this?
hard
A. Use while loops to wait 500ms and 200ms before each task.
B. Use delay(500) for LED blink and delay(200) for sensor reading in sequence.
C. Use a single millis() timer for both tasks with combined interval 700ms.
D. Use two millis() timers, one for LED and one for sensor, each updating separately.
Solution
Step 1: Understand multitasking with millis()
Each task needs its own timer to run independently without blocking.
Step 2: Evaluate options
Use two millis() timers, one for LED and one for sensor, each updating separately. This uses two separate millis() timers, allowing LED and sensor to run at different intervals smoothly.
Final Answer:
Use two millis() timers, one for LED and one for sensor, each updating separately. -> Option D
Quick Check:
Separate timers = true multitasking [OK]
Hint: Use separate millis() timers for each task to avoid blocking [OK]
Common Mistakes:
Using delay() which blocks all tasks
Combining intervals causing missed timings
Using while loops that block execution
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.