fbpixel
Etiquetas: ,

,

O NóMCU ESP32 é baseado no microprocessador dual-core Xtensa LX6 de 32 bits que executa o SO FreeRTOS. Ao utilizar o Arduino IDE, o programa corre por defeito no núcleo 1. Para multitarefas, é interessante utilizar todos os recursos do microprocessador. Neste tutorial veremos como executar tarefas em ambos os núcleos

Existe uma biblioteca FreeRTOS compatível para microcontroladores Arduino com arquitectura AVR (Uno, Nano, Mega, etc.).

Material

  • NóMCU ESP32
  • Cabo USB A Masculino

Descrição do sistema operacional FreeRTOS

FreeRTOS est un système d’exploitation temps-réel open-source et léger. Il est donc parfaitement adapté à des problématiques de gestion de tâches en fonction du temps ou d’occurrence d’événements. Espressif a intégré l’OS sur les dernières versions du SDK. Il est donc possible d’utiliser les fonctionnalité de cet OS afin d’exploiter le potentiel des deux coeurs du NóMCU ESP32 avec l’IDE Arduino.

Código

Neste código, iremos criar várias tarefas às quais iremos atribuir uma função que será executada quando a tarefa for chamada.

Criação da tarefa atribuída a um 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 */ 

Definição do loop infinito a ser executado quando a tarefa é chamada

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

Vale a pena notar que a função delay() (ou vsTaskDelay) permite bloquear a tarefa e passar para a tarefa seguinte com a maior prioridade.

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);
}

Existem várias funções para criar características mais avançadas, tais como sincronização e comunicação entre tarefas. Consulte por favor a documentação.

Algumas características a recordar:

  • xTaskCreate() para criar uma tarefa
  • xTaskCreatePinnedToCore() para criar uma tarefa sobre um núcleo específico
  • vTaskDelayUntil() para activar uma tarefa periodicamente
  • vTaskDelay() bloqueia uma tarefa para um determinado número de ticks do relógio (utiliza pdMS_TO_TICKS para converter uma duração em um número de ticks)
  • vTaskPrioritySet() altera a prioridade de uma tarefa
  • vTaskDelete() para apagar uma tarefa

Resultado

Uma vez iniciado o programa, as tarefas são observadas para funcionarem de forma ordenada.

esp32-multitasking-result Programa multitarefa com ESP32 e FreeRTOS

Fontes