Skip to content

Commit

Permalink
examples: system/deep_sleep
Browse files Browse the repository at this point in the history
1. Fix EXT0 wakeup pin error on ESP32: GPIO3 is not a RTC IO, change to use GPIO25.
2. Add ESP_ERROR_CHECK to explicitly show the runtime error
3. Improve example README
  • Loading branch information
songruo committed Nov 11, 2022
1 parent dd31138 commit 8c40017
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 28 deletions.
29 changes: 21 additions & 8 deletions examples/system/deep_sleep/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,36 @@

(See the README.md file in the upper level 'examples' directory for more information about examples.)

The [deep sleep mode](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#sleep-modes) of the ESP32 is a power saving mode that causes the CPU, majority of RAM, and digital peripherals that are clocked from APB_CLK to be powered off. Deep sleep mode can be exited using one of multiple [wake up sources](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#wakeup-sources). This example demonstrates how to use the [`esp_sleep.h`](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#api-reference) API to enter deep sleep mode, then wake up form different sources.
The [deep sleep mode](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#sleep-modes) is a power saving mode that causes the CPU, majority of RAM, and digital peripherals that are clocked from APB_CLK to be powered off. Deep sleep mode can be exited using one of multiple [wake up sources](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#wakeup-sources). This example demonstrates how to use the [`esp_sleep.h`](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#api-reference) API to enter deep sleep mode, then wake up form different sources.

The following wake up sources are demonstrated in this example (refer to the [Wakeup Sources documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#wakeup-sources) for more details regarding wake up sources):

1. **Timer:** An RTC timer that can be programmed to trigger a wake up after a preset time. This example will trigger a wake up every 20 seconds.
2. **EXT1:** External wake up 1 which is tied to multiple RTC GPIOs. This example use GPIO2 and GPIO4 to trigger a wake up with any one of the two pins are HIGH.
3. **Touch:** Touch pad sensor interrupt. This example uses touch pads connected to GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2 to trigger a wake up when any of the pads are pressed.
4. **ULP:** Ultra Low Power Coprocessor which can continue to run during deep sleep. This example utilizes the ULP and constantly sample the chip's temperature and trigger a wake up if the chips temperature exceeds ~5 degrees Celsius.
- **Timer:** An RTC timer that can be programmed to trigger a wake up after a preset time. This example will trigger a wake up every 20 seconds.
- **EXT0:** External wake up 0 can trigger wakeup when one predefined RTC GPIO is at a predefined logic level. This example uses GPIO25 in ESP32 or GPIO3 in ESP32-S2/S3 to trigger a wake up when the pin is HIGH. (This wake up source is only available on ESP32, ESP32-S2, and ESP32-S3.)
- **EXT1:** External wake up 1 which is tied to multiple RTC GPIOs. This example uses GPIO2 and GPIO4 to trigger a wake up with any one of the two pins are HIGH. (This wake up source is only available on ESP32, ESP32-S2, and ESP32-S3.)
- **GPIO:** Pads powered by VDD3P3_RTC can be used to trigger a wake up from deep sleep. You may choose the pin and trigger level in menuconfig. (This wake up source is unavailable on ESP32, ESP32-S2, and ESP32-S3.)
- **Touch:** Touch pad sensor interrupt. This example uses touch pads connected to GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2/S3 to trigger a wake up when any of the pads are pressed.
- **ULP:** Ultra Low Power Coprocessor which can continue to run during deep sleep. This example utilizes the ULP and constantly sample the chip's temperature and trigger a wake up if the chips temperature exceeds ~5 degrees Celsius.

Note: Some wake up sources can be disabled via configuration (see section on [project configuration](#Configure-the-project))

Warning: On ESP32, touch wake up source cannot be used together with EXT0 or ULP wake up source. If they co-exist, IDF will give a runtime error and the program will crash. By default in this example, touch wake up is enabled, and the other two are disabled. You can switch to enable the other wake up sources via menuconfig.

In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot.

## How to use example

### Hardware Required

This example should be able to run on any commonly available ESP32 development board without any extra hardware if only **Timer** and **ULP** wake up sources are used. However, the following extra connections will be required for the remaining wake up sources.
This example should be able to run on any commonly available ESP32 series development board without any extra hardware if only **Timer** and **ULP** wake up sources are used. However, the following extra connections will be required for the remaining wake up sources.

- **EXT0:** Connect GPIO25 in ESP32 or GPIO3 in ESP32-S2/S3 to HIGH to trigger a wake up.

- **EXT1:** GPIO2 and GPIO4 should be connected to LOW to avoid floating pins. When triggering a wake up, connect one or both of the pins to HIGH. Note that floating pins may trigger a wake up.

- **Touch:** GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2 should be connected to touch sensors (see [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.0/documents/touch_pad_solution/touch_sensor_design_en.md)).
- **GPIO:** If `EXAMPLE_GPIO_WAKEUP_HIGH_LEVEL` is selected in menuconfig, then connect `EXAMPLE_GPIO_WAKEUP_PIN` to HIGH to trigger a wake up; Otherwise, connect `EXAMPLE_GPIO_WAKEUP_PIN` to LOW to trigger a wake up.

- **Touch:** GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2/S3 should be connected to touch sensors (see [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.0/documents/touch_pad_solution/touch_sensor_design_en.md)).

### Configure the project

Expand All @@ -35,7 +43,12 @@ idf.py menuconfig
```

* **Touch wake up** can be enabled/disabled via `Example configuration > Enable touch wake up`
* **ULT wake up** can be enabled/disabled via `Example configuration > Enable temperature monitoring by ULP`
* **EXT0 wake up** can be enabled/disabled via `Example configuration > Enable wakeup from GPIO (ext0)`
* **EXT1 wake up** can be enabled/disabled via `Example configuration > Enable wakeup from GPIO (ext1)`
* **GPIO wake up** can be enabled/disabled via `Example configuration > Enable wakeup from GPIO`
Trigger pin can be chosen via `Example configuration > GPIO wakeup configuration > Enable wakeup from GPIO`
Trigger level can be selected via `Example configuration > GPIO wakeup configuration > Enable GPIO high-level wakeup`
* **ULP wake up** can be enabled/disabled via `Example configuration > Enable temperature monitoring by ULP`

Wake up sources that are unused or unconnected should be disabled in configuration to prevent inadvertent triggering of wake up as a result of floating pins.

Expand Down
22 changes: 14 additions & 8 deletions examples/system/deep_sleep/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@ menu "Example Configuration"
default y
depends on SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP
help
This option enables wake up from deep sleep using touch pads
TOUCH8 and TOUCH9, which correspond to GPIO33 and GPIO32.
This option enables wake up from deep sleep using touch pads.
ESP32 - TOUCH8 and TOUCH9, which correspond to GPIO33 and GPIO32.
ESP32S2/S3 - TOUCH9, which corresponds to GPIO9.

Note: On ESP32, touch wakeup source can not be used together with ext0 wakeup source.

config EXAMPLE_EXT0_WAKEUP
bool "Enable wakeup from GPIO (ext0)"
default y
depends on !SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
default y if !IDF_TARGET_ESP32
default n if IDF_TARGET_ESP32
depends on SOC_PM_SUPPORT_EXT_WAKEUP
help
This option enables wake up from deep sleep from GPIO3. They should be connected to LOW to avoid
floating pins. When triggering a wake up, connect one or both of the pins to HIGH. Note that floating
pins may trigger a wake up.
This option enables wake up from deep sleep from GPIO25(ESP32)/GPIO3(ESP32S2,S3). The pin should be
connected to LOW to avoid being in a floating state. When triggering a wake up, connect the pin to HIGH.
Note that floating pins may trigger a wake up.

Note: On ESP32, ext0 wakeup source can not be used together with touch wakeup source.

config EXAMPLE_EXT1_WAKEUP
bool "Enable wakeup from GPIO (ext1)"
default y
depends on !SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
depends on SOC_PM_SUPPORT_EXT_WAKEUP
help
This option enables wake up from deep sleep from GPIO2 and GPIO4. They should be connected to LOW to avoid
floating pins. When triggering a wake up, connect one or both of the pins to HIGH. Note that floating
Expand Down
28 changes: 16 additions & 12 deletions examples/system/deep_sleep/main/deep_sleep_example_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,23 @@ void app_main(void)

const int wakeup_time_sec = 20;
printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));

#if CONFIG_EXAMPLE_EXT0_WAKEUP
#if CONFIG_IDF_TARGET_ESP32
const int ext_wakeup_pin_0 = 25;
#else
const int ext_wakeup_pin_0 = 3;
#endif

printf("Enabling EXT0 wakeup on pin GPIO%d\n", ext_wakeup_pin_0);
esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 1);
ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 1));

// Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep.
// EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs.
// No need to keep that power domain explicitly, unlike EXT1.
rtc_gpio_pullup_dis(ext_wakeup_pin_0);
rtc_gpio_pulldown_en(ext_wakeup_pin_0);
ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_0));
ESP_ERROR_CHECK(rtc_gpio_pulldown_en(ext_wakeup_pin_0));
#endif // CONFIG_EXAMPLE_EXT0_WAKEUP
#ifdef CONFIG_EXAMPLE_EXT1_WAKEUP
const int ext_wakeup_pin_1 = 2;
Expand All @@ -122,17 +126,17 @@ void app_main(void)
const uint64_t ext_wakeup_pin_2_mask = 1ULL << ext_wakeup_pin_2;

printf("Enabling EXT1 wakeup on pins GPIO%d, GPIO%d\n", ext_wakeup_pin_1, ext_wakeup_pin_2);
esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask, ESP_EXT1_WAKEUP_ANY_HIGH);
ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask, ESP_EXT1_WAKEUP_ANY_HIGH));

/* If there are no external pull-up/downs, tie wakeup pins to inactive level with internal pull-up/downs via RTC IO
* during deepsleep. However, RTC IO relies on the RTC_PERIPH power domain. Keeping this power domain on will
* increase some power comsumption. */
# if CONFIG_EXAMPLE_EXT1_USE_INTERNAL_PULLUPS
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
rtc_gpio_pullup_dis(ext_wakeup_pin_1);
rtc_gpio_pulldown_en(ext_wakeup_pin_1);
rtc_gpio_pullup_dis(ext_wakeup_pin_2);
rtc_gpio_pulldown_en(ext_wakeup_pin_2);
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_1));
ESP_ERROR_CHECK(rtc_gpio_pulldown_en(ext_wakeup_pin_1));
ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_2));
ESP_ERROR_CHECK(rtc_gpio_pulldown_en(ext_wakeup_pin_2));
# endif //CONFIG_EXAMPLE_EXT1_USE_INTERNAL_PULLUPS
#endif // CONFIG_EXAMPLE_EXT1_WAKEUP

Expand Down Expand Up @@ -207,8 +211,8 @@ void app_main(void)
TOUCH_PAD_NUM9, touch_value, (uint32_t)(touch_value * 0.1));
#endif
printf("Enabling touch pad wakeup\n");
esp_sleep_enable_touchpad_wakeup();
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
ESP_ERROR_CHECK(esp_sleep_enable_touchpad_wakeup());
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
#endif // CONFIG_EXAMPLE_TOUCH_WAKEUP

#if CONFIG_IDF_TARGET_ESP32
Expand Down

0 comments on commit 8c40017

Please sign in to comment.