Pular para o conteúdo principal

Modos de Sono do XIAO ESP32S3 Sense

Aqui, apresentarei alguns exemplos simples para demonstrar o uso desses modos de sono de baixo consumo. Todas as placas ESP32 são versáteis, e a placa de desenvolvimento que estou usando neste contexto é a XIAO ESP32S3 Sense.

Visão Geral do Hardware

Seeed Studio XIAO ESP32S3 Sense

Sono Profundo (Deep-Sleep)

Introdução

No modo Deep-Sleep, o ESP32 desliga as CPUs, a maior parte da RAM e todos os periféricos digitais temporizados a partir do APB_CLK. Os únicos componentes que permanecem ligados são:

  • Controlador RTC
  • Coprocessador ULP
  • Memória RTC FAST
  • Memória RTC SLOW

Métodos de Despertar

  • **Timer Wake-up:**O ESP32 pode acordar automaticamente após um tempo especificado configurando um temporizador.

  • **Touchpad Interrupt Wake-up:**O dispositivo pode ser despertado por atividade no touchpad, adequado para aplicações que exigem interação do usuário.

  • **External Wake-up:**O ESP32 pode ser acordado por sinais externos (por exemplo, pressionamento de botão), ideal para aplicações de baixo consumo.

  • **ULP Coprocessor Activity Wake-up:**O coprocessador ULP pode operar de forma independente, monitorando condições específicas e acordando a CPU principal para economizar energia.

  • **GPIO Wake-up:**O dispositivo pode ser despertado por mudanças nos estados dos pinos GPIO (alto ou baixo), oferecendo flexibilidade para vários sensores e periféricos.

Três exemplos simples do XIAO ESP32 S3 Sense usando o modo DeepSleep são apresentados abaixo.

Implementação do Código


#define uS_TO_S_FACTOR 1000000ULL
#define TIME_TO_SLEEP 5

RTC_DATA_ATTR int bootCount = 0;

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(115200);
delay(1000);


++bootCount;
Serial.println("Boot number: " + String(bootCount));


print_wakeup_reason();


esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");

Serial.println("Going to sleep now");
Serial.flush();
esp_deep_sleep_start();
Serial.println("This will never be printed");
}

void loop() {

}

Notas Detalhadas

#define uS_TO_S_FACTOR 1000000ULL 
  • Defina uma macro para converter microssegundos em segundos. 1000000ULL é o fator usado para converter microssegundos em segundos.
#define TIME_TO_SLEEP  5     
  • Defina uma macro que define o tempo pelo qual o ESP32 ficará em modo de sono, neste caso, 5 segundos.
RTC_DATA_ATTR int bootCount = 0;
  • Declare uma variável inteira bootCount com o atributo RTC_DATA_ATTR, que permite que ela mantenha seu valor durante o sono profundo.
void print_wakeup_reason() {
  • Defina uma função chamada print_wakeup_reason() que irá imprimir o motivo pelo qual o ESP32 acordou.
esp_sleep_wakeup_cause_t wakeup_reason;
  • Declare uma variável wakeup_reason do tipo esp_sleep_wakeup_cause_t para armazenar a causa do evento de despertar.
wakeup_reason = esp_sleep_get_wakeup_cause();
  • Chame a função esp_sleep_get_wakeup_cause() para obter o motivo do despertar e atribuí-lo à variável wakeup_reason.
  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;
}
  • ESP_SLEEP_WAKEUP_EXT0 : Este motivo de despertar indica que o ESP32 acordou devido a um sinal externo detectado em um pino GPIO configurado para I/O de RTC (Relógio em Tempo Real). Isso é normalmente usado para despertar do sono quando um botão ou sensor é acionado.
  • ESP_SLEEP_WAKEUP_EXT1 : Isso indica que o despertar foi causado por um sinal externo em pinos GPIO gerenciados pelo controlador RTC. Diferente do EXT0, o EXT1 pode lidar com múltiplos pinos e pode acordar quando qualquer um dos pinos especificados mudar de estado (por exemplo, ir para nível baixo ou alto).
  • ESP_SLEEP_WAKEUP_TIMER : Este motivo de despertar significa que o ESP32 acordou após uma duração de temporizador predefinida. Isso é útil para aplicações que precisam executar tarefas periódicas sem exigir interação do usuário.
  • ESP_SLEEP_WAKEUP_TOUCHPAD : Isso indica que o ESP32 acordou devido a um evento no touchpad. Se um touchpad configurado para despertar detectar um toque, ele pode trazer o dispositivo para fora do modo de sono.
  • ESP_SLEEP_WAKEUP_ULP : Este motivo de despertar significa que o despertar foi acionado por um programa ULP (Ultra-Low Power). Programas ULP podem ser executados enquanto a CPU principal está em sono profundo e podem acordar o ESP32 quando certas condições são atendidas, permitindo operação de baixo consumo com drenagem mínima da bateria.
++bootCount;
  • Incremente a contagem de inicializações e imprima-a sempre que o dispositivo reiniciar.
print_wakeup_reason();
  • Imprima o motivo do despertar do ESP32.
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");

Serial.println("Going to sleep now");
Serial.flush();
esp_deep_sleep_start();
Serial.println("This will never be printed");
  • esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);Habilite o temporizador para acordar o ESP32 após um tempo especificado.
  • Serial.flush();Garanta que todos os dados seriais sejam enviados antes de entrar em modo de sono.
  • esp_deep_sleep_start();Coloque o ESP32 em modo de sono profundo.
dica

Para regravar o programa após entrar no modo de sono profundo, mantenha pressionado o botão de boot e depois pressione o botão de reset para reiniciar o ESP32.

Exibição dos Resultados

Light-Sleep

Introdução

O modo Light Sleep é outro modo de baixo consumo de energia no ESP32 que permite ao dispositivo economizar energia enquanto ainda mantém um tempo de resposta rápido. Nesse modo, os núcleos da CPU são interrompidos, mas a RAM e alguns periféricos permanecem energizados, permitindo que o dispositivo acorde rapidamente em resposta a certos eventos.

O Light Sleep é ideal para aplicações que exigem baixo consumo de energia, mas que ainda precisam manter uma conexão com WiFi ou Bluetooth, pois permite que os módulos de comunicação sem fio permaneçam ativos.

Métodos de Wake-up

  • Wake-up por Timer: O dispositivo pode acordar após um período de tempo especificado, permitindo a execução de tarefas periódicas.
  • Wake-up por Interrupção Externa: O ESP32 pode ser acordado por sinais externos, como pressionamento de botões ou outras interrupções de hardware.
  • Wake-up por Atividade de Rede: O dispositivo pode acordar em resposta a pacotes de rede recebidos, permitindo comunicação eficiente sem estar constantemente em estado ativo.
  • Wake-up por GPIO: Pinos GPIO específicos podem ser configurados para acordar o dispositivo do Light Sleep quando um evento ocorre, como uma mudança de estado ou de sinal.

Implementação de Código

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

const int sleepTime = 10000;
const int ledPin = LED_BUILTIN;

void ledTask(void *pvParameters) {
digitalWrite(ledPin, HIGH);
Serial.println("LED is ON");
vTaskDelay(pdMS_TO_TICKS(1000));
digitalWrite(ledPin, LOW);
Serial.println("LED is OFF");

vTaskDelete(NULL);
}

void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
Serial.println("Setup complete. Going to sleep...");
}

void loop() {
esp_sleep_enable_timer_wakeup(sleepTime * 1000);
Serial.println("Going to sleep now...");
esp_light_sleep_start();

xTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);

delay(1000);
}

Notas Detalhadas

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
  • Incldue FreeRTOS library
const int sleepTime = 10000; 
const int ledPin = LED_BUILTIN;
  • Definir o tempo de sono para 10 segundos
  • Usar o pino do LED embutido
void ledTask(void *pvParameters): 
  • Defina uma tarefa FreeRTOS para controlar o estado do LED.
digitalWrite(ledPin, HIGH); 
Serial.println("LED is ON");
vTaskDelay(pdMS_TO_TICKS(1000));
digitalWrite(ledPin, LOW);
Serial.println("LED is OFF");
vTaskDelete(NULL);
  • vTaskDelay(pdMS_TO_TICKS(1000));Keep the LED on for 1 second
  • vTaskDelete(NULL);Delete the current task
esp_sleep_enable_timer_wakeup(sleepTime * 1000);
Serial.println("Going to sleep now...");
esp_light_sleep_start();
xTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);
delay(1000);
  • esp_sleep_enable_timer_wakeup(sleepTime * 1000);Set timer for wakeup
  • esp_light_sleep_start(); Enter light sleep mode
  • xTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);Create LED control task

Resultados

Modem-Sleep

Introdução

O modo Modem Sleep é outro modo importante de baixo consumo de energia no ESP32, que é diferente do modo Deep Sleep. O modo Modem Sleep é otimizado principalmente para o módulo de comunicação sem fio do ESP32.

Nesse modo, o módulo WiFi/Bluetooth do ESP32 entra em estado de suspensão, enquanto os núcleos da CPU permanecem ativos. Isso permite que o ESP32 mantenha um certo nível de conectividade sem fio enquanto reduz significativamente o consumo de energia.

Métodos de Despertar

  • Despertar por temporizador

  • Despertar por interrupção externa

  • Despertar por tarefa

  • Despertar por atividade de rede

Implementação do Código

#include "WiFi.h"

void setup() {
Serial.begin(115200);
Serial.println("Connecting to WiFi...");

WiFi.begin("****", "****");

while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");

WiFi.setSleep(true);
Serial.println("Modem-Sleep enabled.");
}

void loop() {

Serial.println("Running...");

delay(5000);

WiFi.setSleep(false);
Serial.println("Modem-Sleep disabled. WiFi is active.");

if (WiFi.status() == WL_CONNECTED) {
Serial.println("Still connected to WiFi.");
} else {
Serial.println("WiFi disconnected.");
}

delay(5000);
WiFi.setSleep(true);
Serial.println("Modem-Sleep enabled.");
}

Notas Detalhadas

#include "WiFi.h"
  • Inclua a biblioteca WiFi para habilitar as funções de WiFi.
Serial.println("Connecting to WiFi...");
  • Imprima uma mensagem indicando que a conexão ao WiFi está começando.
WiFi.begin("****", "****");
  • Inicie a conexão à rede WiFi especificada.
    while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
  • Faça o loop até conectar-se ao WiFi com sucesso.
WiFi.setSleep(true);
  • Ative o modo modem sleep para economizar energia.
WiFi.setSleep(false);
  • Desative o modo modem sleep para ativar o WiFi.
if (WiFi.status() == WL_CONNECTED) {
  • Verifique o status do WiFi.
WiFi.setSleep(true);
  • Ative novamente o modo modem sleep.

Resultados

Aplicação da Função de Suspensão

Com o simples exemplo acima, vamos agora dar um passo adiante e usar esses recursos de suspensão no sensor ESP32 S3 Sense.

Preparação de Software

Antes de começar este artigo, certifique-se de que você concluiu algumas preparações de instalação de software caso ainda não tenha utilizado todos os recursos de hardware no XIAO ESP32S3 Sense.

Aqui estão introduções a três funcionalidades, e você pode encontrar mais informações através dos seguintes links:

  • Micrphone Use: Aprenda como usar o microfone no XIAO ESP32S3 Sense para capturar níveis de som ambiente e gravar áudio.

  • MicroSD: Entenda como usar um cartão MicroSD para armazenamento de dados, garantindo que você possa salvar e recuperar arquivos em seus projetos.

  • Camera Use: Domine como usar o módulo de câmera no XIAO ESP32S3 Sense para tirar fotos e gravar vídeos.

Implementação do Código

#include "esp_camera.h"
#include "FS.h"
#include "SD.h"
#include "SPI.h"

#define CAMERA_MODEL_XIAO_ESP32S3

#include "camera_pins.h"

unsigned long lastCaptureTime = 0;
int imageCount = 1;
bool camera_sign = false;
bool sd_sign = false;


void photo_save(const char * fileName) {
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Failed to get camera frame buffer");
return;
}
writeFile(SD, fileName, fb->buf, fb->len);

esp_camera_fb_return(fb);

Serial.println("Photo saved to file");
}

void writeFile(fs::FS &fs, const char * path, uint8_t * data, size_t len){
Serial.printf("Writing file: %s\r\n", path);

File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
if (file.write(data, len) == len) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}

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

camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;

esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}

camera_sign = true;

if (!SD.begin(21)) {
Serial.println("Card Mount Failed");
return;
}

uint8_t cardType = SD.cardType();

if (cardType == CARD_NONE) {
Serial.println("No SD card attached");
return;
}

Serial.print("SD Card Type: ");
if (cardType == CARD_MMC) {
Serial.println("MMC");
} else if (cardType == CARD_SD) {
Serial.println("SDSC");
} else if (cardType == CARD_SDHC) {
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}

sd_sign = true;

Serial.println("Photos will begin shortly, please be ready.");
}

void loop() {
if (camera_sign && sd_sign) {
unsigned long now = millis();

if ((now - lastCaptureTime) >= 60000) {
char filename[32];
sprintf(filename, "/image%d.jpg", imageCount);
photo_save(filename);
Serial.printf("Saved picture: %s\r\n", filename);
Serial.println("Entering deep sleep for 10 seconds...");

esp_sleep_enable_timer_wakeup(10000000);
esp_deep_sleep_start();

}
}
}

Notas Detalhadas

Este código implementa um sistema de captura de imagens baseado no módulo de câmera do ESP32, que pode tirar automaticamente uma foto a cada 60 segundos e salvá-la no cartão SD. Na função void setup(), a câmera e o cartão SD são inicializados e o status do dispositivo é confirmado; na função void loop(), verifica-se se a câmera pode tirar uma foto e, se a condição for atendida, a função photo_save() é chamada para salvar a imagem e, após o salvamento, o dispositivo entra em um estado de deep sleep por 10 segundos para economizar energia.

dica

Esses códigos não podem ser usados diretamente, você precisa adicionar o arquivo de cabeçalho da câmera, por favor verifique o exemplo acima sobre o XIAO ESP32 S3.

Para concluir

Por que usar o modo Deep Sleep

maximizar a economia de energia sem comprometer a funcionalidade, a fim de estender a vida útil da bateria do dispositivo. Cenários adequados: Aplicações em que a duração da bateria é crucial, como nós de sensores remotos, dispositivos vestíveis e outros dispositivos IoT de baixo consumo. Embora o tempo de despertar seja relativamente lento, essa compensação vale a pena.

Por que usar o modo Modem Sleep

otimizar o consumo de energia do módulo de comunicação sem fio, mantendo ainda assim a conectividade de rede. Cenários adequados: Aplicações que precisam manter a conexão de rede, mas também exigem baixo consumo de energia, como dispositivos IoT que operam intermitentemente. O Modem Sleep pode reduzir significativamente o consumo de energia do módulo sem fio, ao mesmo tempo em que fornece uma resposta de despertar rápida.

Em resumo

esses três modos de suspensão oferecem aos desenvolvedores diferentes opções de compromisso entre energia e desempenho, que podem ser escolhidas de forma flexível com base nos requisitos específicos da aplicação. Para dispositivos com requisitos de duração de bateria, o modo Deep Sleep é uma boa escolha; e para dispositivos IoT que precisam manter conectividade de rede, o modo Modem Sleep é a escolha ideal.

Suporte Técnico & Discussão de Produto

Obrigado por escolher nossos produtos! Estamos aqui para lhe fornecer diferentes tipos de suporte para garantir que sua experiência com nossos produtos seja a mais tranquila possível. Oferecemos vários canais de comunicação para atender a diferentes preferências e necessidades.

Loading Comments...