[0:00] My e-Paper weather display finally ran out of juice a few weeks ago.
[0:04] In total the 1000mAh battery lasted almost exactly two months.
[0:09] This would probably have been considerably longer if my home WiFi was a bit more robust.
[0:14] The e-Paper weather display achieves its long battery life by going into deep sleep for
[0:18] most of the time and only waking up every 30 minutes to connect to the internet and
[0:22] update the display.
[0:23] This is a pretty interesting and powerful aspect of the ESP32 and I think it deserves
[0:28] a deep dive.
[0:30] What are we going to do cover in this video?
[0:32] We’ll start off with a quick overview of how to get the ESP32 into deep sleep.
[0:37] We’ll then cover the ways that the ESP32 can be woken up.
[0:40] We can use a timer to wake up after some time.
[0:43] We can wake up using a single GPIO pin or multiple pins.
[0:47] And we can wake up using the touch sensors.
[0:50] We’ll then cover the code that is required to know why the ESP32 was woken up.
[0:55] And finally talk about how to maintain state when going into deep sleep.
[0:59] There is another way of waking the ESP32 device up which uses the Ultra Low Power co-processor,
[1:06] but this deserves a deep dive all to itself.
[1:08] So there’ll be another video coming soon where we cover that in detail.
[1:12] So don’t forget to subscribe!
[1:13] But first, a quick word from the channel sponsor PCBWay.
[1:17] They’ve been sponsoring the channel for a while and we’ve built a few PCBs with them.
[1:22] We’ll be making some more PCBs in some future videos as I want to learn a bit more about KiCad.
[1:27] They also do 3D printing and CNC work.
[1:30] Check out the link to PCBWay in the description.
[1:32] So how do we put the ESP32 into deep sleep?
[1:36] We just need a single function call - esp_deep_sleep_start.
[1:40] Just make sure you’ve setup some kind of trigger or you won’t wake up until you reset the device.
[1:46] Setting up a timer to wake up the ESP32 is very simple, we just call esp_sleep_enable_timer_wakeup
[1:53] before we go into deep sleep.
[1:55] This takes one argument which is the amount of time in microseconds that we want to sleep.
[1:59] Although this is specified in microseconds the exact resolution depends on the source
[2:04] for the RTC slow clock - which is normally only 150KHz.
[2:09] So don’t expect this to be a super accurate time delay.
[2:11] Once we’ve setup the timer, we just call esp_deep_sleep_start.
[2:15] It’s important to remember that nothing runs after this call, so don’t put any code after it.
[2:21] It’s also important to remember that before entering deep sleep you should make sure you
[2:24] put any external peripherals you are using into power saving mode or turn them off.
[2:28] You should also shutdown the WiFi and Bluetooth peripherals if you are using them.
[2:32] I’ve set this demo up to sleep for 30 seconds, I’ve set up the sketch to trigger deep sleep
[2:37] when we push the built in button.
[2:47] After 30 seconds has passed the device automatically wakes up and runs our setup function.
[2:53] The next method we’ll look at for waking up the ESP32 uses the External wakeup mode.
[2:58] This lets us wake up the device when the RTC GPIOs are in a certain state.
[3:03] Note, that not all the GPIO_PINS are wired up the RTC module.
[3:08] These are the pins that can be used to wake up the ESP32.
[3:12] There are two different options for using GPIO_PINS for wake up, we can use a single
[3:17] GPIO pin by using esp_sleep_enable_ext0_wakeup or we can use multiple pins using esp_sleep_enable_ext1_wakeup.
[3:26] You can configure pull up and pull down resistors using the rtc_gpio_pullup_en and rtc_gpio_pulldown_en
[3:34] on the pins, but I find it a bit simpler to configure the pin as you would normally and
[3:39] then use the rtc_gpio_hold_en function which will maintain the pin configuration when going
[3:46] into deep sleep.
[3:48] For esp_sleep_enable_ext0_wakeup you specify the GPIO pin that you want to monitor and
[3:54] the logic level you are triggering on.
[3:56] We can test this out using the built in button on TTGO, this button connects GPIO35 to ground
[4:02] so we need an internal pull up resistor and we want to trigger the wake up when the pin
[4:06] goes low.
[4:08] Once again we go into deep sleep.
[4:10] And then when we push the button we wake up.
[4:12] To monitor multiple GPIO pins we use the esp_sleep_enable_ext1_wakeup function.
[4:19] This lets us specify multiple GPIO pins using a bit mask.
[4:22] We can choose to wake up when any of the pins go high, or wake up when all the pins are low.
[4:29] Here I’m setting up pulldown resistors on two pins and then configuring the wakeup to
[4:33] trigger if any of the pins go high.
[4:36] We go into deep sleep and now if any of the pins go high we wake up.
[4:40] We can also work out which pin woke us up.
[4:43] This is really handy if you have multiple buttons and you want the device to respond
[4:47] in different ways depending on which button is pushed in deep sleep.
[5:02] If we want to wait for all the pins to go low then setup internal pull resistors to
[5:07] pull them high.
[5:08] And change the trigger to all low.
[5:10] Once again we enter deep sleep, now we only wake up if all the pins are taken low - one
[5:15] interesting point is that you can’t really tell which pin actually woke the device up.
[5:19] It will always tell you the lowest GPIO pin was responsible.
[5:26] The final simple thing we can do is wake up using one of the touch pins.
[5:30] There are 9 pins that can be configured to receive touch input.
[5:34] To make wakeup from touch work we need to first setup an interupt on the touch pad - the
[5:39] interrupt handler can be left empty.
[5:41] We then call the esp_sleep_enable_touchpad_wakeup before entering deep sleep.
[5:46] You can setup multiple touchpads and any touchpad that has an interrupt attached to is will
[5:50] trigger the device to wake up.
[5:52] To get a sensible value for the threshold you can experiment using the touchRead function
[5:57] to see what values you get when the pins are touched.
[6:00] Once again we go into deep sleep, and now when I touch the cable the ESP32 wakes up.
[6:12] That’s it for the simple wake modes of the ESP32 - as I said earlier we’ll cover using
[6:17] the Ultra Low Power coprocessor in a follow up video.
[6:21] As you’ve seen in the demos - I’m able to show the reason the ESP32 woke up along with
[6:25] the GPIO pins that caused the wake up - this is what makes the deep sleep mode so powerful.
[6:31] We can go to sleep and then wake up and respond to user input.
[6:35] It’s really simple to get the wake up cause, we just call esp_sleep_get_wakeup_cause, this
[6:40] will either give us:
[6:41] Undefined - which in my case I’ve treated as a normal boot up after reset or power down.
[6:47] EXT0, EXT1, TIMER, TOUCHPAD and ULP - as I said earlier we’ll cover the ULP in a later video.
[6:56] With EXT0, we know which GPIO pin causes the wake up as we can only use one GPIO pin.
[7:02] For EXT1 we can query which GPIO pins caused the wake up to happen by using esp_sleep_get_ext1_wakeup_status.
[7:11] This returns a bit mask indicating which GPIO pins caused the wakeup - but note, this is
[7:15] only useful if we are using the any pin high mode, if we are using the wake up when all
[7:20] pins are low we don’t get any usable information.
[7:23] For Touch we can call esp_sleep_get_touchpad_wakeup_status - this returns the touch pad that caused the
[7:30] device to wake up.
[7:31] This is all pretty cool, but deep sleep turns everything off, including the RAM that your
[7:35] program is using to store variables.
[7:38] Everything gets lost when you go into deep sleep mode.
[7:40] How do we solve this problem?
[7:42] Going back to our original block diagram we can see that there is some memory associated
[7:46] with the RTC module - this memory is kept alive when we go into deep sleep.
[7:51] We have 16KB of RTC memory.
[7:54] We can store data in this memory by using the RTC_DATA_ATTR flag.
[7:58] You can store basic types and even structures in this memory by using this flag.
[8:03] One thing to be aware of is that this memory will persist during deep sleep, but it won’t
[8:07] persist if power is removed or the reset button is pushed.
[8:11] If you want persistant state between power and reset cycles then you need to write your
[8:15] data to flash or some external persistent storage such as an SD card.
[8:24] How much power can we save by going into deep sleep?
[8:27] I don’t really have the right equipment for measuring low current usage, but The Guy With
[8:32] the Swiss Accent has done some really great videos measuring the deep sleep current of
[8:36] various different dev boards, I’ve linked to one of his videos in the description and
[8:40] you can get a link to his spreadsheet that shows a variety of boards along with their
[8:44] deep sleep current.
[8:45] I’ve done a quick test with my TTGO display board, I’m measuring the voltage drop over
[8:49] a 10ohm resistor so this is showing about 60 to 80mA in normal mode.
[8:54] When we drop down to deep sleep this drops to less than a milliamp.
[8:58] As you can tell from the spreadsheet you can get much lower than this with the right hardware
[9:02] and by powering down all the peripherals.
[9:05] Some boards go down to 10s of micro amps.
[9:07] It’s pretty amazing stuff.
[9:09] I’ve got a project coming soon that will make use of deep sleep - so stay tuned!
[9:13] And I’ll see you in the next video!
[0:00] My e-Paper weather display finally ran out of juice a few weeks ago.