Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deep sleep and external wakeup #300

Open
greggailly opened this issue Sep 13, 2023 · 42 comments
Open

Deep sleep and external wakeup #300

greggailly opened this issue Sep 13, 2023 · 42 comments
Labels
enhancement New feature or request

Comments

@greggailly
Copy link

Hi,
Is there a way to put the esp32 in deep_sleep after a certain time without "activity" and then wake up from the deep_sleep with a GPIO pin ?
While looking into the code, I've found the deep_sleep console command with the --io option which works perfectly well in the console but I can't seem to find a way to execute this either after a certain time without "activity" or (maybe easier at first) with an external button.

Any hints appreciated.

Thanks

@sle118 sle118 added the enhancement New feature or request label Sep 13, 2023
@philippe44
Copy link
Collaborator

I have not made anything to maintain properly clocks and sync and all that jazz (and there is a lot), so I have no idea of what happens really when you do that. Why not switching it off?

@Renber78
Copy link

If your goal is to turn off the device in order to save battery power, it is possible to do this with a small hardware modification to the power supply.

You would then have a push button on the device to start the power.
The LMS server will be able to cut off power during standby but will no longer be able to turn it back on since the ESP will no longer be powered (this button must be pressed).
As for automatic shutdown after a certain time, there is an LMS plugin (PowerSave) that does this very well.

