All, I have been working through the best way to use the AB1805 real time clock / watchdog timer to improve my devices power consumption and reliability. This work is based on @rickkas7 library:
I am looking at the section on cellular connection and taking action in the case of a device not connecting in a reasonable amount of time - in this case 11 minutes. The library includes example code which tracks connection time in mSec and does a power off reset if connectivity is lost for over 2 hours. This code seems to be intended to monitor connection status in the main loop and detect and correct a loss of connectivity. This is perfect for devices that are intended to be connected as my utility powered sensors are.
My code takes a slightly different tack my solar powered sensors only connect every hour to report data and are otherwise disconnected. So, I have moved this code out of the main loop() and put it in a function. Also, sinnce cellular connections take a long time, I am ok with accuracy measured in seconds.
Here is the code I use to connect to Particle:
/**
* @brief Connects to Particle or take steps to recover.
*
* @details You can configure the amount of time to fail to connect to the cloud before doing
* a deep power off for 30 seconds. The default is 11 minutes, and you should not set it less
* than 10. You can set it higher if you want.
* Code modified from the application watchdog app note: https://github.com/rickkas7/AB1805_RK
*
* @return 1 if successful, 0 if uncessful or resets device if it has been over two hours
*/
bool connectToParticle() {
unsigned int maxConnectionSeconds = 11 * 60; // Should not be less than 10 minutes
unsigned long connectionStartTime = Time.now(); // Start the clock
char connectionStr[32];
Cellular.on(); // Needed until they fix this: https://github.com/particle-iot/device-os/issues/1631
Particle.connect();
for (unsigned int retry = 0; retry < maxConnectionSeconds && !waitFor(Particle.connected,1000); retry++) { // wait a second and repeat
if(sensorDetect) recordCount(); // service the interrupt every second
Particle.process(); // Keeps the device responsive as it is not traversing the main loop
ab1805.setWDT(-1); // Pet the watchdog as we are out of the main loop for a long time.
}
if (Particle.connected()) {
sysStatus.connectedStatus = true;
sysStatus.lastConnection = Time.now();
snprintf(connectionStr, sizeof(connectionStr),"Connected in %lu secs",Time.now()-connectionStartTime);
Log.info(connectionStr);
if (sysStatus.verboseMode) publishQueue.publish("Cellular",connectionStr,PRIVATE);
systemStatusWriteNeeded = true;
return 1; // Were able to connect successfully
}
else {
sysStatus.connectedStatus = false;
Log.info("cloud connection unsuccessful");
if (Time.now() - sysStatus.lastConnection > maxConnectionSeconds) {
fram.put(FRAM::systemStatusAddr,sysStatus);
Log.info("failed to connect to cloud, doing deep reset");
delay(100);
ab1805.deepPowerDown();
}
systemStatusWriteNeeded = true;
return 0; // Failed to connect
}
}
and here is how I disconnect:
bool disconnectFromParticle() // Ensures we disconnect cleanly from Particle
{
Particle.disconnect();
waitFor(notConnected, 15000); // make sure before turning off the cellular modem
Cellular.off();
sysStatus.connectedStatus = false;
systemStatusWriteNeeded = true;
delay(2000); // Bummer but only should happen once an hour
return true;
}
bool notConnected() { // Companion function for disconnectFromParticle
return !Particle.connected();
}
I have a few questions and am always open to input on how to do this better:
- In the docs, thee is a comment that Cellular.on() and Cellular.off() are required but that this is a big that should be fixed. Yet, when you follow that link, the issue has been closed.
https://docs.particle.io/reference/device-os/firmware/boron/#connect--1
-
Eleven minutes seems like a very long time to try to connect. In this code, I will be collecting connection time data which I plan to add to my webhook and send to Particle. I was wondering what types of Boron LTE connection times others are seeing.
-
I am a bit worried about taking program flow out of the main loop for so long. I believe this is OK since I am monitoring the watchdog and the counter but, I wonder if there is a way to do this as a function and still keep transiting the main program loop?
Thank you,
Chip