Low power "sleep" mode

Continuing the discussion from Arduino Button Mappings:

This topic has been created to continue discussions about the possibility of putting the Arduboy into an extremely low power “sleep” mode, that would allow a sketch to be paused with the display blank, and then resumed after days, weeks, or even months.

Something I forgot to consider is the current drawn by other components.

There will be a voltage regulator to provide power to the display and possibly the processor as well. A typical, efficient, low drop out (LDO) regulator that is commonly used is the Micrel MIC5205. This device will still draw about 80uA when the display and processor are sleeping.

Also, there will probably be a battery charge controller IC. For example, the Gamebuino uses a Microchip MCP73833. This chip requires typically 50uA when not charging (USB disconnected, in our case).

Using the above values, current draw in sleep mode would be more like 150uA. Being very conservative, and to consider other possible sources that have been overlooked, let’s make it 200uA. With a fully charged 180mAh battery, we could sleep for 900 hours, or about one month.

This is still over the “week or two” that @Dreamer3 was hoping for, so it’s probably still worthwhile to continue working on the details of how this could be implemented from a software point of view.

It’s probable that making the buttons interrupt capable wasn’t considered when assigning them to pins. I’m guessing assignment was mostly based on what was easiest, from a circuit board layout and routing point of view.

On May 26, in the comments section of the Arduboy Kickstarter campaign, @bateske stated:

Since the start button is new, it could easily be assigned to an interrupt capable input. We could then use it for pause and sleep and wake up and resume.

By “similar to the power switch” I assume @bateske means right angle, on the edge of the unit. This would be ideal for a pause/resume switch (in addition to start), especially if it were recessed so as to be difficult to accidentally push by being knocked around in a pocket or purse.

For operation, I suggest that a short press on the button would simply pause the game (and perhaps for some games bring up a menu). Once paused, a long press of about 5 seconds would put the unit in sleep mode (and a short press could be used to resume, or any other function).

Another long press would be required to exit sleep mode. What would actually happen is that the interrupt created by pressing the button would wake up the processor immediately, but the software would then make sure that the button remained down for 5 seconds before waking up the display and continuing. If the button was held for less than 5 seconds then the software would return to sleep mode. The reason for requiring a long press is, again, to prevent waking up accidentally from an accidental button bump.

Another way to implement sleep/wake, instead of a long press, would be to require one or more additional button(s) to be held down before pushing start. A combination of requiring multiple buttons and a long press would make accidental activation even more difficult.

And this all requires a user to compile against the official libs? (Which would support sleep?) I kind of feel like the lib should simply hide long presses on start from the app… if someone hits it shortly it registers… if someone holds it for x seconds it triggers sleep or wake. This is pretty easy if someone is using the built in frame loop. If we track button counters (for other button state stuff) we could just not allow long presses of Start… it would only fire momentary events… and long presses would be handled by the core lib once detected (once they crossed the timer threshold).

Well no sketch has to include or use anything in the “official” libs, or any other lib for that matter. There’s nothing that a library can do that can’t be done by equivalent or alternative code in the sketch itself.

I think it’s important that all functions in the library are well designed and easy to understand and use, so people will want to use them. The more consistent procedures such as this are between sketches, the better. That’s what this and other similar discussions are for, and I applaud you for taking the initiative with your proposals.

I have to confess that, personally, designing how a sleep mode should be handled is not one of my higher interests. I started this topic because I had a bit more to say about it and felt it shouldn’t continue under the “button mapping” topic. Hopefully, there will be others who are interested in contributing.

OK, regardless of what I said in my previous post, I’ll still contribute when I feel the need. :smile:

If you’re planning on some kind of universal button handling routine, it’s fine if it includes detecting long presses (or whatever “standard” method of activating sleep mode we decide on), but it should only report it, not automatically activate sleep mode. There may be sketches that don’t ever want to allow sleeping, or more likely, sketches that want the ability to do something before sleeping, such as save important continuation info in EEPROM, just in case the battery dies, or the power switch is used, while asleep.

What should happen is that the button handler returns something that indicates that the “official” sleep mode button sequence has been detected. The sketch would then call a separate library function to actually initiate sleep mode, after doing any saving or other preparation beforehand if desired.

