Icono del sitio AranaCorp

Programa multitarea con ESP32 y FreeRTOS

,

El ESP32 NodeMCU se basa en el microprocesador de doble núcleo Xtensa LX6 de 32 bits que ejecuta el sistema operativo FreeRTOS. Cuando se utiliza el IDE de Arduino, el programa se ejecuta por defecto en el núcleo 1. Para la multitarea, es interesante utilizar todos los recursos del microprocesador. En este tutorial veremos cómo ejecutar tareas en ambos núcleos

Existe una librería FreeRTOS compatible con los microcontroladores Arduino con arquitectura AVR (Uno, Nano, Mega, etc.).

Material

Descripción del sistema operativo FreeRTOS

FreeRTOS es un sistema operativo en tiempo real ligero y de código abierto. Por lo tanto, se adapta perfectamente a los problemas de gestión de tareas en función del tiempo o de ocurrencia de eventos. Espressif ha integrado el sistema operativo en las últimas versiones del SDK. Por lo tanto, es posible utilizar la funcionalidad de este sistema operativo para explotar el potencial de los dos núcleos del NodeMCU ESP32 con el IDE de Arduino.

Código

En este código, crearemos varias tareas a las que asignaremos una función que se ejecutará cuando la tarea sea llamada.

Creación de la tarea asignada a un núcleo

  xTaskCreatePinnedToCore(
                    task1Func,   /* Task function. */
                    "Task1",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    10,           /* priority of the task */
                    &Task1,      /* Task handle to keep track of created task */
                    0);          /* pin task to core 0 */ 

Definición del bucle infinito que se ejecutará cuando se llame a la tarea

void task1Func( void * pvParameters ){
  for(;;){
    // place code here
  }
}

Cabe destacar que la función delay() (o vsTaskDelay) permite bloquear la tarea y pasar a la siguiente con mayor prioridad.

TaskHandle_t Task1;
TaskHandle_t Task2;
TaskHandle_t Task3;
unsigned long previousTime,previousTime1,previousTime2,previousTime3;
void setup() {
 Serial.begin(115200); 
 //create a task on core 0 that will be execute task1Func() with priority 10
 xTaskCreatePinnedToCore(
                   task1Func,   /* Task function. */
                   "Task1",     /* name of task. */
                   10000,       /* Stack size of task */
                   NULL,        /* parameter of the task */
                   10,           /* priority of the task */
                   &Task1,      /* Task handle to keep track of created task */
                   0);          /* pin task to core 0 */                             
 delay(500); 
 //create a task on core 1 that will be execute task2Func() with priority 9
 xTaskCreatePinnedToCore(
                   task2Func,   /* Task function. */
                   "Task2",     /* name of task. */
                   10000,       /* Stack size of task */
                   NULL,        /* parameter of the task */
                   9,           /* priority of the task */
                   &Task2,      /* Task handle to keep track of created task */
                   1);          /* pin task to core 1 */
   delay(500); 
   xTaskCreatePinnedToCore(task3Func, "Task3", 10000, NULL, 8, &Task3, 0);
}
void task1Func( void * pvParameters ){
 for(;;){
   Serial.printf("%s running on core %d (priorite %d) - %dms\n", "Task1", xPortGetCoreID(), uxTaskPriorityGet( NULL ),millis()-previousTime1);
   previousTime1=millis();
   delay(200);//vTaskDelay( pdMS_TO_TICKS( 200 ) );
 }
}
void task2Func( void * pvParameters ){
 for(;;){
   Serial.printf("%s running on core %d (priorite %d) - %dms\n", "Task2", xPortGetCoreID(), uxTaskPriorityGet( NULL ),millis()-previousTime2);
   previousTime2=millis();
   delay(600);
   //vTaskDelay( pdMS_TO_TICKS( 600 ) );
 }
}
void task3Func( void *pvParameters )
{
 for( ;; )
 {
   Serial.printf("%s running on core %d (priorite %d) - %dms\n", "Task3", xPortGetCoreID(), uxTaskPriorityGet( NULL ),millis()-previousTime3);
   previousTime3=millis();
   delay(100);
   //vTaskDelay( pdMS_TO_TICKS( 100 ) );
 }
}
void loop() {
 Serial.printf("%s running on core %d (priorite %d) - %dms\n", "loop()", xPortGetCoreID(), uxTaskPriorityGet( NULL ),millis()-previousTime);
 previousTime=millis();
 delay(500);
}

Hay varias funciones para crear características más avanzadas, como la sincronización y la comunicación entre tareas. Consulte la documentación.

Algunas características a recordar:

Resultado

Una vez iniciado el programa, se observa que las tareas se desarrollan de forma ordenada.

Fuentes

Salir de la versión móvil