ESP32 - RTOS - 3 Blinking LEDs Different timing

This tutorial instructs you how to use RTOS with ESP32 to make a project that blinks three LEDs at different timing

Video Tutorial

you can watch this video tutorial

Hardware Required

1×ESP-WROOM-32 Dev Module
1×Micro USB Cable
3×LED
1×Breadboard
n×Jumper Wires

Introduction to RTOS

A real-time operating system (RTOS) is an operating system (OS) (often a lightweight OS) that runs multi-threaded applications and can meet real-time deadlines. Most RTOSes include a scheduler, resource management, and device drivers. Note that when we talk about “deadlines,” we do not necessarily mean “fast.” Instead, meeting deadlines indicates a level of determinism, meaning we can figure out when certain tasks will execute prior to runtime.

FreeRTOS

FreeRTOS is a real-time kernel (or real-time scheduler) on top of which embedded applications can be built to meet their hard real-time requirements.

It allows applications to be organized as a collection of independent threads of execution.

The kernel decides which thread should be executing by examining the priority assigned to each thread by the application designer.

In the simplest case, the application designer could assign higher priorities to threads with some requirements, and lower priorities to threads with some requirements.

How To Program FreeRTOS

  • Tasks are implemented as C functions which must return void and take a void pointer parameter:
  • void ATaskFunction ( void * pvParameters )
    {
       /* Variables declaration . */
       int32_t lVariableExample = 0;
       /* A task will normally be
       implemented as an infinite loop . */
       for ( ;; ) {
           /* The code to implement
           the task functionality will go here . */
       }
       vTaskDelete ( NULL );
    }
  • Tasks are created using the FreeRTOS xTaskCreate() API function.
  • BaseType_t xTaskCreate (
       TaskFunction_t pvTaskCode ,
       const char * const pcName ,
       uint16_t usStackDepth ,
       void * pvParameters ,
       UBaseType_t uxPriority ,
       TaskHandle_t * pxCreatedTask )
    • pvTaskCode: The pvTaskCode parameter is simply a pointer to the function that implements the task (in effect, just the name of the function);
    • pcName: A descriptive name for the task. This is not used by FreeRTOS in any way. It is included purely as a debugging aid;
    • usStackDepth: Each task has its own unique stack that is allocated by the kernel to the task when the task is created. The usStackDepth value tells the kernel how large to make the stack;
    • pvParameters: Task functions accept a parameter of type pointer to void ( void* );
    • uxPriority: Defines the priority at which the task will execute. Priorities can be assigned from 0, which is the lowest priority to the highest priority;
    • pxCreatedTask: pxCreatedTask can be used to pass out a handle to the task being created. This handle can then be used to reference the task in API calls that, for example, change the task priority or delete the task. If your application has no use for the task handle, then pxCreatedTask can be set to NULL;
    • There are two possible return values: pdPASS or pdFAIL. Fail indicates that the task has not been created because there is insufficient heap memory available for FreeRTOS to allocate enough RAM to hold the task data structures and stack

For more information about FreeRTOS Please visite Documentation

Wiring Diagram

Schematic Diagram

ESP32 Button LED Wiring Diagram

Image is developed using Fritzing. Click to enlarge image

Breadboard Connections

ESP32 Button LED Wiring Diagram

Image is developed using Fritzing. Click to enlarge image

click to see ESP32 pin out

ESP32 Code

Copy

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif


void TaskBlink1( void *pvParameters );
void TaskBlink2( void *pvParameters );
void TaskBlink3( void *pvParameters );

void setup() {

  // Now set up three tasks to run independently.
  xTaskCreatePinnedToCore(
    TaskBlink1
    ,  "TaskBlink1"   // A name just for humans
    ,  1024  // 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.
    ,  NULL 
    ,  ARDUINO_RUNNING_CORE);

    xTaskCreatePinnedToCore(
    TaskBlink2
    ,  "TaskBlink2"   // A name just for humans
    ,  1024  // 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.
    ,  NULL 
    ,  ARDUINO_RUNNING_CORE);

    xTaskCreatePinnedToCore(
    TaskBlink3
    ,  "TaskBlink3"   // A name just for humans
    ,  1024  // 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.
    ,  NULL 
    ,  ARDUINO_RUNNING_CORE);
    
  
  Serial.begin(115200);
  
}

void loop() {
  
}

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

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

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

  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(15, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay(500);  // one tick delay (15ms) in between reads for stability
    digitalWrite(15, LOW);    // turn the LED off by making the voltage LOW
    vTaskDelay(500);  // one tick delay (15ms) in between reads for stability
  }
}

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

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

  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(2, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay(200);  // one tick delay (15ms) in between reads for stability
    digitalWrite(2, LOW);    // turn the LED off by making the voltage LOW
    vTaskDelay(200);  // one tick delay (15ms) in between reads for stability
  }
}

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

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

  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay(300);  // one tick delay (15ms) in between reads for stability
    digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW
    vTaskDelay(300);  // one tick delay (15ms) in between reads for stability
  }
}           

Quick Steps

  • power up your board
  • Open Arduino IDE
  • Select the right board
  • Select the right port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Arduino IDE Upload Code
  • See the changes you made

Book Tutorial

We are considering to make the book tutorials. If you think the book tutorials are essential, you can download it. download book

References

※ NOTE THAT:

Some components works on 3.3v and others works on 5v!