Skip to main content

XIAO ESP32S3 Sense Modos de Suspensión

Aquí, presentaré algunos ejemplos simples para demostrar el uso de estos modos de suspensión de bajo consumo. Todas las placas ESP32 son versátiles, y la placa de desarrollo que estoy usando en este contexto es el XIAO ESP32S3 Sense.

Descripción del Hardware

Seeed Studio XIAO ESP32S3 Sense

Sueño Profundo

Introducción

En el modo de Sueño Profundo, el ESP32 apaga las CPUs, la mayor parte de la RAM y todos los periféricos digitales sincronizados desde APB_CLK. Los únicos componentes que permanecen encendidos son:

  • Controlador RTC
  • Coprocesador ULP
  • Memoria RTC FAST
  • Memoria RTC SLOW

Métodos de Despertar

  • **Despertar por Temporizador:**El ESP32 puede despertar automáticamente después de un tiempo especificado configurando un temporizador.

  • **Despertar por Interrupción de Panel Táctil:**El dispositivo puede ser despertado por actividad en el panel táctil, adecuado para aplicaciones que requieren interacción del usuario.

  • **Despertar Externo:**El ESP32 puede ser despertado por señales externas (por ejemplo, pulsaciones de botones), ideal para aplicaciones de bajo consumo.

  • **Despertar por Actividad del Coprocesador ULP:**El coprocesador ULP puede operar independientemente, monitoreando condiciones específicas y despertando la CPU principal para ahorrar energía.

  • **Despertar por GPIO:**El dispositivo puede ser despertado por cambios en los estados de los pines GPIO (alto o bajo), proporcionando flexibilidad para varios sensores y periféricos.

A continuación se presentan tres ejemplos simples del XIAO ESP32 S3 Sense usando el modo DeepSleep.

Realización del 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 Detalladas

#define uS_TO_S_FACTOR 1000000ULL 
  • Define una macro para convertir microsegundos a segundos. 1000000ULL es el factor utilizado para convertir microsegundos a segundos.
#define TIME_TO_SLEEP  5     
  • Define una macro que establece el tiempo durante el cual el ESP32 entrará en modo de suspensión, en este caso, 5 segundos.
RTC_DATA_ATTR int bootCount = 0;
  • Declara una variable entera bootCount con el atributo RTC_DATA_ATTR, que le permite retener su valor durante el sueño profundo.
void print_wakeup_reason() {
  • Define una función llamada print_wakeup_reason() que imprimirá la razón por la cual el ESP32 se despertó.
esp_sleep_wakeup_cause_t wakeup_reason;
  • Declara una variable wakeup_reason de tipo esp_sleep_wakeup_cause_t para almacenar la causa del evento de despertar.
wakeup_reason = esp_sleep_get_wakeup_cause();
  • Llama a la función esp_sleep_get_wakeup_cause() para obtener la razón del despertar y asígnala a la variable 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 : Esta razón de despertar indica que el ESP32 se despertó debido a una señal externa detectada en un pin GPIO configurado para E/S RTC (Reloj de Tiempo Real). Esto se usa típicamente para despertar del sueño cuando se activa un botón o sensor.
  • ESP_SLEEP_WAKEUP_EXT1 : Esto indica que el despertar fue causado por una señal externa en pines GPIO gestionados por el controlador RTC. A diferencia de EXT0, EXT1 puede manejar múltiples pines y puede despertar cuando cualquiera de los pines especificados cambie de estado (por ejemplo, vaya a bajo o alto).
  • ESP_SLEEP_WAKEUP_TIMER : Esta razón de despertar significa que el ESP32 se despertó después de una duración de temporizador predefinida. Esto es útil para aplicaciones que necesitan realizar tareas periódicas sin requerir interacción del usuario.
  • ESP_SLEEP_WAKEUP_TOUCHPAD : Esto indica que el ESP32 se despertó debido a un evento de touchpad. Si un touchpad configurado para despertar detecta un toque, puede sacar al dispositivo del modo de sueño.
  • ESP_SLEEP_WAKEUP_ULP : Esta razón de despertar significa que el despertar fue activado por un programa ULP (Ultra-Bajo Consumo). Los ULP pueden ejecutarse mientras la CPU principal está en sueño profundo y pueden despertar el ESP32 cuando se cumplen ciertas condiciones, permitiendo operación de bajo consumo con drenaje mínimo de batería.
++bootCount;
  • Increment the boot count and print it every time the device reboots.
print_wakeup_reason();
  • Imprime la razón del despertar del 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);Habilita el temporizador para despertar el ESP32 después de un tiempo especificado.
  • Serial.flush();Asegura que todos los datos serie se envíen antes de entrar en modo de suspensión.
  • esp_deep_sleep_start();Pone el ESP32 en modo de suspensión profunda.
