How to Create Multitask Arduino Without RTOS
You can create multitask behavior on Arduino without an
RTOS by using non-blocking code with millis() to manage timing and switch between tasks. This approach lets you run multiple functions seemingly at the same time by checking elapsed time instead of using delay().Syntax
Use millis() to track elapsed time without stopping the program. Store the last time a task ran and check if enough time has passed to run it again.
Basic pattern:
unsigned long previousMillis = 0;
const unsigned long interval = 1000; // time in milliseconds
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// run your task here
}
// other code can run here without delay
}arduino
unsigned long previousMillis = 0; const unsigned long interval = 1000; // 1 second void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; // Task code here } // Other tasks can run here }
Example
This example blinks two LEDs at different intervals without blocking each other. It shows how multitasking works by checking time for each task separately.
arduino
const int ledPin1 = 13; const int ledPin2 = 12; unsigned long previousMillis1 = 0; unsigned long previousMillis2 = 0; const unsigned long interval1 = 500; // Blink LED1 every 500ms const unsigned long interval2 = 1000; // Blink LED2 every 1000ms void setup() { pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT); } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis1 >= interval1) { previousMillis1 = currentMillis; digitalWrite(ledPin1, !digitalRead(ledPin1)); } if (currentMillis - previousMillis2 >= interval2) { previousMillis2 = currentMillis; digitalWrite(ledPin2, !digitalRead(ledPin2)); } }
Output
LED on pin 13 blinks every 0.5 seconds; LED on pin 12 blinks every 1 second, independently.
Common Pitfalls
- Using
delay()blocks all code, stopping multitasking. - Not updating the previous time variable causes tasks to run repeatedly without delay.
- Mixing blocking code like
delay()with non-blocking code breaks multitasking.
Correct multitasking requires all tasks to be non-blocking and use millis() timing.
arduino
/* Wrong way: Using delay blocks multitasking */ void loop() { digitalWrite(13, HIGH); delay(500); // blocks everything digitalWrite(13, LOW); delay(500); // blocks everything // No other tasks can run here } /* Right way: Using millis() for non-blocking timing */ unsigned long previousMillis = 0; const unsigned long interval = 500; void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; digitalWrite(13, !digitalRead(13)); } // Other tasks can run here }
Quick Reference
Tips for multitasking on Arduino without RTOS:
- Use
millis()to track time instead ofdelay(). - Keep tasks short and non-blocking.
- Store last run time for each task separately.
- Check elapsed time before running each task.
- Use
digitalRead()anddigitalWrite()carefully to toggle outputs.
Key Takeaways
Use millis() for timing to avoid blocking code and enable multitasking.
Avoid delay() because it stops all other code from running.
Track last run time for each task separately to manage multiple tasks.
Keep each task short and non-blocking for smooth multitasking.
Multitasking without RTOS is cooperative and depends on careful timing checks.