Also, what the button handler reports shouldn’t be defined as long start button detected. It should report specifically user initiated sleep mode request detected. This way, if we decide to change what the “official” way of entering sleep mode is, such as using a different button or sequence, the sketch itself is unaware of this change.

For example, Arduboy2, or some other future product, might come with a dedicated sleep button. The library for the Arduboy2 would be different (or use #defines) to account for this button but a sketch would need no alterations to work with it.

The lib can easily handle that by simply allowing the user to register a function called when the device sleeps or wakes. It doesn’t have to be “fully manual” to allow that type of flexibility. Again developers can always do what they want, write from scratch, edit the core lib, etc… I just think some strong patterns and guidelines here would help. Having the core lib auto handle sleep and wake and allowing apps to register for both callbacks (before sleep/after wake) would handle 90+% of use cases, would it not?

I know some of that Arduino libs already have this “register a function to handle” functionality, but I forget which ones off the top of my head - so it’s not even a new pattern.

What should happen is that the button handler returns something that indicates that the “official” sleep mode button sequence has been detected.

Right, that’s what I meant by keeping it secret from the app. IF we took this approach we could just tell API developers that long presses are not supported on the start button other than for sleep mode… and if they ask the button API it will only report momentary presses… BUT the actual signal for sleep mode could be just the function callbacks I mentioned earlier - and in the future if we had a dedicated sleep button then that button could fire the callbacks and we could give the start button back to users for long presses.

It could be I’m way off, but I just seem it would be nice if the device itself had some functionality I could expect to be somewhat consistent across apps. IE, if I’m in bed at night I’d like to use low brightness… I wouldn’t want one game to be super high brightness because the dev thought that was cool. I mean I can’t STOP a dev from doing that, but I can try to encourage letting the user set the brightness by building it into core lib some how - same with sound. Just my 0.02.

What about sketches that don’t want to allow the device to sleep at all? Or maybe I only want to allow sleeping at certain points but not others.

Keep in mind that the Arduino platform was developed to allow people, who may not be expert programmers, to quickly get a project requiring a microprocessor up and running with little effort. Introducing callback functions (in an environment where they’re so rare that even you can’t remember which libs use them), might scare inexperienced but enthusiastic developers off.

And they will if what’s available in the library appears too complicated. So now you have sketches that “do their own thing” which are inconsistent with the norm.

I don’t think a function should be so complicated as to attempt to handle everything but the kitchen sink. I would rather have a button function which told me “the user is requesting sleep mode” and another function to use if I chose to act upon it.

I think it’s better to give (perhaps strong) recommendations, guidelines and examples, and make them easy to implement, than forcing those things on everyone unless they do a lot of work to do things differently.

As with you, this is just my 0.000088 Bitcoin.

1 Like

If we’re doing what best for most then those who have other ideas can edit the core lib or use compile flags to do something different. Again, nothing is ever forced. Unless we just use other libs we need our own API and documentation, etc… so the documentation for using/supporting sleep mode would be there - and just as easy to use as any other part of the documented API.

I would rather have a button function which told me “the user is requesting sleep mode” and another function to use if I chose to act upon it.

Exactly, but I’d rather let people turn OFF sleep support than having to add 2 lines of code to turn it on. Reasonable defaults. Sleep mode, great battery life… I think some things should “just work” out of the box (without effort) and if you don’t want them you (easily) opt out of them.

I don’t see the value in telling devs it’s good to include “if (wantsSleep) doSleep” in all their sketches, when it’s something that would benefit almost everyone. Instead we should make it easy to register callbacks and show how they work in the examples.

The way I think of it is it would be nice if app developers just built apps and the device sleep mode was “above” that… you run whatever app you want and can still sleep the device anytime you want for a month of battery life and it just magically worked. If there was no cost to do that - we should do it - totally. Instead there would be a small cost to build it into the core lib… but if that cost were small enough - and it didn’t interfere with someones app, it sounds like a win win to me. And in the rare case it did interfere someone could manually turn it off and explain to their users why their app doesn’t support sleep.