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

Electron resumes session after sleep #845

Merged
merged 3 commits into from
Mar 18, 2016

Conversation

technobly
Copy link
Member

After System.sleep(pin, trigger, seconds) or System.sleep(pin, trigger) electron will enter STOP mode, modem will remain on and powered in this mode (Photon/P1 will still have the Wi-Fi module powered off). The reason for this is to maintain an active PDP context to keep our current DTLS session happy. Upon waking, the system will immediately be able to Particle.publish() with the bare minimum amount of data transferred (TX/RX). Current consumption in this mode is ~4mA for the most of the idle time with small peaks when the modem is maintaining a cellular network connection. Current consumption should be further reduced when Low Power mode is enabled. (NOTE: Please measure and test these current readings yourself before deploying a product based on them, this is preliminary info)

Simple change, big impact :)

@technobly
Copy link
Member Author

@m-mcgowan just a heads up that I added the 0.5.x milestone to this PR. Very important for sleepy code with low data usage on resume.

@m-mcgowan
Copy link
Contributor

How about we remove the conditional compilation and instead wire this through to a flag, so that the behavior is controllable by the caller. We could have a new flag SLEEP_NETWORK_UP or similar that maintains the network connection. The flag has no affect on the core/photon.

This could also be used on the deep sleep mode too. So the sleep API turns off the radio by default (keeping consistency with other platforms) and allows the user to optionally maintain the network connection.

Currently deep sleep already doesn't turn off the radio - I believe this is an oversight. I feel it's best to make the APIs consistent (so that 0.5.0 does turn off the radio by default) since that's the least surprising outcome. The SLEEP_NETWORK_UP flag is there for those cases where the caller wants to maintain the cellular connection.

@m-mcgowan
Copy link
Contributor

In a meeting with me, @technobly and @avtolstoy, we decided that there would be an additional optional flag as the last parameter to deep sleep, and stop sleep modes. The flags are:

SLEEP_NETWORK_STANDBY
SLEEP_NETWORK_OFF

e.g.

System.sleep(SLEEP_MODE_DEEP, 10, SLEEP_NETWORK_STANDBY);
System.sleep(D7, RISING, 10, SLEEP_NETWORK_STANDBY);

The default is SLEEP_NETWORK_OFF so that sleep shuts down the network as part of sleep.

The flags will be strongly typed to remove the chance of confusion in mixing with other integer-typed parameters.

This is intended as a stop-gap solution. The sleep mode API will be overhauled for a 1.0 release.

@m-mcgowan m-mcgowan force-pushed the feature/electron/sleep-resume branch from 4c388c8 to 6b0f9fe Compare March 14, 2016 14:21
@m-mcgowan
Copy link
Contributor

