0
0
AutocadHow-ToBeginner · 3 min read

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 of delay().
  • Keep tasks short and non-blocking.
  • Store last run time for each task separately.
  • Check elapsed time before running each task.
  • Use digitalRead() and digitalWrite() 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.