Fault tolerance and sleep mode weird behavior

Tags: #<Tag:0x00007f038f062400>


Hello guys.
This is my first post here but I’m using particle products for 3 years now.
I ran into a weird behavior while testing electron sleep mode along with the wonderful library of fault tolerance by @rickkas7.

The code I test is provided below. Basically it’s the example from the library + Going to sleep for 10 seconds and waking up again.

What happens is that it will operate ok but every now and then it would fall to sleep so deep that it just won’t recover from it. I needed to take the battery out and re-plug it to make it work back.

What could be the reason, and what could help it?

// Electron Sample Application for fault tolerance and problem debugging techniques
// Requires system firmware 0.6.1 or later!
// Original code location:
// https://github.com/rickkas7/electronsample

#include "Particle.h"

#include "AppWatchdogWrapper.h"
#include "BatteryCheck.h"
#include "ConnectionCheck.h"
#include "ConnectionEvents.h"
#include "SessionCheck.h"
#include "Tester.h"

// If you are using a 3rd party SIM card, put your APN here. See also
// the call to Particle.keepAlive in setup()
// STARTUP(cellular_credentials_set("YOUR_APN_GOES_HERE", "", "", NULL));

SerialLogHandler logHandler;

// We use retained memory keep track of connection events; these are saved and later uploaded
// to the cloud even after rebooting
void startup() {

// System threaded mode is not required here, but it's a good idea with 0.6.0 and later.
// https://docs.particle.io/reference/firmware/electron/#system-thread

// SEMI_AUTOMATIC mode or system thread enabled is required here, otherwise we can't
// detect a failure to connect
// https://docs.particle.io/reference/firmware/electron/#semi-automatic-mode

// Manage connection-related events with this object. Publish with the event name "connEventStats" and store up to 32 events
// in retained memory. This provides better visibility into what your Electron is using but doesn't use too much data.
ConnectionEvents connectionEvents("connEventStats");

// Check session by sending and receiving an event every hour. This can help troubleshoot problems where
// your Electron is online but not communicating
SessionCheck sessionCheck(3600);

// Monitors the state of the connection, and sends this data using the ConnectionEvents.
// Handy for visibility.
ConnectionCheck connectionCheck;

// Tester adds a function that makes it possible exercise some of the feature remotely using functions.
// testerFn is the function and and the second parameter that's a pin to test pin sleep modes.
Tester tester("testerFn", D2);

// BatteryCheck is used to put the device to sleep immediately when the battery is low.
// 15.0 is the minimum SoC, if it's lower than that and not externally powered, it will
// sleep for the number of seconds in the second parameter, in this case, 3600 seconds = 1 hour.
BatteryCheck batteryCheck(15.0, 3600);

// This is a wrapper around the ApplicationWatchdog. It just makes using it easier. It writes
// a ConnectionEvents event to retained memory then does System.reset().
AppWatchdogWrapper watchdog(60000);

void setup() {

	// If you're battery powered, it's a good idea to enable this. If a cellular or cloud connection cannot
	// be made, a full modem reset is first done. If that doesn't resolve the problem, on the second and
	// subsequent failures, the Electron will sleep for this many seconds. The intention is to set it to
	// maybe 10 - 20 minutes so if there is a problem like SIM paused or a network or cloud failure, the
	// Electron won't continuously try and fail to connect, depleting the battery.
	connectionCheck.withFailureSleepSec(15 * 60);

	// We store connection events in retained memory. Do this early because things like batteryCheck will generate events.

	// Check if there's sufficient battery power. If not, go to sleep immediately, before powering up the modem.

	// Set up the other modules

	// We use semi-automatic mode so we can disconnect if we want to, but basically we
	// use it like automatic, as we always connect initially.

void loop() {
    waitFor(Particle.connected, 20*60000);
	// 7. Going to sleep

	// It's necessary to turn on the cellular modem in MANUAL or SEMI_AUTOMATIC mode
	// before going to sleep. This happens because the modem is put to sleep using AT
	// commands, and they don't work when the modem is not on.

	// This workaround appears to be necessary when using SYSTEM_THREAD(ENABLED).
	// The reason is that .on() and .off() are asynchronous in system threaded mode
	// and if the calls don't complete, sleep mode is not properly entered.

	// The Cellular.off() requirement is probably a bug. I think it's because when
	// going to sleep in system threaded mode, it's not waiting for the modem to actually
	// go to sleep. As of 0.6.0 it's necessary, otherwise you drop in a weird mode that
	// ends up using 2.8 to 60 mA instead of 132 uA.

	// Resulted in 132 uA power consumption, as it should

	System.sleep(SLEEP_MODE_DEEP, 10); // System.sleep(SLEEP_MODE_DEEP, secDifference); //secDifference not including time to enter sleep mode 

	// This part not reached; sleep mode deep starts over again after setup()


What have you got connected to WKP?
There is a HW flaw in the STM32 that prevents the device from being woken up from deep sleep when WKP is held HIGH at the moment of entering deep sleep.


I believe it’s disconnected, should I tie it to ground?


Having the pin floating may cause issues, so adding a 10k pull-down resistor would at least take that off the list of possible causes.


Thank you for the suggestion.
I’ve connected 10k resistor between WKP and GND. The same behavior I described initially kept happening.
Maybe you have more suggestions?
Thank you,