Here’s a more elaborate example. It allows:
- Wake by cellular
- Wake by another pin (RISING only)
- Wake by sleep time expired
It requires 0.8.0 (tested with 0.8.0-rc.8) because it require multi-pin wake support and SleepResult. (The example above works with 0.7.0.)
It also has a function, variable, and event subscription, and those work too on wake from cellular.
To run the test:
- To go to sleep, pull D2 to GND
- To wake by pin, pull D3 to 3V3
- You can wake by ping, function (“testFn”), variable (“testVar”), or publish (“wakeEvent”)
And some other caveats:
- It only works with stop mode sleep (pin + time). You can’t wake from SLEEP_MODE_DEEP from a pin other than WKP, so you can’t wake on RI_UC.
- You need to use SLEEP_NETWORK_STANDBY, otherwise the modem is turned off and obviously can’t receive the request.
- You can wake on more than 2 pins, but all of the pins must wake on RISING as that’s what RI_UC requires.
- You probably won’t see the function or subscribe log messages because serial won’t have reconnected yet.
#include "Particle.h"
#if SYSTEM_VERSION < 0x00080000
#error "You must target system firmware 0.8.0 or later to use this code"
#endif
SerialLogHandler logHandler(LOG_LEVEL_TRACE);
const int SLEEP_PIN = D2;
const int WAKE_PIN = D3;
const unsigned long SLEEP_TIME_SECS = 120;
int testVar = 0;
int testFn(String param);
void wakeEvent(const char *event, const char *data);
void setup() {
Serial.begin();
pinMode(SLEEP_PIN, INPUT_PULLUP);
pinMode(WAKE_PIN, INPUT_PULLDOWN);
Particle.variable("testVar", testVar);
Particle.function("testFn", testFn);
Particle.subscribe("wakeEvent", wakeEvent, MY_DEVICES);
}
void loop() {
if (digitalRead(SLEEP_PIN) == LOW) {
Log.info("turning on AT+URING=1");
// Enable wake on all URCs
Cellular.command("AT+URING=1\r\n");
delay(1000);
SleepResult sleepResult = System.sleep({RI_UC, WAKE_PIN}, RISING, SLEEP_TIME_SECS, SLEEP_NETWORK_STANDBY);
// This delay is to allow the serial monitor to reconnect only
delay(2000);
if (sleepResult.wokenUpByRtc()) {
Log.info("woke up by time expired");
}
else
if (sleepResult.pin() == RI_UC) {
Log.info("woke up by cellular");
}
else {
Log.info("woke up by WAKE_PIN");
}
// Turn URING back to the default value (only notify on SMS or voice call)
Cellular.command("AT+URING=0\r\n");
testVar++;
}
}
int testFn(String param) {
Log.info("testFn %s", param.c_str());
return 0;
}
void wakeEvent(const char *event, const char *data) {
Log.info("wakeEvent %s %s", event, data);
}