Manual

do

Maker

.

com

Desafio maker 05: resposta - TaskHandle

Desafio maker 05: resposta - TaskHandle

Esse foi sem sombra de dúvidas o desafio mais fácil até agora. Quem usa task, provavelmente precisou em algum momento usar um TaskHandle para interagir com o processamento paralelo. Se não leu o Desafio Maker 05, dê uma lida  rapidinho pelo menos pra saber qual era o tema.

TaskHandle

Normalmente passamos NULL como parâmetro do manipulador, ao criar uma task. Se feito desse modo, não há como controlar a task "externamente" ao processo assíncrono da thread. Porém o TaskHandle nos dá alguns controle sobre as tasks, como pausar, retomar e excluir, além de pegar seu status.

Como o desafio propõe o controle sem aferir qual task está em execução através do status das threads, como saber para qual das 4 tasks enviar o suspend? Simples (mas dispendioso); criar um array com os manipuladores e incrementar um indexador e cada passagem de task.

Veja uma task declarada:

void task1(void *pvParameters){
  vTaskDelay(pdMS_TO_TICKS(10000)); //aqui seria solenoide do leite
  xTaskCreatePinnedToCore(task2,"task2",10000,NULL,0,&tasks[1],0);
  idx+=1;
  vTaskDelete(NULL);
}

Usei o delay para representar o processamento da task, mas obviamente deveria ser a função millis() em um caso de uso real, tal qual exemplifico na função loop(), mas adiante.

Quando a task termina seu trabalho, ela inicia o próximo processo, incrementa o indexador que é referência para manipulação da task e então se exclui.

Repare que a task1 usa o idx 0, e assim sucessivamente. Quando a task4 termina seu trabalho, coloca o idx em 0 novamente antes de se excluir.

Na função loop() eu usei a serial invés de botão, porque estou com preguiça de fazer solda e wiring, mas quem está lendo esse artigo já deve estar muuuuito habituado com GPIO e digitalRead(). Então, se for recebido 0, utiliza-se vTaskSuspend(tasks[idx]), onde tasks é um array com os TaskHandleidx é o indexador da tarefa. Desse modo, não precisamos verificar o status de cada uma das tasks antes de suspendê-la, basta apontar diretamente para seu manipulador conforme o idx. O código do desafio ficou assim:

#include <Wire.h>
#include <WiFi.h>

TaskHandle_t t_task1;
TaskHandle_t t_task2;
TaskHandle_t t_task3;
TaskHandle_t t_task4;

TaskHandle_t tasks[4] = {t_task1,t_task2,t_task3,t_task4};

unsigned char idx   = 0;
unsigned char onOff = 1;
unsigned long int timeout = millis();

void task1(void *pvParameters){
  vTaskDelay(pdMS_TO_TICKS(10000)); //aqui seria solenoide do leite
  xTaskCreatePinnedToCore(task2,"task2",10000,NULL,0,&tasks[1],0);
  idx+=1;
  vTaskDelete(NULL);
}

void task2(void *pvParameters){
  vTaskDelay(pdMS_TO_TICKS(12000)); //aqui seria solenoide do leite
  xTaskCreatePinnedToCore(task3,"task3",10000,NULL,0,&tasks[2],0);
  idx+=1;
  vTaskDelete(NULL);
}

void task3(void *pvParameters){
  vTaskDelay(pdMS_TO_TICKS(30000)); //aqui seria solenoide do leite
  xTaskCreatePinnedToCore(task4,"task4",10000,NULL,0,&tasks[3],0);
  idx+=1;
  vTaskDelete(NULL);
}

void task4(void *pvParameters){
  vTaskDelay(pdMS_TO_TICKS(30000)); //aqui seria solenoide do leite
  xTaskCreatePinnedToCore(task1,"task1",10000,NULL,0,&tasks[0],0);
  idx=0;
  vTaskDelete(NULL);
}

void setup() {
    Serial.begin(115200);

    while (!Serial);

    xTaskCreatePinnedToCore(task1,"task1",10000,NULL,0,&tasks[0],0);

}

void loop() {
  if (Serial.available()){
    onOff = Serial.read()-48;a
    if (onOff == 1){
      if (eTaskGetState(&tasks[idx]) == 0){
        vTaskResume(tasks[idx]);
      }
    }
    else{
      vTaskSuspend(tasks[idx]);
      Serial.println("1");
    }
    Serial.print("resposta: ");
    Serial.println(onOff);
  }
  
  if ((millis()-timeout) > 1000){
    timeout = millis();
    if (onOff == 1){
      Serial.println(idx);
    }
  }

}

Dá pra fazer com Arduino se usar RTOS, apesar do desempenho ser bastante ruim.

Se precisar de mais referências (e tiver habilidade com inglês), a documentação oficial do ESP32 é bastante auxiliadora. Aliás, foi de lá que estudei e aprendi a usar o ESP32.

E aí? Conseguiu resolver? Gostou do resultado?

Até o próximo desafio!

Inscreva-se no nosso canal Manual do Maker no YouTube.

Também estamos no Instagram.

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.