Skip to main content

XIAO ESP32S3 Sense Sleep Modes

Here, I will present some simple examples to demonstrate the use of these low-power sleep modes. All ESP32 boards are versatile, and the development board I am using in this context is the XIAO ESP32S3 Sense.

Hadware Oview

Seeed Studio XIAO ESP32S3 Sense

Deep-Sleep

Introduction

In Deep-Sleep mode, the ESP32 powers off the CPUs, most of the RAM, and all digital peripherals clocked from APB_CLK. The only components that remain powered are:

  • RTC controller
  • ULP coprocessor
  • RTC FAST memory
  • RTC SLOW memory

Wake-up Methods

  • Timer Wake-up:The ESP32 can wake up automatically after a specified time by setting a timer.

  • Touchpad Interrupt Wake-up:The device can be awakened by activity on the touchpad, suitable for applications requiring user interaction.

  • External Wake-up:The ESP32 can be woken up by external signals (e.g., button presses), ideal for low-power applications.

  • ULP Coprocessor Activity Wake-up:The ULP coprocessor can operate independently, monitoring specific conditions and waking up the main CPU to save power.

  • GPIO Wake-up:The device can be awakened by changes in the GPIO pin states (high or low), providing flexibility for various sensors and peripherals.

Three simple examples of XIAO ESP32 S3 Sense using DeepSleep mode are given below.

Code realization


#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() {

}

Detailed Notes

#define uS_TO_S_FACTOR 1000000ULL 
  • Define a macro to convert microseconds to seconds. 1000000ULL is the factor used to convert microseconds to seconds.
#define TIME_TO_SLEEP  5     
  • Define a macro that sets the time for which the ESP32 will go to sleep, in this case, 5 seconds.
RTC_DATA_ATTR int bootCount = 0;
  • Declare an integer variable bootCount with the attribute RTC_DATA_ATTR, which allows it to retain its value during deep sleep.
void print_wakeup_reason() {
  • Define a function named print_wakeup_reason() that will print the reason the ESP32 woke up.
esp_sleep_wakeup_cause_t wakeup_reason;
  • Declare a variable wakeup_reason of type esp_sleep_wakeup_cause_t to store the cause of the wakeup event.
wakeup_reason = esp_sleep_get_wakeup_cause();
  • Call the function esp_sleep_get_wakeup_cause() to retrieve the reason for the wakeup and assign it to the wakeup_reason variable.
  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 : This wakeup reason indicates that the ESP32 woke up due to an external signal detected on a GPIO pin configured for RTC (Real-Time Clock) I/O. This is typically used for wakeup from sleep when a button or sensor is triggered.
  • ESP_SLEEP_WAKEUP_EXT1 : This indicates that the wakeup was caused by an external signal on GPIO pins managed by the RTC controller. Unlike EXT0, EXT1 can handle multiple pins and can wake up when any of the specified pins change state (e.g., go low or high).
  • ESP_SLEEP_WAKEUP_TIMER : This wakeup reason signifies that the ESP32 woke up after a predefined timer duration. This is useful for applications that need to perform periodic tasks without requiring user interaction.
  • ESP_SLEEP_WAKEUP_TOUCHPAD : This indicates that the ESP32 woke up due to a touchpad event. If a touchpad configured for wakeup detects a touch, it can bring the device out of sleep mode.
  • ESP_SLEEP_WAKEUP_ULP : This wakeup reason means that the wakeup was triggered by a ULP (Ultra-Low Power) program. ULPs can run while the main CPU is in deep sleep and can wake the ESP32 when certain conditions are met, allowing for low-power operation with minimal battery drain.
++bootCount;
  • Increment the boot count and print it every time the device reboots.
print_wakeup_reason();
  • Print the reason for the ESP32's wakeup.
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);Enable the timer to wake up the ESP32 after a specified time.
  • Serial.flush();Ensure all serial data is sent before going to sleep.
  • esp_deep_sleep_start();Put the ESP32 into deep sleep mode.
tip

To re-burn the program after entering deep sleep mode, hold down the boot button and then press the reset button to reboot the ESP32.

Results Show

Light-Sleep

Introduction

Light Sleep mode is another low-power mode in the ESP32 that allows the device to conserve energy while still maintaining a quick response time. In this mode, the CPU cores are halted, but the RAM and some peripherals remain powered on, allowing the device to wake up quickly in response to certain events.

Light Sleep is ideal for applications that require low power consumption but still need to maintain a connection to WiFi or Bluetooth, as it allows the wireless communication modules to remain active.

