Spark Sleep Modes - Low Power Consumption

I thought I would raise the topic again as the Photon is in the works.

After reading many of the threads on sleep modes and low power consumption - a topic that was active many months ago - there were suggestions from @BDub about using a regulator with a sleep control pin as well as bringing out support for Vbat.

I wanted to post this in the Hardware section in hopes the new Photon may incorporate some of these suggestions.

As for the Software - all of the threads dropped off around March - has anyone been able to successfully get DEEP_SLEEP working?

There was a comment from @kennethlimcp

In regards to DEEP_SLEEP restarting the user code again, does that mean the behavior is as if the core just restarted when returning from DEEP_SLEEP?

UPDATE - Just checked the documentation on DEEP_SLEEP and it basically resets the core on return from DEEP_SLEEP.

I already manage the WiFi (CC3000) in my user code, what I am looking for is a way to have the STM32 go into sleep without affecting the CC3000.

If the only options are the Spark.sleep() then how do they interact with SYSTEM_MODES? If I have set SYSTEM_MODE(MANUAL) and use Spark.sleep(SLEEP_MODE_DEEP, 600) will the core restart correctly?

I was hoping for a mode that retained memory variables but placed the processor into a low power mode, if none such mode exists I guess I can store my variables in EEPROM before entering SLEEP_MODE_DEEP and then restore them after returning in my setup().

I'm curious what others are doing?

@mtnscott, calling Spark.sleep() with the DEEP_SLEEP setting will cause the core to reset when the sleep time expires, just as if you had hit the reset button.

In order to implement wake-on-interrupt, the Core is placed in STOP mode. According to the STM32 manua:

SRAM and register contents are preserved. In the Stop mode, all I/O pins keep the same state as in the Run mode

So, from the sounds of it, vars should be maintained. However, the firmware calls STOP mode after a reset done after calling Spark.sleep(pin, seconds). This means initialization code will be run after resuming from stop. If you set a flag in EEPROM, it may be possible to skip initialization and keep the existing vars. :smile:

2 Likes

Guess it time to write a test app to try this out. If I can't recover the variables after a Spark.sleep(pin, seconds) and testing an EEPROM value to skip my initialization then I might as well use DEEP_SLEEP :smile:

@mtnscott, my only concern is the initialization done by the firmware and then the object instantiations. Will the var mapping be the same after stop/reset? In your test app, print the address of your vars before and after the sleep to get a sense of what’s happening. :smile:

@peekay123 Would it not be simpler just to have a global and test its value in setup?

bool _bWakeFromSleep;

setup() {
    if (_bWakeFromSleep) {
        Serial.print("Waking from sleep");
        return;
    }
    Serial.begin(9600);
    _bWakeFromSleep = true;
}

loop() {
    Serial.println("In Loop"); 
    Spark.sleep(D6, 30);
}

BTW - why do I need to supply a pin when I really just want to wake after x seconds?

@mtnscott, absolutely! That is the idea but just to make sure, print its address and value to be sure both are preserved (the address should be for sure since that is allocated by the linker). I am not sure what will happen to the Serial port during the sleep/wake cycle however. :smile:

@peekay123 Since I don't really want to use a PIN to wake up, throwing away a PIN just to use the sleep mode seems like a waste. Is there any alternative? Also if I have to supply a PIN I guess I need to also set it to INPUT, ground it to avoid any unintentional wake ups?

Oh yeah, I remember reports of the serial port not recovering from sleep.

@mtnscott, STOP mode can be awakened by a timer so perhaps the pin /timer call to Spark.spleep() is the way to go. It is possible that STOP might be called without a reset, effectively stopping the code at the call and then waking and starting execution from where it left off. I know @mohit had mentioned the possibility in the github issues discussion.

@peekay123 Well it appears the following does not put the core into any STOP state -

Spark.sleep(D6, 30);

The function call has no effect and my setup() does not get called again. The RGB lights don’t change in my app (I tear down the WiFi connection so normally I get a breathing white)

Any thoughts? Has anyone used this specific mode of operation? It’s different than the normal Spark.sleep(seconds) as that does not put the core into STOP.

@mtnscott, are you not missing a parameter to define the interrupt condition for waking (RISING, etc.)?

Also, don’t forget to tie your input to GND just to make sure there is no noise on the pin. :smile:

Oops - that was it. Unfortunately none of the memory variables are retained and when returning from the SLEEP state the WiFi is enabled, It was disabled prior to entering sleep.

Looks like the current implementation of Spark.sleep is not what I am looking for. I may try playing around with the MCU SLEEP mode directly.

Thanks!

@mtnscott, look at sleep() and Enter_STOP_Mode() in spark_utilities.cpp for some inspiration. :smile:

2 Likes