tip

Para volver a grabar el programa después de entrar en modo de sueño profundo, mantén presionado el botón de arranque y luego presiona el botón de reinicio para reiniciar el ESP32.

Mostrar Resultados

Sueño Ligero

Introducción

El modo de Sueño Ligero es otro modo de bajo consumo en el ESP32 que permite al dispositivo conservar energía mientras mantiene un tiempo de respuesta rápido. En este modo, los núcleos de la CPU se detienen, pero la RAM y algunos periféricos permanecen encendidos, permitiendo que el dispositivo se despierte rápidamente en respuesta a ciertos eventos.

El Sueño Ligero es ideal para aplicaciones que requieren bajo consumo de energía pero aún necesitan mantener una conexión a WiFi o Bluetooth, ya que permite que los módulos de comunicación inalámbrica permanezcan activos.

Métodos de Despertar

  • Despertar por Temporizador: El dispositivo puede despertarse después de un período de tiempo especificado, permitiendo que se ejecuten tareas periódicas.
  • Despertar por Interrupción Externa: El ESP32 puede ser despertado por señales externas, como pulsaciones de botones u otras interrupciones de hardware.
  • Despertar por Actividad de Red: El dispositivo puede despertarse en respuesta a paquetes de red entrantes, habilitando comunicación eficiente sin estar constantemente en un estado activo.
  • Despertar por GPIO: Pines GPIO específicos pueden ser configurados para despertar el dispositivo del Sueño Ligero cuando ocurre un evento, como un cambio de estado o señal.

Realización del 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 Detalladas

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
  • Incluir biblioteca FreeRTOS
const int sleepTime = 10000; 
const int ledPin = LED_BUILTIN;
  • Establecer el tiempo de suspensión a 10 segundos
  • Usar el pin LED incorporado
void ledTask(void *pvParameters): 
  • Define una tarea de FreeRTOS para controlar el estado del 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);Configurar temporizador para despertar
  • esp_light_sleep_start(); Entrar en modo de sueño ligero
  • xTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);Crear tarea de control LED

Mostrar Resultados

Modem-Sleep

Introducción

El modo Modem Sleep es otro modo de bajo consumo importante en ESP32, que es diferente del modo Deep Sleep. El modo Modem Sleep está optimizado principalmente para el módulo de comunicación inalámbrica del ESP32.

En este modo, el módulo WiFi/Bluetooth del ESP32 entra en estado de sueño, mientras que los núcleos de CPU permanecen activos. Esto permite al ESP32 mantener un cierto nivel de conectividad inalámbrica mientras reduce significativamente el consumo de energía.

Métodos de Despertar

  • Despertar por Temporizador

  • Despertar por Interrupción Externa

  • Despertar por Tarea

  • Despertar por Actividad de Red

Realización del 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 Detalladas

#include "WiFi.h"
  • Incluye la biblioteca WiFi para habilitar las funciones WiFi.
Serial.println("Connecting to WiFi...");
  • Imprime un mensaje indicando que la conexión a WiFi está iniciando.