Wake-up Methods

  • Timer Wake-up: The device can wake up after a specified time period, allowing for periodic tasks to be executed.
  • External Interrupt Wake-up: The ESP32 can be woken up by external signals, such as button presses or other hardware interrupts.
  • Network Activity Wake-up: The device can wake up in response to incoming network packets, enabling efficient communication without constantly being in an active state.
  • GPIO Wake-up: Specific GPIO pins can be configured to wake the device from Light Sleep when an event occurs, such as a change in state or signal.

Code Realization

#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);
}

Detailed Notes

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
  • Incldue FreeRTOS library
const int sleepTime = 10000; 
const int ledPin = LED_BUILTIN;
  • Set sleep time to 10 seconds
  • Use the built-in LED pin
void ledTask(void *pvParameters): 
  • Define a FreeRTOS task to control the LED state.
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

Results Show

Modem-Sleep

Introduction

Modem Sleep mode is another important low-power mode in ESP32, which is different from the Deep Sleep mode. Modem Sleep mode is primarily optimized for the wireless communication module of the ESP32.

In this mode, the WiFi/Bluetooth module of the ESP32 enters a sleep state, while the CPU cores remain active. This allows the ESP32 to maintain a certain level of wireless connectivity while significantly reducing the power consumption.

Wake-up Methods

  • Timer Wake-up

  • External Interrupt Wake-up

  • Task Wake-up

  • Network Activity Wake-up

Code Realization

#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.");
}

Detailed Notes

#include "WiFi.h"
  • Include the WiFi library to enable WiFi functions.
Serial.println("Connecting to WiFi...");
  • Print a message indicating that the connection to WiFi is starting.
WiFi.begin("****", "****");
  • Start connecting to the specified WiFi network.
    while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
  • Loop until successfully connected to WiFi.
WiFi.setSleep(true);
  • Enable modem sleep mode to save power.
WiFi.setSleep(false);
  • Disable modem sleep mode to activate WiFi.
if (WiFi.status() == WL_CONNECTED) {
  • Check the WiFi status.
WiFi.setSleep(true);
  • Enable modem sleep mode again.

Results Show

Sleep Function Application

With the above simple example, let's now take it a step further and use these sleep features on the ESP32 S3 Sense sensor.

Softare Preparetion

Before starting this article, please ensure you have completed some software installation preparations if you haven't yet utilized all the hardware features on the XIAO ESP32S3 Sense.

Here are introductions to three functionalities, and you can find more information through the following links:

  • Micrphone Use: Learn how to use the microphone on the XIAO ESP32S3 Sense to capture ambient sound levels and record audio.

  • MicroSD: Understand how to use a MicroSD card for data storage, ensuring you can save and retrieve files in your projects.

  • Camera Use: Master how to use the camera module on the XIAO ESP32S3 Sense to take photos and record videos.

Code Realization

#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();

}
}
}

Detailed Notes

This code implements an image capture system based on the ESP32 camera module, which can automatically take a photo every 60 seconds and save it to the SD card. In the void setup() function, the camera and SD card are initialized and the device status is confirmed; in the void loop() function, the camera is checked to see if it can take a picture, and if the condition is met, the photo_save() function is called to save the image and enter a deep sleep state for 10 seconds after saving to save energy.

tip

These codes can not be used directly, you need to add the header file about the camera, please check the above example about XIAO ESP32 S3.

To conclude

Why use Deep Sleep mode

maximize power savings without compromising functionality, in order to extend the battery life of the device. Suitable scenarios: Applications where battery life is crucial, such as remote sensor nodes, wearable devices, and other low-power IoT devices. Although the wakeup time is relatively slow, this trade-off is worthwhile.

Why use Modem Sleep mode

optimize the power consumption of the wireless communication module, while still maintaining network connectivity. Suitable scenarios: Applications that need to maintain network connection but also require low power, such as intermittently working IoT devices. Modem Sleep can significantly reduce the power consumption of the wireless module while still providing fast wakeup response.

In summary

these three sleep modes provide developers with different power/performance trade-off options that can be flexibly chosen based on the specific requirements of the application. For devices with battery life requirements, Deep Sleep mode is a good choice; and for IoT devices that need to maintain network connectivity, Modem Sleep mode is the optimal choice.

Tech Support & Product Discussion

Thank you for choosing our products! We are here to provide you with different support to ensure that your experience with our products is as smooth as possible. We offer several communication channels to cater to different preferences and needs.

Loading Comments...