20 de janeiro de 2022

Do bit Ao Byte

Embarcados, Linux e programação

Botão de wakeup com ESP32

deep sleep no esp32 | botão de wakeup

Se está acompanhando a abrangente série sobre sleep modes com ESP32, já deve ter visto que temos a possibilidade de usar gatilhos externos para tirar o ESP32 de um dos sleep modes, chamado “external wakeup”, que pode ser ext0 ou ext1. Vamos aos detalhes agora sobre a adição de um botão de wakeup com ESP32.

Wakeup do deep sleep

Vamos fazer algo muito semelhante ao deep sleep temporizado, tendo como principal mudança a chamada do deep sleep e a indicação do botão de wakeup. Mas não pode ser qualquer botão; tem que ser um dos botões relacionados ao RTC do ESP32, sendo 0, 2, 4, 12-15, 25-27, 32-39. Outros não funcionarão. Aqui usei o GPIO 27 para o botão. Fiz o define no início do código, então chamei a função esp_sleep_enable_ext0_wakeup() com os respectivos parâmetros, dentro da função setup(). Na função loop() executa-se o que precisa ser executado em sua aplicação, então entra-se em deep sleep. Isso pode ser feito fora do loop, em uma task que se mantenha executando ou em setup(), ou outra função que seja executada antes de loop().

Adicionalmente, vamos incluir uma função que mostra a razão do wakeup, assim teremos um código um pouco mais elaborado. Deve ter reparado que estou limitando os artigos relacionados à mais limpa informação possível, para não haver confusão e ficar fácil de pesquisar.

O botão foi conectado no GPIO 27 e GND. No código ficou assim:

#include "esp_sleep.h"

#define BUTTON GPIO_NUM_27 //Botão de pulso
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ ESP32_DEFAULT_CPU_FREQ_80

//se precisar guardar algum valor, tem que ser na memória do RTC
RTC_DATA_ATTR static int boot_count = 0;

//razão do wakeup
void print_wakeup_reason(){
    esp_sleep_wakeup_cause_t wakeup_reason;

    wakeup_reason = esp_sleep_get_wakeup_cause();

    switch(wakeup_reason)
    {
      case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
      case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
      case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
      case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad");   break;
      case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program");   break;
      default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
    }
}

void setup(){
    Serial.begin(9600);
    gpio_set_direction(BUTTON, GPIO_MODE_INPUT);
    //(está sendo usado para outro proposito tb)
    
    //Contagem de boots. sempre que volta, recomeça
    Serial.printf("Numero de boots: %d\n", boot_count);
    print_wakeup_reason();

    //conecta o pino 27 ao RTC
    esp_sleep_enable_ext0_wakeup(BUTTON, HIGH);
    
}

void loop(){
    ++boot_count;
    uint32_t ram = ESP.getFreeHeap(); //pega uso de memória
    Serial.printf("RAM: %d, Boot num: %d\n",ram, boot_count);
    esp_deep_sleep_start();
}

Por si só esse código já comprova o deep sleep, senão a função loop deveria ficar continuamente imprimindo o valor da RAM. Como está, apenas veremos uma mensagem ao ativar o gatilho:

botão de wakeup - saída serial

A sujeira disposta na mensagem é da inicialização do ESP32. Ela precede a inicialização do WiFi, que está em setup(). Cada vez que voltamos do deep sleep, todo o processo é reiniciado, a variável boot_count é incrementada e seu valor é guardado na memória do RTC, graças à declaração RTC_DATA_ATTR static int boot_count = 0;.

A cada retorno do deep sleep também estamos chamando a função que trata a causa do wakeup. Quando for pelo botão, teremos a mensagem advinda da função print_wakeup_reason() para gatilhos na ext0.

Artigos relacionados

Esse artigo “não” foi sobre deep sleep especificamente, mas sobre o uso de botão de wakeup, que faz com que a chamada do deep sleep seja diferente. Caso não tenha acompanhando os demais artigos, em todos eles trago alguma informação especial relacionada ao tema e, caso esse artigo lhe tenha despertado interesse, aproveite para ver os demais.

E ainda teremos ao menos mais 1 artigo importante relacionado, para que você possa fazer a melhor implementação em seu projeto sem que haja dúvidas da escolha.

Além dos materiais escritos em português, caso queira referências mais específicas (sem código de exemplo, mas boa teoria), tem a documentação oficial da Espressif.

Revisão: Ricardo Amaral de Andrade