Saltar al contenido principal

Modos de suspensión de XIAO ESP32S3 Sense

Aquí presentaré algunos ejemplos sencillos 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 utilizando en este contexto es la XIAO ESP32S3 Sense.

Descripción general del hardware

Seeed Studio XIAO ESP32S3 Sense

Deep-Sleep

Introducción

En el modo Deep-Sleep, el ESP32 apaga las CPU, la mayor parte de la RAM y todos los periféricos digitales sincronizados desde APB_CLK. Los únicos componentes que permanecen alimentados son:

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

Periférico USB deshabilitado durante Deep Sleep: Todos los periféricos digitales, incluido el periférico USB interno (USB-Serial-JTAG), se apagarán durante el Deep Sleep. La salida serie por USB no estará disponible mientras el dispositivo esté en Deep Sleep. Si necesitas depurar, utiliza un chip USB-UART externo conectado a los pines UART de hardware.

Métodos de activación

  • Activación por temporizador: El ESP32 puede despertarse automáticamente después de un tiempo especificado configurando un temporizador.

  • Activación por interrupción del panel táctil: El dispositivo puede despertarse mediante actividad en el panel táctil, adecuado para aplicaciones que requieren interacción del usuario.

  • Activación externa: El ESP32 puede despertarse mediante señales externas (por ejemplo, pulsaciones de botones), ideal para aplicaciones de bajo consumo.

  • Activación por actividad del coprocesador ULP: El coprocesador ULP puede funcionar de forma independiente, supervisando condiciones específicas y despertando la CPU principal para ahorrar energía.

  • Activación por GPIO: El dispositivo puede despertarse 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 sencillos del uso del modo DeepSleep con XIAO ESP32 S3 Sense.

Implementació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 suspensión, en este caso, 5 segundos.
RTC_DATA_ATTR int bootCount = 0;
  • Declara una variable entera bootCount con el atributo RTC_DATA_ATTR, lo que le permite conservar su valor durante el deep sleep.
void print_wakeup_reason() {
  • Define una función llamada print_wakeup_reason() que imprimirá la razón por la que se despertó el ESP32.
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 activación.
wakeup_reason = esp_sleep_get_wakeup_cause();
  • Llama a la función esp_sleep_get_wakeup_cause() para obtener la razón de la activación y asignarla 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 activación indica que el ESP32 se despertó debido a una señal externa detectada en un pin GPIO configurado para E/S RTC (Real-Time Clock). Normalmente se utiliza para la activación desde suspensión cuando se pulsa un botón o se dispara un sensor.
  • ESP_SLEEP_WAKEUP_EXT1 : Esto indica que la activación fue causada 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 cambia de estado (por ejemplo, pasa a bajo o a alto).
  • ESP_SLEEP_WAKEUP_TIMER : Esta razón de activación significa que el ESP32 se despertó después de una duración de temporizador predefinida. 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 del panel táctil. Si un panel táctil configurado para activación detecta un toque, puede sacar al dispositivo del modo de suspensión.
  • ESP_SLEEP_WAKEUP_ULP : Esta razón de activación significa que la activación fue desencadenada por un programa ULP (Ultra-Low Power). Los ULP pueden ejecutarse mientras la CPU principal está en deep sleep y pueden despertar el ESP32 cuando se cumplen ciertas condiciones, lo que permite un funcionamiento de bajo consumo con un drenaje mínimo de la batería.
++bootCount;
  • Incrementa el contador de arranque y lo imprime cada vez que el dispositivo se reinicia.
print_wakeup_reason();
  • Imprime la razón de la activación 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();Asegúrate de que todos los datos serie se envíen antes de entrar en suspensión.
  • esp_deep_sleep_start();Pone el ESP32 en modo deep sleep.
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 pulsa el botón de reinicio para reiniciar el ESP32.

Resultados mostrados

Light-Sleep

Introducción

El modo Light Sleep es otro modo de bajo consumo en el ESP32 que permite al dispositivo ahorrar 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, lo que permite que el dispositivo se despierte rápidamente en respuesta a ciertos eventos.

Light Sleep es ideal para aplicaciones que requieren bajo consumo de energía pero que 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.

aviso

Periférico USB deshabilitado durante Light Sleep: El periférico USB interno (USB-Serial-JTAG) se deshabilitará durante Light Sleep para ahorrar energía. Esto significa que la salida Serial por USB no estará disponible mientras el dispositivo esté en Light Sleep. Si estás utilizando el puerto USB para ver los registros Serial, no verás ninguna salida durante el período de sueño. Para depurar, considera usar un chip USB-UART externo conectado a los pines UART de hardware, o utiliza el despertar por GPIO para monitorizar la salida después de que el dispositivo se despierte.

Métodos de despertar

  • Despertar por temporizador: El dispositivo puede despertarse después de un período de tiempo especificado, lo que permite ejecutar tareas periódicas.
  • Despertar por interrupción externa: El ESP32 puede despertarse mediante 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, lo que permite una comunicación eficiente sin estar constantemente en un estado activo.
  • Despertar por GPIO: Pines GPIO específicos pueden configurarse para despertar el dispositivo desde Light Sleep cuando ocurre un evento, como un cambio de estado o de señal.

Implementació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 la biblioteca FreeRTOS
const int sleepTime = 10000; 
const int ledPin = LED_BUILTIN;
  • Establecer el tiempo de suspensión en 10 segundos
  • Usar el pin LED integrado
void ledTask(void *pvParameters): 
  • Definir una tarea 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);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 mostrados