The idea being to add a transistor between your power supply and your hardware whose trigger will be controlled by the button and then maintained by a GPIO when the ESP has started. (The LED power output will probably be perfect for this, but I haven't checked)

If this solution interests you, I can describe it to you in more detail.

@philippe44
Copy link
Collaborator

philippe44 commented Sep 14, 2023

I also assume that if we do that, there will be requests for using a long-press of an existing button or a shift-press to enter sleep mode. So that means it should be a feature of "buttons". But then, if you want to use "lms_ctrls_raw" option to simply send raw information to LMS, that will not work. In addition, it means that you must define a button set just to have a GPIO that enters in to sleep, even if you don't want anything else.

I now have typically contradictory requirements. You want "buttons" but you don't want "buttons" and doing both will be a nightmare... sigh. I'll have to think about it to not implement something quick and dirty that I'll regret immediately after.

@greggailly
Copy link
Author

Thank you to you both !
I'll look more into a hardware solution that controls power all together and the PowerSave plugin @Renber78 suggested.
I was looking into deep sleep to make it more flexible for the wakeup part (using a gpio pin or timer based) but for now I will probably go with switching off as the main goal is indeed to save power.

@philippe44
Copy link
Collaborator

I've added a sleep option, see https://github.com/sle118/squeezelite-esp32#sleeping. Let me know if it works for you

@philippe44 philippe44 reopened this Sep 16, 2023
@Renber78
Copy link

Several quick observations:

  • Enters an infinite wake/sleep loop with the "delay=1" config only (My hardware does not allow me to do otherwise because my buttons are on an extender and my IR on GPIO34)
  • LCD backlight does not turn off
  • I did a test on an unused GPIO on my card (19) "delay=1,wake=19:0" and I got the following message: E (2838) services: invalid wake GPIO 19 (not in RTC domain)

But I think that if the project must be used with batteries, it is better to implement a hardware solution because deep sleep will only cut off the ESP. The dac, display or other accessory will not be cut off and will still drain the battery over time.
The hardware solution that I proposed above is identical to a power button that you have on any commercial battery-powered Bluetooth speaker.

If you wish, I can take care of making a test and an electronic diagram for users.

@philippe44
Copy link
Collaborator

philippe44 commented Sep 16, 2023

Thanks for testing out. The infinite loop when no wake is solved now. The wake gpio must be in the rtc domain and 19 is not. Now, it still can work with an expander if the interrupt of that expander is in the rtc domain. That's one use case I tested. On the backlight topic, how is it connected on your board? I would think that if it is using a GPIO, it will automatically switch off. Now, on my test device, it is not connected so it remains up indeed.

Schematics to be added to README would always be a nice addition. I also added a comment on soft on/off and that can be elaborated by a lot

@Renber78
Copy link

Now wake only works, I also tested the interruption of my extender and it's good. On the other hand, when I put my IR sensor on I have a loop (may be linked to the set_GPIO bug that I reported in another post)
I will pass the scope over it during the day to ensure that the IR sensor does not send any noise.
For my LCD, in fact it did not have a lighting pin... I have several... and I got confused. I tested another LCD and it's ok too.
Good day !

@Renber78
Copy link

Also, in the Readme, this sentence misled me:

Note that not all GPIOs can be used to wake-up the esp32

ESP32: 0, 2, 4, 12-15, 25-27, 32-39;
ESP32-S3: 0-21.

I understood that these are the pins that I cannot use...
The sentence could be turned differently for greater clarity.

@philippe44
Copy link
Collaborator

Agreed, I've changed it. The backlight is also difficult to handle as there is no option to turn it off by SW. On ST7789, the register 53 does not seem to work as expected. So basically, it's left to the fact that there is a pull-down on that line and if it is connected to the esp32, when it goes on sleep, then the pulldown switches it off.

@Renber78
Copy link

Renber78 commented Sep 16, 2023

After playing with it a bit, I noticed this:

  • When the player plays a song for at least the duration of the "delay" parameter, it goes directly to sleep if I stop playback.
  • The player went to sleep when I navigated the menus with the remote control. Shouldn't we reset the delay counter to 0 when a button is pressed or when an IR reception is received?
  • I have an sleep loop if I use the central button of the knob (GPIO33) as an wakeup. This one is however equipped with an external pull-up. Same observation with my IR receiver on the GPIO34 (which also has a pull-up integrated into the TSOP4838 so should be forced to 1 in sleep)

My test config:
delay=1,wake=13:0|33:0

@sle118
Copy link
Owner

sle118 commented Sep 16, 2023

I'm happy to see this made some progress. It will never be as efficient as a real power cutting option, but it will also make a difference on battery operated devices as cutting radios will reduce power consumption by a lot. It's enough to extend the charge if one forgot to turn the power off manually with a switch. My little Bose Bluetooth speakers died because the battery drained over time, so consuming power during sleep is common I would say

@philippe44
Copy link
Collaborator

For the 3rd point, unfortunately that a limit of esp32. If you look at the README, when using multiple wakes, it wakes-up if at least one of them is 1 and this is the only criteria, sadly.
For the sleep after playing, I'll look and for the activity detection, it's true that it's only based on audio.

@sle118
Copy link
Owner

sle118 commented Sep 16, 2023

you might want to add an option to set RTC pin levels before going to sleep: low=x|y|z,high=a|b|c for the pins that support it. this would provide a path for controlling hardware during sleep

@philippe44
Copy link
Collaborator

you might want to add an option to set RTC pin levels before going to sleep: low=x|y|z,high=a|b|c for the pins that support it. this would provide a path for controlling hardware during sleep

It's already there as the "rtc" option

@sle118
Copy link
Owner

sle118 commented Sep 16, 2023

I have to admit I had not read the documentation before posting my previous comment, so thank you for educating me. Reading your explanation, I'm thinking that the SqueezeAmp might be a good candidate for the control of the power regulator in deep sleep. I am referring to the tiny header that was made available for a switch. Am I interpreting your documentation correctly?

@philippe44
Copy link
Collaborator

I have to admit I had not read the documentation before posting my previous comment, so thank you for educating me. Reading your explanation, I'm thinking that the SqueezeAmp might be a good candidate for the control of the power regulator in deep sleep. I am referring to the tiny header that was made available for a switch. Am I interpreting your documentation correctly?

Yes absolutely. It requires some flying wires obviously

@Renber78
Copy link

Renber78 commented Sep 16, 2023

In order to keep the batteries in good condition, it would also be interesting to automatically go to sleep when the battery voltage reaches a critical threshold. This could be added to the battery configuration line.
A little luxury: The display shows the transition to sleep mode and low battery. ;-)

@sle118
Copy link
Owner

sle118 commented Sep 16, 2023

@Renber78 now this is what I can scope creep 🤣