@technobly - please review these changes when you get chance. (I've not tested them - going to have a bout of coding then will test.) Any thoughts how we can automate tests for this new functionality?

@technobly
Copy link
Member Author

@m-mcgowan we should start with simply automating existing sleep tests. One way to test sleep mode reliably is to use a serial to usb adapter on Serial1 for debugging output. This way the serial stream will stay open as the device goes to sleep and/or resets after waking from sleep. Typically the USB serial will disconnect on sleep Stop and Standby.

A simple GPIO could work for this as well, but not nearly as accurate as sending and parsing a message that says "GOING TO SLEEP", "WAKING UP" ... and after several iterations "FINISHED" ... or even "S", "W" and "F" from the test device. Then timing from the test rig to ensure these messages are occurring at predefined times.

One step further would be to command the test device to sleep at different times, 5, 10, 20, 30 seconds and with different sleep APIs and log / measure all appropriate responses.

Beyond that we need to put a CI on the interrupts that wake Sleep stop mode as well.

Then to test the new API -> NETWORK_STANDBY, for the Electron we would expect low data usage in sleep Stop and fast connection times, both fairly straight forward to measure. We could monitor current usage as well when asleep, as we'd expect the modem to be on.

@m-mcgowan
Copy link
Contributor

@technobly Please review and merge.

@@ -106,8 +118,11 @@ void system_sleep(Spark_Sleep_TypeDef sleepMode, long seconds, uint32_t param, v

void system_sleep_pin(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long seconds, uint32_t param, void* reserved)
{
network_suspend();
bool network_sleep = (param & 1)==0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this just use network_sleep_flag(param)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I had planned to do this as part of the refactoring while writing the code - seems that fell through the cracks. Good catch!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll push that change.

technobly and others added 3 commits March 18, 2016 15:09
* after System.sleep(pin, trigger, seconds) or System.sleep(pin, trigger) electron will enter STOP mode, modem will remain on and powered in this mode (Photon/P1 will still have the Wi-Fi module powered off). The reason for this is to maintain an active PDP context to keep our current DTLS session happy.  Upon waking, the system will immediately be able to Particle.publish() with the bare minimum amount of data transferred (TX/RX).  Current consumption in this mode is ~4mA for the most of the idle time with small peaks when the modem is maintaining a cellular network connection.  Current consumption should be further reduced when Low Power mode is enabled.
@monkbroc monkbroc force-pushed the feature/electron/sleep-resume branch from 0f87b4e to 5220382 Compare March 18, 2016 19:10
@monkbroc monkbroc assigned technobly and unassigned monkbroc Mar 18, 2016
@monkbroc
Copy link
Member

I reviewed the code. The changes look good. I rebased to the latest develop so it's mergeable but I don't have enough background info on what behaviour this should have to test it. I'm assigning it back to you @technobly.

m-mcgowan added a commit that referenced this pull request Mar 18, 2016
@m-mcgowan m-mcgowan merged commit c974657 into develop Mar 18, 2016
@m-mcgowan
Copy link
Contributor

oops..trigger finger

@technobly
Copy link
Member Author

Tested these 6 cases successfully on the Electron:

Only one sleep type will not require a full handshake. Two others will require a full handshake and then restore and resume sessions thereafter. Deep sleep always requires full handshake even though it seems like it should be able to restore and resume as well.

In deep sleep, D7 LED is off
In stop sleep, D7 LED is on

spinWait(6000); is required for this PR, will not be required for future use.

#include "application.h"

SYSTEM_MODE(SEMI_AUTOMATIC);

// ALL_LEVEL, TRACE_LEVEL, DEBUG_LEVEL, INFO_LEVEL, WARN_LEVEL, ERROR_LEVEL, PANIC_LEVEL, NO_LOG_LEVEL
Serial1DebugOutput debugOutput(9600, ALL_LEVEL);

retained int count = 0;

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

void spinWait(uint32_t timeout) {
    uint32_t start = millis();
    while (millis() - start < timeout) Particle.process();
}

void setup() {
    pinMode(D1, INPUT_PULLDOWN);
    pinMode(D7, OUTPUT);
    Particle.connect();
    DEBUG_D("\r\n[ Particle.connect ]\r\n\r\n");
    waitUntil(Particle.connected);
    DEBUG_D("\r\n[ Particle.connected ]\r\n\r\n");
}

void loop() {
    digitalWrite(D7, LOW);
    DEBUG_D("\r\n[ Waking up and publishing once! ]\r\n\r\n");
    Particle.publish("b", String(++count));

    spinWait(6000);

    DEBUG_D("\r\n[ Going to sleep ]\r\n\r\n");
    digitalWrite(D7, HIGH);

    // These all will restore and resume sessions after the first full handshake (fairly low data usage)
    //
    // System.sleep(D1, RISING, 30); // SLEEP_NETWORK_OFF is default
    // System.sleep(D1, RISING, 30, SLEEP_NETWORK_OFF); // Turns off network

    // These all require a full handshake (higher data usage)
    //
    // System.sleep(SLEEP_MODE_DEEP, 30); // SLEEP_NETWORK_OFF is default
    // System.sleep(SLEEP_MODE_DEEP, 30, SLEEP_NETWORK_STANDBY); // Does not turn off network
    // System.sleep(SLEEP_MODE_DEEP, 30, SLEEP_NETWORK_OFF); // Turns off network

    // This is the only one that doesn't require another
    // session resume or handshake upon waking (lowest data usage)
    //
    System.sleep(D1, RISING, 30, SLEEP_NETWORK_STANDBY); // Does not turn off network
}

@technobly technobly removed their assignment Mar 19, 2016
@monkbroc monkbroc deleted the feature/electron/sleep-resume branch March 23, 2016 00:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants