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 de hardware

Seeed Studio XIAO ESP32S3 Sense

Deep-Sleep

Introdução

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

  • Controlador RTC
  • Coprocessador ULP
  • Memória RTC FAST
  • Memória RTC SLOW
atenção

Periférico USB desativado durante o Deep Sleep: Todos os periféricos digitais, incluindo o periférico USB interno (USB-Serial-JTAG), serão desligados durante o Deep Sleep. A saída serial via USB não estará disponível enquanto o dispositivo estiver em Deep Sleep. Se você precisar depurar, use um chip USB-UART externo conectado aos pinos UART de hardware.

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ões), 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 deep sleep.
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 (Real-Time Clock). 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 vários pinos e pode acordar quando qualquer um dos pinos especificados muda de estado (por exemplo, vai 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 tirar o dispositivo 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 deep sleep 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 a imprima toda vez 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 deep sleep.
dica

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

Exibição de 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 ligados, 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 ainda precisam manter uma conexão com WiFi ou Bluetooth, pois permite que os módulos de comunicação sem fio permaneçam ativos.

atenção

Periférico USB desativado durante o Light Sleep: O periférico USB interno (USB-Serial-JTAG) será desativado durante o Light Sleep para economia de energia. Isso significa que a saída Serial via USB não estará disponível enquanto o dispositivo estiver em Light Sleep. Se você estiver usando a porta USB para visualizar logs Serial, não verá nenhuma saída durante o período de sono. Para depurar, considere usar um chip USB-UART externo conectado aos pinos UART de hardware ou use wake-up por GPIO para monitorar a saída após o dispositivo acordar.

Métodos de despertar

  • Despertar por temporizador: O dispositivo pode acordar após um período de tempo especificado, permitindo a execução de tarefas periódicas.
  • Despertar por interrupção externa: O ESP32 pode ser acordado por sinais externos, como pressionamento de botões ou outras interrupções de hardware.
  • Despertar 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.
  • Despertar por GPIO: Pinos GPIO específicos podem ser configurados para acordar o dispositivo do Light Sleep quando um evento ocorrer, como uma mudança de estado ou sinal.

Implementação do 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>
  • Incluir a biblioteca FreeRTOS
const int sleepTime = 10000; 
const int ledPin = LED_BUILTIN;
  • Definir o tempo de sono para 10 segundos
  • Usar o pino de LED integrado
void ledTask(void *pvParameters): 
  • Definir 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));Manter o LED aceso por 1 segundo
  • vTaskDelete(NULL);Excluir a tarefa atual
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);Definir o temporizador para o despertar
  • esp_light_sleep_start(); Entrar no modo de sono leve
  • xTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);Criar tarefa de controle do LED

Exibição dos resultados

Modem-Sleep

Introdução

O modo Modem Sleep é outro modo de baixo consumo importante 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 sono, enquanto os núcleos da CPU permanecem ativos. Isso permite que o ESP32 mantenha um certo nível de conectividade sem fio, reduzindo 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"
  • Incluir a biblioteca WiFi para habilitar as funções de WiFi.
Serial.println("Connecting to WiFi...");
  • Imprimir uma mensagem indicando que a conexão ao WiFi está iniciando.
WiFi.begin("****", "****");
  • Iniciar a conexão à rede WiFi especificada.
    while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
  • Repetir até conectar-se ao WiFi com sucesso.
WiFi.setSleep(true);
  • Habilitar o modo modem sleep para economizar energia.
WiFi.setSleep(false);
  • Desabilitar o modo modem sleep para ativar o WiFi.
if (WiFi.status() == WL_CONNECTED) {
  • Verificar o status do WiFi.
WiFi.setSleep(true);
  • Habilitar novamente o modo modem sleep.

Exibição dos resultados

Aplicação da função de sono

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

Preparação de software

Antes de iniciar 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 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(), é verificado 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 entrar em um estado de sono profundo por 10 segundos após o salvamento para economizar energia.

dica

Este código não pode ser usado 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 vida útil 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 funcionam de forma intermitente. 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

estes três modos de suspensão fornecem aos desenvolvedores diferentes opções de compromisso entre consumo de 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 vida útil de bateria, o modo Deep Sleep é uma boa escolha; e para dispositivos IoT que precisam manter a conectividade de rede, o modo Modem Sleep é a escolha ideal.

Suporte Técnico e Discussão de Produtos

Obrigado por escolher nossos produtos! Estamos aqui para oferecer 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...