FreeRTOS operating system for Arduino, running multiple processes in parallel

posted in: Microcontroller | 0

1. Introduction

In the previous post, I showed you how to use timer interrupt to create multi-process, today I will show you a simpler way to create multi-process. That is using the FreeRTOS operating system.

FreeRTOS Real Time Operating System is an open source embedded Real Time Operating System developed by Real Time Engineers Ltd, founded and owned by Richard Barry. FreeRTOS is designed to be suitable for many compact embedded systems because it implements very few functions such as: basic task and memory management mechanisms, important API functions for synchronization mechanisms. It does not provide built-in network interfaces, drivers, or file systems like other high-end embedded operating systems. However, FreeRTOS has many advantages, supporting many different microcontroller architectures, compact size (4.3 Kbytes after compiling on Arduino), written in C language and can be used, developed with various C compilers (GCC, OpenWatcom, Keil, IAR, Eclipse, …), allowing unlimited tasks to run concurrently, unlimited execution priority, hardware mining capabilities. In addition, it also allows implementing moderation mechanisms between processes such as: queues, counting semaphore, mutexes.

You go to Include Library -> Manage Library, find FreeRTOS and install the library part.

2. Programming

Idea: Create a program that blinks Led pin 12, reads Analog signal at pin A0 and sends Serial.

#include <Arduino_FreeRTOS.h>
#define LED_BUILTIN 12
// define two tasks for Blink & AnalogRead
void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );

// the setup function runs once when you press reset or power the board
void setup() {
  
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
  }

  // Now set up two tasks to run independently.
  xTaskCreate(
    TaskBlink // Tạo task nháy led
    ,  "Blink"   // A name just for humans
    ,  128  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  2  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. Mức độ ưu tiên
    ,  NULL );

  xTaskCreate(
    TaskAnalogRead // Tạo task đọc analog
    ,  "AnalogRead"
    ,  128  // Stack size
    ,  NULL
    ,  1  // Priority Mức độ ưu tiên
    ,  NULL );

  // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

void loop()
{
  // Empty. Things are done in Tasks. Để trống vì mọi thứ được thực hiện trong các task
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void TaskBlink(void *pvParameters)  // This is a task.
{
  (void) pvParameters;

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO 
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care 
  of use the correct LED pin whatever is the board used.
  
  The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute
  the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.
  e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.
  
  If you want to know what pin the on-board LED is connected to on your Arduino model, check
  the Technical Specs of your board  at https://www.arduino.cc/en/Main/Products
  
  This example code is in the public domain.

  modified 8 May 2014
  by Scott Fitzgerald
  
  modified 2 Sep 2016
  by Arturo Guadalupi
*/

  // initialize digital LED_BUILTIN on pin 13 as an output.
  pinMode(LED_BUILTIN, OUTPUT);

  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
  }
}

void TaskAnalogRead(void *pvParameters)  // This is a task.
{
  (void) pvParameters;
  
/*
  AnalogReadSerial
  Reads an analog input on pin 0, prints the result to the serial monitor.
  Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
  Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

  This example code is in the public domain.
*/

  for (;;)
  {
    // read the input on analog pin 0:
    int sensorValue = analogRead(A0);
    // print out the value you read:
    Serial.println(sensorValue);
    vTaskDelay(1);  // one tick delay (15ms) in between reads for stability
  }
}

With the FreeRTOS operating system you will easily create complex projects without the headache of timer interrupts and code synchronization.

Leave a Reply

Your email address will not be published.