Modem-Sleep

Introducción

El modo Modem Sleep es otro modo de bajo consumo importante en el 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 un estado de suspensión, mientras que los núcleos de la CPU permanecen activos. Esto permite que el ESP32 mantenga cierto nivel de conectividad inalámbrica mientras reduce significativamente el consumo de energía.

Métodos de activación

  • Activación por temporizador

  • Activación por interrupción externa

  • Activación por tarea

  • Activación por actividad de red

Implementació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"
  • Incluir la biblioteca WiFi para habilitar las funciones WiFi.
Serial.println("Connecting to WiFi...");
  • Imprimir un mensaje indicando que se está iniciando la conexión a WiFi.
WiFi.begin("****", "****");
  • Comenzar a conectarse a la red WiFi especificada.
    while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
  • Repetir hasta conectarse correctamente a WiFi.
WiFi.setSleep(true);
  • Habilitar el modo modem sleep para ahorrar energía.
WiFi.setSleep(false);
  • Deshabilitar el modo modem sleep para activar el WiFi.
if (WiFi.status() == WL_CONNECTED) {
  • Comprobar el estado de WiFi.
WiFi.setSleep(true);
  • Habilitar de nuevo el modo modem sleep.

Resultados mostrados

Aplicación de la función de suspensión

Con el sencillo ejemplo anterior, ahora demos un paso más y utilicemos estas funciones de suspensión en el sensor ESP32 S3 Sense.

Preparación de software

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

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

  • Micrphone Use: Aprende cómo usar el micrófono en el XIAO ESP32S3 Sense para capturar niveles de sonido ambiental y grabar audio.

  • MicroSD: Entiende cómo usar una tarjeta MicroSD para el almacenamiento de datos, asegurando que puedas guardar y recuperar archivos en tus proyectos.

  • Camera Use: Domina cómo usar el módulo de cámara en el XIAO ESP32S3 Sense para tomar fotos y grabar videos.

Implementació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 comprueba 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 deep sleep durante 10 segundos después de guardar para ahorrar energía.

tip

Estos códigos no se pueden usar directamente, necesitas añadir el archivo de cabecera relacionado con la cámara; por favor, consulta 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 en las que la duración de la batería es crucial, como nodos de sensores remotos, dispositivos wearables y otros dispositivos IoT de bajo consumo. Aunque el tiempo de activación es relativamente lento, esta compensación vale la pena.

Por qué usar el modo Modem Sleep

optimizar el consumo de energía del módulo de comunicación inalámbrica, manteniendo al mismo tiempo la conectividad de red. Escenarios adecuados: aplicaciones que necesitan mantener la conexión de red pero también requieren bajo consumo de energía, como dispositivos IoT que funcionan de forma intermitente. Modem Sleep puede reducir significativamente el consumo de energía del módulo inalámbrico y, al mismo tiempo, proporcionar una respuesta de activación rápida.

En resumen

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

Soporte técnico y debate sobre productos

Gracias por elegir nuestros productos. Estamos aquí para ofrecerte diferentes tipos de soporte y garantizar que tu experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para adaptarnos a diferentes preferencias y necesidades.

Loading Comments...