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

System.sleep(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long seconds) and attachInterrupt() #1029

Closed
RobMeades opened this issue Jun 13, 2016 · 8 comments

Comments

@RobMeades
Copy link

commented Jun 13, 2016

Hi there. It appears that if one has an interrupt attached to a pin, and then one wants to put the system to sleep and wake-up on that pin, the System.sleep() call replaces the call that you had previously attached to that interrupt (tested on Electron [2G-G350] with firmware 0.5.1).

Here is some test code:

const int intPin = WKP;

time_t sleepTime = 0;
volatile bool interruptFired = false;

// Handle the wake-up interrupt going off
static void intWakeUp() {
    interruptFired = true;
}

void setup() {
    Serial.begin(9600);

    pinMode(D7, OUTPUT);

    pinMode(D3, OUTPUT);
    digitalWrite(D3, LOW);

    pinMode(intPin, INPUT_PULLDOWN);
    if (attachInterrupt(intPin, intWakeUp, RISING)) {
        Serial.println ("Interrupt attached to intPin.");
    } else {
        Serial.println ("WARNING: couldn't attach interrupt to intPin.");
    }
}

void loop() {
    time_t sleepForSeconds = 10;

    delay(10000);

    if (interruptFired) {
        interruptFired = false;
        Serial.printf("Interrupt fired at %s.\n", Time.timeStr().c_str());
    }

    Serial.printf("Sleeping for %d seconds at %s.\n", sleepForSeconds, Time.timeStr().c_str());
    if (sleepTime != 0) {
        Serial.printf("...%d seconds after waking.\n", Time.now() - sleepTime);
    }

    // Leave a little time for serial prints to leave the building before sleepy-byes
    delay (500);

    // Sleep unless sleepy-time has ended or the wake-up interrupt pin has gone off
    sleepTime = Time.now();
    System.sleep(intPin, RISING, sleepForSeconds, SLEEP_NETWORK_STANDBY);
    digitalWrite(D7, !digitalRead(D7));
}

Obviously one could attach the interrupt again but if the interrupt happened to go off between the wake-up call and the reattachment it would be lost, which is undesirable. It would be much better if the System.sleep() chained the existing user function call.


Completeness:

  • Minimum test case added
  • Device, system and user firmware versions stated
  • Particle confirmed
@monkbroc

This comment has been minimized.

Copy link
Member

commented Jun 13, 2016

Hi Rob,

Could you clarify what you think should happen in this case? When the device wakes up from System.sleep with the wakeup pin it behaves as if the device is reset and runs all user code from the beginning with no values being maintained in memory from before the stop mode. (this is copied from the sleep section of the docs)

@ScruffR

This comment has been minimized.

Copy link
Contributor

commented Jun 13, 2016

Hi Julien,
I think the docs are not quite correct in this regard.
Stop Mode does not start from the beginning (go through setup()) and does keep SRAM powered IMHO.
Unfortunately the actual behaviour is only placed in a note further down that section

(Note: The Photon and Electron will not reset before going into stop mode so all the application variables are preserved after waking up from this mode. The voltage regulator is put in low-power mode. This mode achieves the lowest power consumption while retaining the contents of SRAM and registers.)

@monkbroc

This comment has been minimized.

Copy link
Member

commented Jun 13, 2016

The sleep docs need to be revised and clarified then. We now have many sleep modes that don't all behave the same but all all triggered from System.sleep.

@ScruffR

This comment has been minimized.

Copy link
Contributor

commented Jun 13, 2016

That's true, hence Rob has also opened an issue in the docs repo.

It's not only sleep() that needs work. Too many places have subsections/notes about all the differente system versions where feature get added/deprecated/changed/...

@avtolstoy avtolstoy self-assigned this Jun 13, 2016

@RobMeades

This comment has been minimized.

Copy link
Author

commented Jun 13, 2016

Indeed, and for cellular Stop Mode sleep is the one most likely to be used as it saves the registration load on the device and the network.

To answer @monkbroc's question, I would like the System.sleep() call to not remove my interrupt function but instead to run it after it's done its own work.

@ScruffR

This comment has been minimized.

Copy link
Contributor

commented Jun 13, 2016

AFAIK you could also use System.sleep(SLEEP_MODE_DEEP, timeout, SLEEP_NETWORK_STANDBY) (despite the fact it's not doced).
It also wakes on a RISING edge on WKP but goes through setup() and doesn't keep SRAM (apart from retained variables).

@avtolstoy

This comment has been minimized.

Copy link
Member

commented Jun 30, 2016

@RobMeades This should be fixed in PR #1051. If there is an interrupt handler already attached to the same pin as used for Sleep, it will not be cleared/reconfigured and will be called immediately after exiting STOP mode (well, not immediately, but as soon as HSE clock stabilizes).

@RobMeades

This comment has been minimized.

Copy link
Author

commented Jul 5, 2016

@avtolstoy excellent, many thanks.

@avtolstoy avtolstoy referenced this issue Aug 2, 2016
7 of 7 tasks complete

@technobly technobly closed this Aug 9, 2016

@technobly technobly added this to the 0.6.x milestone Aug 9, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.