Understanding Threads in Arduino
Threads are a fundamental concept in programming that allow multiple sequences of operations to run concurrently. In the context of Arduino, threading is an important aspect for executing multiple tasks simultaneously without blocking the main program loop. However, because traditional Arduino platforms typically operate on a single-threaded architecture, executing multiple threads requires some ingenuity and the use of specific libraries or approaches.
Utilizing the FreeRTOS Library
FreeRTOS is an effective real-time operating system used to manage multiple threads on Arduino boards. This library allows developers to create independent tasks (threads) that can run concurrently. Starting with FreeRTOS requires including the library in your Arduino IDE, which can be installed through the Library Manager.
Once FreeRTOS is set up, tasks can be defined using the xTaskCreate
function. Each task will have its own function, stack size, priority, and parameters. Here’s how to get started:
-
Include FreeRTOS in your sketch:
#include <Arduino_FreeRTOS.h>
-
Define task functions:
Each task is written as a function. For example:void TaskBlink(void *pvParameters) { for (;;) { digitalWrite(LED_BUILTIN, HIGH); vTaskDelay(pdMS_TO_TICKS(500)); digitalWrite(LED_BUILTIN, LOW); vTaskDelay(pdMS_TO_TICKS(500)); } } void TaskMonitor(void *pvParameters) { for (;;) { Serial.println("Monitoring sensors..."); vTaskDelay(pdMS_TO_TICKS(1000)); } }
-
Create tasks in the setup function:
The tasks must be created in thesetup()
function as follows:void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); xTaskCreate(TaskBlink, "Blink", 100, NULL, 1, NULL); xTaskCreate(TaskMonitor, "Monitor", 100, NULL, 1, NULL); }
- Start the scheduler:
To initiate the multitasking, callvTaskStartScheduler()
at the end of the setup function, allowing the FreeRTOS control to take over and manage task scheduling.
Using the Scheduler with Non-Blocking Code
When multiple operations need to be run without traditional threading, using a non-blocking approach is crucial. This involves splitting functions into smaller pieces that can be executed in intervals without halting the program flow. Use the millis()
function to track time and control the execution of each operation.
For example, if you are reading a sensor every second while simultaneously blinking an LED, you can achieve this using a non-blocking loop:
unsigned long previousMillis = 0;
const long interval = 1000;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Read sensor value
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
}
// Simulating LED blink
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
Leveraging Arduino’s Built-in Functions
Some Arduino-compatible boards, especially those based on the ATmega32u4 or ESP8266, support multitasking natively. In these environments, using built-in functions such as yield()
can help manage tasks by allowing the processor to switch between them more efficiently.
By invoking yield()
within long-running loops or any function that leads to delays, control is returned to the scheduler so it can attend to other tasks, enhancing responsiveness.
FAQs
1. What are the advantages of using threads on Arduino?
Threads help in managing multiple tasks efficiently without blocking the main program loop, allowing for more complex designs like real-time monitoring, control systems, or interactive devices.
2. Can I use FreeRTOS on any Arduino board?
While many Arduino boards are compatible with FreeRTOS, performance may vary. Boards with more processing power and memory, like Arduino Due or ESP32, are recommended for better multitasking capabilities.
3. What is the difference between multitasking and multithreading in the context of Arduino?
Multitasking refers to executing multiple tasks at once, typically managed through non-blocking code or scheduling methods. Multithreading involves running multiple threads (or tasks) concurrently, which can be handled using libraries like FreeRTOS that simulate a multi-threaded environment.