Sleeping a handheld device

Does anyone have experience powering down or sleeping & waking a microprocessor-based, battery-operated handheld device?

I am in the final stages of an ESP8285-based handheld device project that is powered by a battery. I want to enter sleep or power down the device after some time of inaction to increase battery life.

After lots of research, I have found that:
Putting the 8285 to sleep for a programmed time can be done in “startup” using ESP.deepSleep() functions. After this time it will wake up [if wired correctly]. It can also be awoken via an I/O pin or interrupt.
This approach has all the code in “startup” and somewhere in that code it tells the processor to sleep for a programmed amount of time after which it awakes and runs “startup”.

In my app I want it to go to sleep after some time of inaction at the devices panel, not on a programmed cycle.

It seems that it is a common need for a device like this to sleep yet I find no examples of how this is done.

The only way I can think to do this is:

  • Keep track of a timer in the main program (like 10 min).
  • Reset this timer when a button is pushed.
  • When no buttons are pushed and the timer expires execute an ESP.deepSleep(0) [0 = infinity]
  • The user cycles the power switch to reset and therefore wake up the device.

The above seems kludgey to me.
Any other advice and examples are welcome.

I think how you describe it is indeed how it’s done, except for the last thing: any button should be able to wake it up if it’s asleep; shouldn’t have to power reset to wake. What inputs do you have?

When I most recently did this, it was on an ESP32, and it did wake on any button push.

(I’d think that a hardware watchdog-like auto-sleep function would be even more complicated from having to explicitly poke to to make it not to to sleep, or… just hope that they had the particular heuristics you want? Maybe I’m not understanding what you would expect it to work like?)

I have two ground-true buttons on the I/O.

There is also no evidence that the same button can be used for a realtime function and also for waking the processor, without conflict.


I found these functions for ESP 32 but not sure they are supported in 8285 and I am not positive how they work.

// for entering deep sleep and return with gpio