@Renber78
Copy link

Yes absolutely. It requires some flying wires obviously
it is not so simple...

Don't forget that when the power is cut there will no longer be 3V3 on the ESP, nor pull-up, nor RTC.
On the SqueezeAMP, J7 must be held at GND to shut down, but without power to the ESP the holding GPIO will be unable to pull to ground.

VCC also cannot be used directly as a voltage source for a button pull-up, it would burn the GPIO.

It will necessarily be necessary to go through transistors...

@Renber78
Copy link

Well, I spoke too quickly... by doing the opposite logic, it goes without much quibble.

  • Put a pull-down between VCC and J7 to force the power supply OFF.
  • Connect GPIO to J7 through a diode (passing from GPIO to J7)
  • The switch must be placed between VCC and J7 through a resistance which will be calculated according to the pull-down value (divider bridge) so as not to exceed the maximum admissible 7V of DC/DC on the EN pin.

I haven't tested it because I don't have this hardware but on paper this solution seems to be the right one for the SqueezeAMP.

Also, by adding a P-MOS between VCC and J7 as well as a pull-up resistor on its trigger, you could use an already existing button to wake up the system.

If I have a little more time, I will make different possible diagrams tomorrow.

@philippe44
Copy link
Collaborator

philippe44 commented Sep 17, 2023

ok - I've added buttons/rotary/ir in criteria for not sleeping as well as BT when it's a sink. I've also added a battery option. End of feature creep, let's see how it works.

NB: I've also activated LED when BT is a sink (@sle118 - don't be mad 😄)

@Renber78
Copy link

Good job, the points I pointed out are well corrected.
I haven't tested sleep vs battery voltage yet.

@Renber78
Copy link

Renber78 commented Sep 17, 2023

squeeze_sleep

Here is a first draft for the various diagrams of a hardware solution. Nothing has been tested yet but it should work.
Make your comments.

@philippe44
Copy link
Collaborator

philippe44 commented Sep 18, 2023

Silly question: on 3/ can't we just have something like that or is this an issue with transient before the zener limits the voltage
Screenshot 2023-09-17 18 30 17

@Renber78
Copy link

Renber78 commented Sep 18, 2023

Yes, you can do like this if your existing button is to Vbatt. I assumed that it was to GND (which is generally the most used method)
Your diagram still has a big advantage, you don't have R3 which pumps a slight current from the battery!

So I will add this scenario.

For transitions, nothing prevents us from replacing the zener with a TVS or even a resistor (which should be sized according to V_batt).

@philippe44
Copy link
Collaborator

A TVS is probably the better choice then because I was thinking of the case where that soft on/off is after the vcc/vbatt switch so it can have a large swing of values, so making sure the gpio button voltage on the esp32 is imposed is important, no?

@Renber78
Copy link

Renber78 commented Sep 18, 2023

Yes I will place a TVS it is indeed safer.

Something else:
I saw your last note regarding using the IR sensor as an wakes up
I re-tested this and it doesn't work for me, the system wakes up alone. (my config: wake=34:0)
I checked my IR signal which is at 1 and does not move.
Have you tested this?
Is there a problem with the GPIO34?

@philippe44
Copy link
Collaborator

Yes I've tested it on a SqueezeAMP. Why wouldn't it move? By definition, the IR signal changes when receiving something. So it will transition to the wake-up value of 0.

@Renber78
Copy link

Renber78 commented Sep 18, 2023

