24 de agosto de 2019

Watchdog Timer - ESP32

Um sistema de Watchdog é responsável por reiniciar o circuito caso ocorra travamentos.
Vamos ver como configurá-lo no ESP32.


Na postagem Watchdog Timer - Reset Automático do Circuito foi detalhado melhor como funciona um watchdog e, utilizamos um Arduino.

Nesse exemplo veremos como utilizar no ESP32.

A biblioteca do watchdog para o ESP32 é a <esp_task_wdt.h>.

As principais chamadas para seu funcionamento são:

esp_task_wdt_init(struct de configuração);
Essa função inicializa o watchdog passando a variável do tipo struct com as configurações. O timeout_ms, que deve ser informado em milissegundos e é do tipo inteiro. O idle_core_mask com o valor do núcleo e o trigger_panic para acionar a reinicialização.

esp_task_wtd_add(tarefa);
Essa função adiciona uma tarefa ao watchdog. Para a tarefa atual devemos passar o parâmetro NULL.

esp_task_wdt_reset();
Essa é a função responsável por resetar o cronômetro do watchdog, não permitindo que o timeout seja atingido.

O exemplo abaixo foi configurado um watchdog com timeout de 4 segundos.

Através do monitor serial é possível acompanhar o funcionamento.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*---------------------------------------------------------
  Programa : WATCHDOG TIMER - ESP32
  Autor    : Fellipe Couto [ http://www.efeitonerd.com.br ]
  Data     : 10/07/2024
  ---------------------------------------------------------*/

#include <esp_task_wdt.h>  //Biblioteca do watchdog
#define BUTTON 0           //Porta de conexão do botão (ESP32 Dev Module o botão boot é o pino 0)

void setup() {
  //Configura a porta com pull-up interno
  pinMode(BUTTON, INPUT_PULLUP);

  //Inicia a comunicação serial e exibe a mensagem
  Serial.begin(115200);
  delay(500);
  Serial.println("\nWATCHDOG TIMER - ESP32");
  Serial.println("Mantenha o botao pressionado por mais de 4 segundos para o reiniciar o circuito.\n");

  //Habilita o watchdog configurando o timeout para 4 segundos
  esp_task_wdt_config_t wdt_config = {
    .timeout_ms = 4000,
    .idle_core_mask = 1,
    .trigger_panic = true
  };
  esp_task_wdt_init(&wdt_config);
  esp_task_wdt_add(NULL);
}

void loop() {
  //Variável para contagem de tempo
  int count = 0;

  //Fica preso no loop enquanto o botão estiver pressionado
  while (digitalRead(BUTTON) == LOW) {
    Serial.print("Botao pressionado... ");
    Serial.println(count);
    count++;
    delay(1000);
  }

  //Reseta o temporizador do watchdog
  esp_task_wdt_reset();
}

Essa configuração é para a versão 3.x da biblioteca do ESP32 disponibilizada para IDE Arduino.

Abaixo está a configuração para a versão 2.x.

esp_task_wdt_init(tempo em segundos, verdadeiro/falso para reinicialização);
Essa função inicializa o watchdog passando dois parâmetros. O primeiro é o timeout, que deve ser informado em segundos e é do tipo inteiro. O segundo é do tipo booleano e informa se ao atingir o timeout deve ser reinicializado o circuito.

esp_task_wtd_add(tarefa);
Essa função adiciona uma tarefa ao watchdog. Para a tarefa atual devemos passar o parâmetro NULL.

esp_task_wdt_reset();
Essa é a função responsável por resetar o cronômetro do watchdog, não permitindo que o timeout seja atingido.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*---------------------------------------------------------
  Programa : WATCHDOG TIMER - ESP32
  Autor    : Fellipe Couto [ http://www.efeitonerd.com.br ]
  Data     : 24/08/2019
  ---------------------------------------------------------*/

// PARA A BIBLIOTECA ESP32 ATÉ A VERSÃO 2.x

#include <esp_task_wdt.h> //Biblioteca do watchdog
#define BUTTON 0           //Porta de conexão do botão (ESP32 Dev Module o botão boot é o pino 0)

void setup() {
  //Configura a porta com pull-up interno
  pinMode(BUTTON, INPUT_PULLUP);

  //Inicia a comunicação serial e exibe a mensagem
  Serial.begin(115200);
  Serial.println("WATCHDOG TIMER - ESP32");
  Serial.println("Mantenha o botao pressionado por mais de 4 segundos para o reiniciar o circuito.\n");

  //Habilita o watchdog configurando o timeout para 4 segundos
  esp_task_wdt_init(4, true);
  esp_task_wdt_add(NULL);
}

void loop() {
  //Variável para contagem de tempo
  int count = 1;

  //Fica preso no loop enquanto o botão estiver pressionado
  while (digitalRead(BUTTON) == LOW) {
    Serial.print("Botao pressionado... ");
    Serial.println(count);
    count++;
    delay(1000);
  }

  //Reseta o temporizador do watchdog
  esp_task_wdt_reset();
}
 
Referências:
 
Postagem atualizada em 10/07/2024.

18 comentários:

  1. Parabéns. Resolveu meu problema. DEsde ontem estou pesquisando sobre o WD e só acho matéria muito superficiais oudetalhadas a fundo, nada de prático. A sua publicação foi direta e precisa. Estou projetando um medido de energia e o ESP32 trava de vez em quando. Não reportando para a "nuvem". Agora deixar em testes. Valeu mesmo.

    ResponderExcluir
    Respostas
    1. Obrigado pelo comentário, Renilson! Fico feliz em poder ter ajudado. Abraços!

      Excluir
  2. Excelente post. Simples e direto. Parabéns !

    ResponderExcluir
  3. Bom dia, como implemento esse código numa aplicação prática? Quero dizer, um travamento real, nesse exemplo vc usou um botão para forçar o travamento, numa aplicação tenho que colocar a programação dentro do while do botão que força o travamento?

    ResponderExcluir
    Respostas
    1. Boa tarde! O Watchdog Timer trabalha partindo do princípio que sempre haverá um loop dentro sendo executado. Por isso, a cada número 'x' da tarefas vc deve restar o temporizador do Watchdog, ou a cada volta do loop, efetuar esse reset do temporizador.
      Nada mais é que um cronômetro que se configurado para 20 segundos, toda vez que ele atingir esse tempo, ele fará com que o circuito inteiro seja reiniciado.
      Por isso, a cada volta do loop, ou a cada tarefa, zeramos seu temporizador para não deixá-lo chegar ao seu tempo limite. Quando acontecer um travamento do circuito, a linha responsável por zerar o tempo não será executada e consequentemente o temporizador atingirá seu tempo limite, forçando a reinicialização do circuito.
      Watchdog Timer é muito útil para aplicações que devem permanecer ligada por muitas horas ou dias, ou aplicações que devem sempre permanecer ligadas.
      Esse é um exemplo de Watchdog via software. Existe tbm a possibilidade de um Watchdog de hardware para outros tipos de problemas.

      Excluir
  4. Nesse caso vc usou um botão para mandar nível lógico low para o pino 2, num real travamento esse pino 2 vai receber nível lógico low pelo fato dele estar como "input_pullup"?

    ResponderExcluir
    Respostas
    1. No caso do pino 2, é para somente manter o loop while em execução, não permitindo que o microcontrolador executado a função esp_task_wdt_reset(); que está abaixo do loop. Se o reset do Watchdog não for realizado antes do tempo limite dele configurado, o microcontrolador será reiniciado.

      Excluir
  5. Olá, tenho um problema, meu esp sempre da reset quando atualizo a pagina do servidor em mais de 1 cliente ao mesmo tempo, aparece o mesmo erro. Segui esse post porém continua o problema, pode me ajudar?

    ResponderExcluir
    Respostas
    1. Bom dia, Jesio Costa! Ao realizar o acesso, pode estar estouro o timeout do Watchdog. Verificou isso? Ao acessar uma página interna, o ESP entra em processamento, e pode não estar resetando o temporizador do watchdog em tempo hábil.

      Excluir
  6. Rapaz, tenho que lhe agradecer. Estou montando um sisteminha IOT em minha casa e meu ESP32 algumas vezes travava quando tentava publicar as leituras. O correto mesmo seria identificar o motivo do travamento, mas implementar o WDT aparentemente (ainda não testei por longo tempo) resolveu meu problema. Muito obrigado!

    ResponderExcluir
    Respostas
    1. Bom dia, Luis! Ótimo que a postagem tenha ajudado! Fico feliz! Bons projetos!! Abraços!

      Excluir
  7. Obrigado pelo excelente post, muito direto, simples e prático!!!

    ResponderExcluir
    Respostas
    1. Boa tarde!! Valeu! Fico feliz que a postagem tenha ajudado! Abraços!

      Excluir
  8. Usei esse modelo de implementação e me ajudou muito em meu projeto. Recentemente fui carregar em um esp32 e deu erro, parece mudança na biblioteca:
    47 | esp_err_t esp_task_wdt_init(const esp_task_wdt_config_t *config);
    | ^~~~~~~~~~~~~~~~~
    exit status 1
    invalid conversion from 'int' to 'const esp_task_wdt_config_t*' [-fpermissive]

    sabe como resolver?

    ResponderExcluir
    Respostas
    1. Boa tarde! A Espressif aplicou atualizações na biblioteca do ESP32 e alteraram os parâmetros do watchdog sem manter a versão anterior ativa. Me programei para atualizar essa postagem aqui :)
      No site da Espressif está a documentação:
      https://docs.espressif.com/projects/esp-idf/en/v5.1.3/esp32/api-reference/system/wdts.html

      Excluir