pinMode(GPIO#, INPUT_PULLUP); // GPIO 16 = DO

rtc_gpio_hold_en(GPIO_NUM_[GPIO#]);

esp_sleep_enable_ext0_wakeup(GPIO_NUM_[GPIO#],LOW);

esp_deep_sleep_start(); // goes into deep sleep

ex: if I am using D0 as a functional button can I also assign it as a wakeup button. Does the wakeup function stop looking at that button after it wakes?

What does the processor do when the wakeup button is asserted. Is this an interrupt and does it need an ISR? Or does it just do a reset?

I’ve probably run out of helpfulness, because I barely worked with the 16-bit ESPs and mostly have used ESP32 variants, and it’s been too long even there. I don’t know whether I even have the code around for the ESP32 project to check — was a father-son thing and there was a lesson that happened there involving the importance of data backup. :smiling_face:

I’d just be surprised if you couldn’t wake up from deep sleep on arbitrary button press because so many gadgets do just that.

I was thinking the same thing. I will followup with the results of my testing.

1 Like

I got lost in model numbers. For anyone else who lands here, the ESP8285 is a (single core I think) 32-bit Tensilica like most of the ESP32 family, in a small package with a more limited number of GPIOs.

Espressif consider the Risc-V ESP8684 to be the newer version, which has half the deep-sleep power consumption. The ESP8285 consumes 10 µA in deep sleep, and the ESP8684 consumes 5 µA.

While RTC (Real Time Clock) is the only powered unit during deep sleep, so you would think that you could only wake up based on a timer, it turns out that this RTC unit is also responsible for monitoring external conditions for wakeup. You can configure it to wake up on either high or low condition for the RTC-enabled GPIOs you choose. See the “External Wake up” section in this article:

What I don’t see in the 8285 datasheet is a list of which GPIOs are RTC GPIOs.

This is a continuation of the ESP8266 and as far as I can tell the sleep modes are equivalent and the ESP8266 documentation is the place to start. The 8285 documentation is fairly brief but lists the 8266 datasheet as ‘required reading’…
(https://www.espressif.com/sites/default/files/documentation/0a-esp8285_datasheet_en.pdf)

In deep sleep the only part of the system running is the RTC; the GPIO system is hard off.

The only way to wake the module is with a soft-reset; this can be generated from the timer on GPIO16 (the RTC timer signal pin) which is linked to RST. You could wake your system by parisiteing that line with the interrupt signal, it’s pull down to reset.

There is a good article on this here:

1 Like

Aw, only GPIO16 on the ESP8285. :cry:

So you can have a “wakeup” button tied to GPIO16, but that’s it on that platform.

Yep, it’s all confusing:

  • ESP8266 - the ‘base model’, limited deep sleep Wake.
  • ESP8285 - a expanded model (more memory+wifi) of the 8266
  • ESP32-S - the 'classic ESP chip with tensillica cores and better deep-sleep wakeups.
  • ESP32-C - the risc-v variant with great sleep modes, 5uA at best… on a par with the M4 nordic chips.
1 Like

The current design approach used GPIO 16/D0 as the ext wakeup.
I tied a tilt switch to that pin.

My main conceptual confusion was around when in external trigger mode how do I put it to sleep. I think I got that answered.

Since I have yet to test this I am still wondering if I use GPIO for a button in Loop() can I also use it for the wakeup.

I will find out today …

1 Like

Actually tied to RST, the RTC uses GPIO16 for it’s wake signal, but it is the reset that does the waking.

edit: this is my understanding of how it works. Does your sketch wake correctly with just a signal on GPIO16 @donkjr ?

Not only that different manufactures use and call these processors different and misleading things.

This is a great to tool to cut through the confusion and determine exactly what you have connected.

https://espressif.github.io/esptool-js/

Not tested this mode yet.
Tying GPIO16 to reset causes wakeup (reset) after the programmed time.

I am planning on using the esp_sleep_enable_ ext0_wakeup(), or esp_sleep_enable_ ext0_wakeup() functions which should wakeup from a pin defined in the parameters of those functions. The pin has to be a RTC capable pin.

I’ve got a horrible suspicion these are only available in light sleep (if at all, they only show up in ESP32 documentation for me).

I was doing some stuff with an ESP32 in a T-Watch and trying to keep the clock/time accurate even through sleep cycles since I didn’t want to use WiFi to keep the clock accurate. It had a builtin RTC after all but what I found was there was no accurate clock signal and if you wanted to come out of deep sleep with an accurate clock you needed the external 32KHz xtal.
Also where I ran into conversations about different sleep modes, lowering clock speeds to CPU and memory to decrease power usage.

So you might find interesting things related to power usage and sleeping in the T-Watch threads.

The T-Watch is a ESP32-S3 device; which has good deep-sleep wake options, from IO pins, uart and it’s internal timers.

The ESP8266 based devices have no deep sleep wake option other than a (soft) reset on the RST pin, so I think Don will end up having to use that. It’s pull-down and easy to have multiple sources of the signal, eg from a seperate RTC and a button.

The T-Watch actually has a a seperate PFC8563 RTC chip onboard with a crystal and backup battery. It has an interrupt pin that goes to a deep-sleep wake capable gpio pin on the ESP32. There is no need to touch the internal RTC of the mcu. The micropython firmware I use gives 2/3 days of on-wrist use by leveraging the RTC, touchscreen and MMU (accelerometer) interrupt features.

1 Like

From the [ESP8285 Data Sheet]
(https://www.espressif.com/sites/default/files/documentation/0a-esp8285_datasheet_en.pdf)
image

From the ESP8266 Data sheet

I’m not frustrated at all… :slight_smile:

That must be some other T-Watch than the 2020 v2 model I have because it has no external RTC, the ESP32 has onboard RTC( and the ESP8285 Don mentioned is more like the ESP32 than the ESP8266 from what I gathered).

There is an onboard RTC and that’s what’s active in deep sleep BUT it’s not very accurate because it likely uses the onboard clock so when you wake up there will be some missing or gained time. ie the time the RTC has is not going to be the same as the outside world. To improve this there are a couple of GPIO pins which can have a more accurate xtal placed across them(32KHz).

There are gobs of forum discussions on this and some tricks which can be played to know the drift and correct for it when a consistent sleep period is used. In Don’s case he wants to wake on an IO so if he cares how accurate the RTC time is, he’ll want to enable/implement the 32KHz xtal support or add an offboard battery backed RTC clock.
example of just one discussion I found: RTC accuracy - ESP32 Forum

I cant belive its this hard !!

The esp EXT0 setup functions I found for sleep don’t even compile:

esp_sleep_enable_ext0_wakeup((gpio_num_t)[GPIO#],LOW);


Design intent:
I have 2 ground true buttons on the handheld device [which is a mag meter]:

  • Hold (Save a value)
  • Cal (calibrate)

If no buttons are pushed for some time(t) then the processor is put to sleep.
If the Hold button is pushed it will come out of sleep.

I have the HOLD button connected to GPIO16 on the 8285 and grnd

Time(t) does not need to be accurate.

Apparently those esp functions only work with an esp32.
They compiled when an esp 32 was plugged in.