WiFi.begin("****", "****");
  • Comienza la conexión a la red WiFi especificada.
    while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
  • Bucle hasta conectarse exitosamente al WiFi.
WiFi.setSleep(true);
  • Habilita el modo de suspensión del módem para ahorrar energía.
WiFi.setSleep(false);
  • Desactiva el modo de suspensión del módem para activar WiFi.
if (WiFi.status() == WL_CONNECTED) {
  • Verificar el estado del WiFi.
WiFi.setSleep(true);
  • Habilitar nuevamente el modo de suspensión del módem.

Mostrar Resultados

Aplicación de la Función de Suspensión

Con el ejemplo simple anterior, ahora vamos a dar un paso más y usar estas características de suspensión en el sensor ESP32 S3 Sense.

Preparación de Software

Antes de comenzar este artículo, asegúrese de haber completado algunas preparaciones de instalación de software si aún no ha utilizado todas las características de hardware en el XIAO ESP32S3 Sense.

Aquí hay introducciones a tres funcionalidades, y puede encontrar más información a través de los siguientes enlaces:

  • Uso del Micrófono: Aprenda cómo usar el micrófono en el XIAO ESP32S3 Sense para capturar niveles de sonido ambiental y grabar audio.

  • MicroSD: Comprenda cómo usar una tarjeta MicroSD para almacenamiento de datos, asegurándose de que pueda guardar y recuperar archivos en sus proyectos.

  • Uso de la Cámara: Domine cómo usar el módulo de cámara en el XIAO ESP32S3 Sense para tomar fotos y grabar videos.

Realización del 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 Detalladas

Este código implementa un sistema de captura de imágenes basado en el módulo de cámara ESP32, que puede tomar automáticamente una foto cada 60 segundos y guardarla en la tarjeta SD. En la función void setup(), se inicializan la cámara y la tarjeta SD y se confirma el estado del dispositivo; en la función void loop(), se verifica si la cámara puede tomar una foto, y si se cumple la condición, se llama a la función photo_save() para guardar la imagen y entrar en un estado de sueño profundo durante 10 segundos después de guardar para ahorrar energía.

tip

Estos códigos no pueden usarse directamente, necesitas añadir el archivo de cabecera sobre la cámara, por favor revisa el ejemplo anterior sobre XIAO ESP32 S3.

Para concluir

Por qué usar el modo Deep Sleep

maximizar el ahorro de energía sin comprometer la funcionalidad, con el fin de extender la vida útil de la batería del dispositivo. Escenarios adecuados: Aplicaciones donde la vida útil de la batería es crucial, como nodos de sensores remotos, dispositivos portátiles y otros dispositivos IoT de bajo consumo. Aunque el tiempo de activación es relativamente lento, este compromiso vale la pena.

Por qué usar el modo Modem Sleep

optimizar el consumo de energía del módulo de comunicación inalámbrica, mientras se mantiene la conectividad de red. Escenarios adecuados: Aplicaciones que necesitan mantener conexión de red pero también requieren bajo consumo, como dispositivos IoT que funcionan intermitentemente. Modem Sleep puede reducir significativamente el consumo de energía del módulo inalámbrico mientras proporciona una respuesta de activación rápida.

En resumen

estos tres modos de suspensión proporcionan a los desarrolladores diferentes opciones de compromiso entre energía/rendimiento que pueden elegirse flexiblemente según los requisitos específicos de la aplicación. Para dispositivos con requisitos de vida útil de batería, el modo Deep Sleep es una buena opción; y para dispositivos IoT que necesitan mantener conectividad de red, el modo Modem Sleep es la opción óptima.

Soporte Técnico y Discusión de Productos

¡Gracias por elegir nuestros productos! Estamos aquí para proporcionarte diferentes tipos de soporte para asegurar que tu experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para atender diferentes preferencias y necesidades.

Loading Comments...