{"id":17000,"date":"2021-08-04T18:10:26","date_gmt":"2021-08-04T21:10:26","guid":{"rendered":"https:\/\/arduxop.com.br\/loja\/?p=17000"},"modified":"2021-08-04T18:49:56","modified_gmt":"2021-08-04T21:49:56","slug":"multitarefa-em-esp32-com-arduino-e-freertos","status":"publish","type":"post","link":"https:\/\/arduxop.com.br\/loja\/multitarefa-em-esp32-com-arduino-e-freertos\/","title":{"rendered":"Multitarefa em ESP32 com Arduino e FreeRTOS"},"content":{"rendered":"<div class=\"post-image\"><\/div>\n<div class=\"post-content\">\n<div class=\"entry-content clearfix\">\n<p>Existem v\u00e1rios casos de uso para querer multitarefa em um microcontrolador. Por exemplo: voc\u00ea pode ter um microcontrolador que l\u00ea um sensor de temperatura, mostra-o em um LCD e o envia para a nuvem.<\/p>\n<p>Voc\u00ea pode fazer todos os tr\u00eas de forma s\u00edncrona, um ap\u00f3s o outro. Mas e se voc\u00ea estiver usando uma tela e-ink que leva alguns segundos para atualizar?<\/p>\n<div class=\"google-auto-placed ap_container\"><\/div>\n<p>Felizmente, a implementa\u00e7\u00e3o do Arduino para o ESP32 inclui a possibilidade de agendar tarefas com o FreeRTOS. Eles podem ser executados em um \u00fanico n\u00facleo, muitos n\u00facleos e voc\u00ea pode at\u00e9 definir o que \u00e9 mais importante e deve receber tratamento preferencial.<\/p>\n<p>&nbsp;<\/p>\n<h3>Cria\u00e7\u00e3o de tarefas<\/h3>\n<p>Para agendar uma tarefa, voc\u00ea deve fazer duas coisas: criar uma fun\u00e7\u00e3o que contenha o c\u00f3digo que deseja executar e, em seguida, criar uma tarefa que chame essa fun\u00e7\u00e3o.<\/p>\n<p>Digamos que eu queira acender e apagar um LED continuamente.<\/p>\n<div class=\"google-auto-placed ap_container\"><\/div>\n<p>Primeiro, vou definir o pino ao qual o LED est\u00e1 conectado e definir seu modo para OUTPUT. Coisas muito comuns do Arduino:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-k8\">const<\/span> <span class=\"enlighter-k5\">int<\/span><span class=\"enlighter-text\"> led1 = 2;<\/span><span class=\"enlighter-c0\"> \/\/ Pino do LED<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-k5\">void<\/span> <span class=\"enlighter-m0\">setup<\/span><span class=\"enlighter-g1\">(){<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">pinMode<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">led1, OUTPUT<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>A seguir, criarei uma fun\u00e7\u00e3o que se tornar\u00e1 a base da tarefa. Eu uso digitalWrite() para ligar e desligar o LED e uso <code>vTaskDelay<\/code> (em vez de delay()) para pausar a tarefa 500ms entre os estados alterados:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-k5\">void<\/span> <span class=\"enlighter-m0\">toggleLED<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-k5\">void<\/span><span class=\"enlighter-text\"> * parameter<\/span><span class=\"enlighter-g1\">){<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-k1\">for<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">;;<\/span><span class=\"enlighter-g1\">){<\/span><span class=\"enlighter-c0\"> \/\/ Loop infinito<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ Ligue o LED<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">digitalWrite<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">led1, HIGH<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ Ligue o LED<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">vTaskDelay<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">500 \/ portTICK_PERIOD_MS<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ Desligue o LED<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">digitalWrite<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">led1, LOW<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ Pause a tarefa novamente por 500ms<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">vTaskDelay<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">500 \/ portTICK_PERIOD_MS<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Essa \u00e9 sua primeira tarefa! Algumas coisas a serem observadas:<\/p>\n<p>Sim, criamos um loop for infinito (;;) e isso pode parecer um pouco estranho. Como podemos realizar v\u00e1rias tarefas se escrevermos uma tarefa que dura para sempre? O truque \u00e9 vTaskDelay, que diz ao planejador que essa tarefa n\u00e3o deve ser executada por um determinado per\u00edodo. O agendador pausar\u00e1 o loop for e executar\u00e1 outras tarefas (se houver).<\/p>\n<div class=\"google-auto-placed ap_container\"><\/div>\n<p>Por \u00faltimo, mas n\u00e3o menos importante, temos que informar o planejador sobre nossa tarefa. Podemos fazer isso na fun\u00e7\u00e3o <code>setup()<\/code>:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-k5\">void<\/span> <span class=\"enlighter-m0\">setup<\/span><span class=\"enlighter-g1\">()<\/span> <span class=\"enlighter-g1\">{<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">xTaskCreate<\/span><span class=\"enlighter-g1\">(<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> toggleLED, <\/span><span class=\"enlighter-c0\"> \/\/ Fun\u00e7\u00e3o que deve ser chamada<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-s0\">&#8220;Toggle LED&#8221;<\/span><span class=\"enlighter-text\">, <\/span><span class=\"enlighter-c0\"> \/\/ Nome da tarefa (para depura\u00e7\u00e3o)<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1000, <\/span><span class=\"enlighter-c0\"> \/\/ Nome da tarefa (para depura\u00e7\u00e3o)<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-text\">, <\/span><span class=\"enlighter-c0\"> \/\/ Par\u00e2metro para passar<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1, <\/span><span class=\"enlighter-c0\"> \/\/ Prioridade da tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-e1\">NULL<\/span> <span class=\"enlighter-c0\"> \/\/ Identificador de tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>\u00c9 isso a\u00ed! Quer piscar outro LED em um intervalo diferente? Basta criar outra tarefa e sentar enquanto o planejador cuida da execu\u00e7\u00e3o de ambas.<\/p>\n<h3><\/h3>\n<h3>Cria\u00e7\u00e3o de uma tarefa \u00fanica<\/h3>\n<p>Voc\u00ea tamb\u00e9m pode criar tarefas que s\u00e3o executadas apenas uma vez. Por exemplo, meu monitor de energia cria uma tarefa para fazer upload de dados para a nuvem quando tiver leituras suficientes.<\/p>\n<p>Tarefas \u00fanicas n\u00e3o precisam de um loop for sem fim; em vez disso, tem a seguinte apar\u00eancia:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-k5\">void<\/span> <span class=\"enlighter-m0\">uploadToAWS<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-k5\">void<\/span><span class=\"enlighter-text\"> * parameter<\/span><span class=\"enlighter-g1\">){<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ Implemente sua l\u00f3gica personalizada aqui<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ Quando terminar, chame vTaskDelete. N\u00e3o se esque\u00e7a disso!<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">vTaskDelete<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Isso se parece com uma fun\u00e7\u00e3o C ++ normal, exceto para o <code>vTaskDelete()<\/code>. Depois de cham\u00e1-lo, o FreeRTOS sabe que a tarefa foi conclu\u00edda e n\u00e3o deve ser reprogramada. (Nota: n\u00e3o se esque\u00e7a de chamar esta fun\u00e7\u00e3o, ou isso far\u00e1 com que o watchdog reinicie o ESP32).<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-m0\">xTaskCreate<\/span><span class=\"enlighter-g1\">(<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> uploadToAWS, <\/span><span class=\"enlighter-c0\"> \/\/ Fun\u00e7\u00e3o que deve ser chamada<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-s0\">&#8220;Upload to AWS&#8221;<\/span><span class=\"enlighter-text\">, <\/span><span class=\"enlighter-c0\"> \/\/ Nome da tarefa (para depura\u00e7\u00e3o)<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1000, <\/span><span class=\"enlighter-c0\"> \/\/ Tamanho da pilha (bytes)<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-text\">, <\/span><span class=\"enlighter-c0\"> \/\/ Par\u00e2metro para passar<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1, <\/span><span class=\"enlighter-c0\"> \/\/ Prioridade da tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-e1\">NULL<\/span> <span class=\"enlighter-c0\"> \/\/ Identificador de tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h3>Escolha em qual n\u00facleo executar<\/h3>\n<p>Quando voc\u00ea usa <code>xTaskCreate()<\/code>, o agendador \u00e9 livre para escolher em qual n\u00facleo ele executa sua tarefa. Na minha opini\u00e3o, esta \u00e9 a solu\u00e7\u00e3o mais flex\u00edvel (voc\u00ea nunca sabe quando um chip IoT quad-core pode aparecer, certo?)<\/p>\n<p>No entanto, \u00e9 poss\u00edvel fixar uma tarefa em um n\u00facleo espec\u00edfico com <code>xTaskCreatePinnedToCore<\/code>. \u00c9 como <code>xTaskCreate<\/code> e leva um par\u00e2metro adicional, o n\u00facleo no qual voc\u00ea deseja executar a tarefa:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-m0\">xTaskCreatePinnedToCore<\/span><span class=\"enlighter-g1\">(<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> uploadToAWS, <\/span><span class=\"enlighter-c0\"> \/\/ Fun\u00e7\u00e3o que deve ser chamada<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-s0\">&#8220;Upload to AWS&#8221;<\/span><span class=\"enlighter-text\">, <\/span><span class=\"enlighter-c0\"> \/\/ Nome da tarefa (para depura\u00e7\u00e3o)<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1000, <\/span><span class=\"enlighter-c0\"> \/\/ Tamanho da pilha (bytes)<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-text\">, <\/span><span class=\"enlighter-c0\"> \/\/ Par\u00e2metro para passar<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1, <\/span><span class=\"enlighter-c0\"> \/\/ Prioridade da tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-text\">, <\/span><span class=\"enlighter-c0\"> \/\/ Identificador de tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 0, <\/span><span class=\"enlighter-c0\"> \/\/ Core em que voc\u00ea deseja executar a tarefa (0 ou 1)<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<h3>Verifique em qual n\u00facleo voc\u00ea est\u00e1 executando<\/h3>\n<p>A maioria das placas ESP32 tem processadores dual-core, ent\u00e3o como saber em qual n\u00facleo sua tarefa est\u00e1 sendo executada?<\/p>\n<p>Basta chamar <code>xPortGetCoreID()<\/code> de dentro de sua tarefa:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-k5\">void<\/span> <span class=\"enlighter-m0\">exampleTask<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-k5\">void<\/span><span class=\"enlighter-text\"> * parameter<\/span><span class=\"enlighter-g1\">){<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> Serial.<\/span><span class=\"enlighter-m3\">print<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-s0\">&#8220;A tarefa est\u00e1 sendo executada em:&#8221;<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> Serial.<\/span><span class=\"enlighter-m3\">println<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-m0\">xPortGetCoreID<\/span><span class=\"enlighter-g1\">())<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">vTaskDelay<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">100 \/ portTICK_PERIOD_MS<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Quando voc\u00ea tiver tarefas suficientes, o planejador come\u00e7ar\u00e1 a despach\u00e1-las para ambos os n\u00facleos.<\/p>\n<p>&nbsp;<\/p>\n<h3>Parando tarefas<\/h3>\n<p>Agora, e se voc\u00ea adicionou uma tarefa ao agendador, mas deseja interromp\u00ea-la? Duas op\u00e7\u00f5es: voc\u00ea exclui a tarefa de dentro dela mesma ou usa um identificador de tarefa. Terminar uma tarefa de dentro j\u00e1 foi discutido antes (use <code>vTaskDelete<\/code>).<\/p>\n<p>Para interromper uma tarefa de outro lugar (como outra tarefa ou seu loop principal), temos que armazenar um identificador de tarefa:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-c0\">\/\/ Este TaskHandle permitir\u00e1<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\">TaskHandle_t task1Handle = <\/span><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-k5\">void<\/span> <span class=\"enlighter-m0\">task1<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-k5\">void<\/span><span class=\"enlighter-text\"> * parameter<\/span><span class=\"enlighter-g1\">){<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ sua l\u00f3gica de tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">xTaskCreate<\/span><span class=\"enlighter-g1\">(<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> task1,<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-s0\">&#8220;Task 1&#8221;<\/span><span class=\"enlighter-text\">,<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1000,<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-text\">,<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> 1,<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-text\"> task1Handle <\/span><span class=\"enlighter-c0\"> \/\/ Identificador de tarefa<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Bastava definir o identificador e pass\u00e1-lo como \u00faltimo par\u00e2metro de <code>xTaskCreate<\/code>. Agora podemos elimin\u00e1-lo com <code>vTaskDelete<\/code>:<\/p>\n<div class=\"enlighter-default enlighter-v-standard enlighter-t-eclipse enlighter-hover enlighter-linenumbers \">\n<div class=\"enlighter\">\n<div class=\"\">\n<div><span class=\"enlighter-k5\">void<\/span> <span class=\"enlighter-m0\">anotherTask<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-k5\">void<\/span><span class=\"enlighter-text\"> * parameter<\/span><span class=\"enlighter-g1\">){<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-c0\"> \/\/ Mata a tarefa 1 se ela estiver em execu\u00e7\u00e3o<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-k1\">if<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">task1Handle != <\/span><span class=\"enlighter-e1\">NULL<\/span><span class=\"enlighter-g1\">)<\/span> <span class=\"enlighter-g1\">{<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-m0\">vTaskDelete<\/span><span class=\"enlighter-g1\">(<\/span><span class=\"enlighter-text\">task1Handle<\/span><span class=\"enlighter-g1\">)<\/span><span class=\"enlighter-text\">;<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<div class=\"\">\n<div><span class=\"enlighter-g1\">}<\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3><\/h3>\n<h3>Prioridade da tarefa<\/h3>\n<p>Ao criar tarefas, devemos dar-lhe uma prioridade. \u00c9 o quinto par\u00e2metro de <code>xTaskCreate<\/code>. As prioridades s\u00e3o importantes quando duas ou mais tarefas est\u00e3o competindo por tempo de CPU. Quando isso acontecer, o planejador executar\u00e1 primeiro a tarefa de prioridade mais alta. Faz sentido!<\/p>\n<p>No FreeRTOS, um n\u00famero de prioridade mais alta significa que uma tarefa \u00e9 mais importante. Achei isso um tanto contra-intuitivo porque para mim uma \u201cprioridade 1\u201d parece mais importante do que uma \u201cprioridade 2\u201d, mas isso sou s\u00f3 eu.<\/p>\n<div class=\"google-auto-placed ap_container\"><\/div>\n<p>Quando duas tarefas compartilham a mesma prioridade, o FreeRTOS compartilhar\u00e1 o tempo de processamento dispon\u00edvel entre elas.<\/p>\n<p>Cada tarefa pode ter uma prioridade entre 0 e 24. O limite superior \u00e9 definido por <code>configMAX_PRIORITIES<\/code> no arquivo <a href=\"https:\/\/github.com\/espressif\/arduino-esp32\/blob\/master\/tools\/sdk\/include\/freertos\/freertos\/FreeRTOSConfig.h#L174\">FreeRTOSConfig.h<\/a>.<\/p>\n<p>Eu uso isso para diferenciar as tarefas prim\u00e1rias das secund\u00e1rias. Leve meu medidor de energia para casa \u2013 a tarefa de maior prioridade \u00e9 medir a eletricidade (prioridade 3). Atualizar a exibi\u00e7\u00e3o ou sincronizar o tempo com um servidor NTP n\u00e3o \u00e9 t\u00e3o cr\u00edtico para sua funcionalidade principal (prioridade 2).<\/p>\n<div class=\"google-auto-placed ap_container\"><\/div>\n<h3><\/h3>\n<h3>Voc\u00ea n\u00e3o precisa de tarefas para realizar v\u00e1rias tarefas ao mesmo tempo<\/h3>\n<p>Apenas uma observa\u00e7\u00e3o r\u00e1pida antes de encerrar este post: voc\u00ea n\u00e3o precisa do FreeRTOS ou de um microcontrolador multicore para fazer v\u00e1rias coisas ao mesmo tempo.<\/p>\n<p>Existem muitos tutoriais online sobre como voc\u00ea pode usar <code>millis()<\/code> para realizar a mesma coisa em sua fun\u00e7\u00e3o <code>loop()<\/code>. Outra solu\u00e7\u00e3o seria usar um agendador de tarefas Arduino como o <a href=\"https:\/\/github.com\/arkhipenko\/TaskScheduler\/blob\/master\/examples\/Scheduler_example01\/Scheduler_example01.ino\">TaskScheduler<\/a>. Ele roda em qualquer placa compat\u00edvel com o Arduino, incluindo aquelas que n\u00e3o t\u00eam um processador multicore.<\/p>\n<div class=\"google-auto-placed ap_container\"><\/div>\n<p>Segue o Site completo de <a href=\"https:\/\/github.com\/arkhipenko\/TaskScheduler\">TaskSheduler<\/a> (para Arduino, Esp32, Esp8266, STM32)<\/p>\n<p>E se desejar mais informa\u00e7\u00f5es sobre FreeRTOS veja no Tutorial da Embarcados (<a href=\"https:\/\/www.embarcados.com.br\/e-books\/e-book-colecao-esp32-parte-2\/\">Link<\/a>)<\/p>\n<p>Mas isso est\u00e1 al\u00e9m do escopo deste artigo. Vou ficar com o ESP32 por enquanto!<\/p>\n<p>Feliz multitarefa!<\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Existem v\u00e1rios casos de uso para querer multitarefa em um microcontrolador. Por exemplo: voc\u00ea pode ter um microcontrolador que l\u00ea um sensor de temperatura, mostra-o em um LCD e o envia para a nuvem. Voc\u00ea pode fazer todos os tr\u00eas de forma s\u00edncrona, um ap\u00f3s o outro. Mas e se voc\u00ea estiver usando uma tela [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":17002,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[569,207,1],"tags":[],"class_list":["post-17000","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artigos","category-blog","category-sem-categoria","entry","has-media","owp-thumbs-layout-horizontal","owp-btn-normal","owp-tabs-layout-horizontal","has-no-thumbnails","has-product-nav"],"_links":{"self":[{"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/posts\/17000","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/comments?post=17000"}],"version-history":[{"count":0,"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/posts\/17000\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/media\/17002"}],"wp:attachment":[{"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/media?parent=17000"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/categories?post=17000"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/arduxop.com.br\/loja\/wp-json\/wp\/v2\/tags?post=17000"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}