WakeOn RI in SLEEP_NETWORK_STANDBY?

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);
}

9 Likes