Why Use Deep Sleep in the ESP32
- Lower maintenance costs by extending time between battery replacements
- Lower deployment costs by using a small solar panel, mounting bracket, battery and enclosure
The ESP32 Datasheet explains the different sleep modes available, and provides a great table explaining the power consumption of those different modes. The different sleep modes have different functions. RTC below stands for “Real Time Clock” and ULP for “Ultra Low Power.”
Active mode: The chip radio is powered on. The chip can receive, transmit, or listen.
Modem-sleep mode: The CPU is operational and the clock is configurable. The Wi-Fi/Bluetooth baseband and radio are disabled.
Light-sleep mode: The CPU is paused. The RTC memory and RTC peripherals, as well as the ULP co-processor are running. Any wake-up events (MAC host, RTC timer, or external interrupts) will wake up the chip.
Deep-sleep mode: Only the RTC memory and RTC peripherals are powered on. Wi-Fi and Bluetooth connection data are stored in the RTC memory. The ULP co-processor is functional.
Hibernation mode: The internal 8-MHz oscillator and ULP co-processor are disabled. The RTC recovery memory is powered down. Only one RTC timer on the slow clock and certain RTC GPIOs are active. The RTC timer or the RTC GPIOs can wake up the chip from the Hibernation mode.
How to Deep Sleep the ESP32
[code lang=”arduino”]#include "esp_sleep.h"
const int wakeup_time_sec = 900; // 900 seconds is 15 minutes
esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
esp_deep_sleep_start();[/code]
In the current configuration using the breakout board, the system went from using 40mA in standby mode to 6.4mA in Deep Sleep. Given the pulses to send data only last 0.5s, this system change drive the power consumption per day down by 84%. In a solar powered example, you could switch from a 3 Watt solar panel down to a 0.6 or 1 Watt solar panel.
We would expect to go far lower in power consumption in a production application where we could shut down the voltage regulator, UART controller, etc.
| No Deep Sleep | Deep Sleep | |
| Standard Current | 40mA | 6.4mA |
| Pulse Current | 100mA | 100mA |
| Pulse Duration | 500ms | 500ms |
| Duty Cycle | 0.0056% | 0.0056% |
| Watt Hours Per Day | 3.6Wh | 0.57Wh |
Send IoT Data to an MQTT Broker
In solar-powered use cases, it is often important to know the current status of your battery. If the battery reaches a low capacity threshold, you can reduce the measurement and transmission duty cycle or identify potential problems in the field. Customers have used battery measurements to have end users re-orient solar panels to the South and increase power production.
Connecting and maintaining a WiFi or cellular connection, an MQTT connection, and sending messages are power-intensive processes. By having a device make its connections, send its data, and then go to sleep, you can greatly reduce the total power consumption for your IoT solution and extend battery life.
So, for this example, we’ll check the voltage of a battery and send it to an MQTT Broker. In this example, we’ll be using the
Here’s what you’ll need:
[code lang=”arduino”]
#define LOSANT_DEVICE_ID ""
#define LOSANT_ACCESS_KEY ""
#define LOSANT_ACCESS_SECRET ""
#define EXAMPLE_ESP_WIFI_SSID ""
#define EXAMPLE_ESP_WIFI_PASS ""
[/code]
These are #defines that will be used throughout the code. The first three are your Losant Device credentials. You’ll need to create a device and an access key
[code lang=”arduino”]
void read_bat_and_publish(void *client)
{
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_GPIO35_CHANNEL, ADC_ATTEN_11db);
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_11db, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
print_char_val_type(val_type);
//build state topic
char state_topic[128];
sprintf(state_topic, "losant/%s/state", LOSANT_DEVICE_ID);
int adc_reading = adc1_get_raw(ADC1_GPIO35_CHANNEL);
ESP_LOGI(TAG, "Raw: %d", adc_reading);
// This board has voltage divider, so need to multiply by 2.
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars) * 2;
ESP_LOGI(TAG, "Voltage: %d", voltage);
cJSON *payload = cJSON_CreateObject();
cJSON *data = cJSON_AddObjectToObject(payload, "data");
cJSON_AddNumberToObject(data, "battery_voltage", voltage);
esp_mqtt_client_publish(client, state_topic, cJSON_Print(payload), 0, 0, 0);
}[/code]
This function reads the battery voltage, multiples it by two (since the Huzzah32 has a voltage divider built in), and publishes the value
[code lang=”arduino”]
void app_main(void)
{
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
// start wifi
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
wifi_init_sta();
esp_mqtt_client_handle_t client = mqtt_app_start();
if (client) {
read_bat_and_publish(client);
vTaskDelay(pdMS_TO_TICKS(5000)); // wait 5 seconds
// disconnect from MQTT client
esp_mqtt_client_disconnect(client);
vTaskDelay(pdMS_TO_TICKS(5000)); // wait 5 seconds
}
const int wakeup_time_sec = 900; // 900 seconds = 15 minutes
ESP_LOGI(TAG, "Enabling timer wakeup, %ds\n", wakeup_time_sec);
esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
ESP_LOGI(TAG, "Entering deep sleep\n");
esp_deep_sleep_start();
}[/code]
In this main function, we are outputting some information about the device we are using, and then setting the log levels.
Next we start WiFi, then start the MQTT connection, and then call the function to read the battery voltage and publishing the value to an MQTT topic.
Finally we set the length for how long we want the Huzzah32 to sleep, and then go to sleep with

Leave a Reply