12 de abril de 2021

Do bit Ao Byte

Embarcados, Linux e programação

Como implementar deep sleep no ESP32

deep sleep no esp32 | botão de wakeup

Se chegou a esse artigo por outro meio que não “4 modos de sleep com ESP32”, recomendo a leitura antes de seguir com essa implementação. De repente, outro modo de sleep pode ser mais adequado para sua implementação do que o deep sleep no ESP32; desabilitar somente o RF, desabilitar parcialmente os recursos periféricos, utilizar determinado gatilho para levantar do sleep etc. Se já veio direto do artigo supracitado ou se já conhece os outros métodos, então boa leitura!

Como implementar deep sleep

Se não leu o artigo recomendado acima, talvez seja necessário esclarecer algumas coisas. Uma delas é que em deep sleep não temos interrupções periféricas externas, como um botão, para levantar a MCU. Quando usamos deep sleep, fazemos uso do RTC interno do ESP32, que mantém apenas os recursos necessários e suficientes para retomar a CPU.

Quando voltamos de um deep sleep, todo o fluxo do programa é reiniciado. Dados que estejam nos FIFOs da UART serão perdidos e nenhum valor de variável é armazenado, portanto, se precisar guardar algum valor, declare uma variável para a memória lenta do RTC e guarde nela o valor:

RTC_DATA_ATTR static int boot_count = 0;

Essa variável deve ser colocada no início do seu código, antes da função setup() ou antes de main(), se não estiver usando a API do Arduino.

Se estiver utilizando a API do Arduino, pode imprimir essa variável ao final da função setup(). Isso significa que ao acordar do deep sleep, todo o processo de boot é executado novamente; reconexão WiFi, reconfiguração de serviços, declaração de variáveis etc.

Colocando ao final de setup:

void setup(){
    Serial.begin(9600);
    ...
    Serial.printf("Numero de boots: %d\n", boot_count); //"printf" somente no ESP
}

Na função loop(), coloque esse código ao terminar todas as demais rotinas:

void loop(){
    //...suas rotinas, então...
    delay(5000);
    const int deep_sleep_sec = 60;
    ESP_LOGI(TAG, "Entering deep sleep for %d seconds", deep_sleep_sec);
    esp_deep_sleep(1000000LL * deep_sleep_sec);
}

Deixei 5 segundos aqui porque a única tarefa que eu tinha era uma conexão ao broker MQTT. Como fiz uma task, o processo é assíncrono e não dava tempo de fazer a conexão antes de entrar em deep sleep. Isso é uma coisa que deve ser considerada; você deve garantir que suas rotinas consigam concluir suas execuções antes de entrar em deep sleep para que não haja perda de dados.

Após a pausa (que simplesmente aguarda pela conexão ao broker), defini 60 segundos de deep sleep e iniciei o processo. A saída na serial fica assim:

deep sleep no ESP32

A sujeira na serial é por causa do boot, nada demais.

E esse é todo o código necessário para fazer deep sleep. Dê uma conferida em todos os modos de sleep no ESP32 para ao menos conhecê-los, caso já não conheça todos.

Essa é a documentação oficial da Espressif, caso queira consultar algo mais que já não esteja disposto na série de artigos sobre deep sleep.

Revisão: Ricardo Amaral de Andrade