,
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.