When I say that it doesn't move, it's when there is no reception of course (which means that I don't have any disturbing noise that will wake up the ESP).
But I have the same problem with the central knob (GPIO33) which is also on pull-up. On the other hand, with the interrupt of the extender (GPIO13) it works (yet it is exactly the same principle as the others, with pull-up, active at 0)

As a reminder: The problem is that it wakes up directly after being put on standby

I think there is really a problem with GPIO3x

Here is the wake-up log:

I (91938) sleep: Configure to isolate all GPIO pins in sleep state
I (91938) services: going to sleep cause 0, wake-up on GPIO -1 level 0

GPIO -1 is not normal

edit: I confirm that all GPIOs greater than 27 do not work for wake-up (v1558)

@philippe44
Copy link
Collaborator

philippe44 commented Sep 18, 2023

Indeed, no GPIO over 31 would work because I forgot that the built-in leading zeros count function by default is 32 bits 😞. I've now changed it for the 64 bits version and tested that GPIO 34 is taken into account.

@sle118
Copy link
Owner

sle118 commented Sep 19, 2023

Indeed, no GPIO over 31 would work because I forgot that the built-in leading zeros count function by default is 32 bits 😞. I've now changed it for the 64 bits version and tested that GPIO 34 is taken into account.
....and there was one bit per gpio so 32 gpios max. optimization is never easy 😄

@philippe44
Copy link
Collaborator

philippe44 commented Sep 19, 2023

BTW I've added something after discussing with @sle118 to handle IR spurious wakes as much as possible.

If you want to wake up on IR, as soon as the gpio toggles, it will wake up the esp32 whether it's a valid command or not and it's impossible to know if it is, you need to be booted up.

So the system will, if it woken up due to ir, enter a period of "spurious" minutes after which if there is no activity, it will go back to sleep.

It happens whether there is an inactivity delay or not.

@Renber78
Copy link

GOOD. I don't see any more problems now.

Two small details without too much importance:

  • I had cases where the display remained frozen when going to standby.
    Maybe include a clear display before going to sleep.
  • The sleep delay set to 1min gives 1min20sec, to 2min = 2min20sec, ...

Good day !

@philippe44
Copy link
Collaborator

philippe44 commented Sep 19, 2023

The delay is by chunks of 30s, so yes it's not accurate but I did not think it matters. For the display, there is a DisplayOff before sleeping, but there is scheduling and I2S involved and it might happen that there is a freeze because the command has not been executed.

I'm always trying to reduce cpu and memory while keeping things basics so the sleep system is the possibility for any software components to register a callback that tells how long its has been inactive. All callbacks are called every 30s to evaluate if sleep is possible. Another set of callbacks can be registered and are called when the system has decided to sleep. It's not really a democracy, you can't refuse to go to sleep, but you can always cheat and say you're busy although you have not done anything ... sounds familiar suddenly 😃

@Renber78
Copy link

squeeze_sleep

I reworked the diagrams.
You will notice that I did not place a TVS... I solved the problem the old-fashioned way ;-)

I also changed my approach on diagrams 3 and 4 by reversing the logic of the output to the key GPIO.
There is no longer any battery consumption when stopping the system on all diagrams now.

@wizmo2
Copy link

wizmo2 commented Sep 27, 2023

A little off topic, but could you look at implementing the set_GPIO `power' output in recovery mode? I set the output using the :1 option, but peripherals are currently only powered in while in ota.

@philippe44
Copy link
Collaborator

I'm very reluctant to do that because I really don't like to do config reading in recovery. I already think that we do way too much of it now and it should be removed. Recovery should be recovery, and fully minimalistic

@wizmo2
Copy link

wizmo2 commented Sep 29, 2023

No worries, I think vcc is what I actually need, and it looks like you initialize that.

@sle118
Copy link
Owner

sle118 commented Sep 29, 2023

And this doesn't even take into account the lack of room in recovery. We're counting bytes here.

@philippe44 I think we should remove some "set default" from the recovery of you haven't done that already. Perhaps having a weak function in the main entry point could be helpful to segregate that at linking.

@philippe44
Copy link
Collaborator

Don't you think that removing the register_xxx as I started to do is a better choice?

@wizmo2
Copy link

wizmo2 commented Sep 29, 2023

I've been working on this while trying to build a targeted install for the s3 project I'm working on.
Was starting to prepare a a PR to clean up the UI, along with the some of the Konfig.build settings.

My current build hides everything that was pre-configured, but there are settings that include system parameters and user preferences (for example, rotary encoder settings and display orientation),

IMO, I think you should consider reviewing this and separate pre-defined hardware vrs optional settings. I believe you already have the basics for this, with nvs defaults and overrides.

If you need some help, more than willing,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants