I was curious if you (or anyone else) could explain to me if there’s any difference between these two pieces of code? With my original code, I would still have the occasional blocking Electron that required a manual reset to be done.
So when Particle.connect() ends up blocking, it still wouldn’t time out after 3 minutes would it? Seems like both pieces of code effectively do the same thing. I’ve had devices block with my Original code (System Threading + Manual) so I’m guessing FW-side there isn’t much else to do here to reduce the issue?
I’m probably missing something here, but I would think your “Revised” Code should work.
If a Publish was missed using the Revised Code, maybe it was just that the Electron couldn’t connect to the cellular network during the 3 minutes (poor signal, etc) ?
I would guess you would rather go to sleep in that case verses Reset.
It was suggested to me in another Thread to skip the “else” and go to sleep after the waitFor, since it either Published or Not (didn’t really matter). Again, I’m not sure if this helps in your Project.
When the connection attempt fails, I reset the device up to 3 times, before I put it back into Sleep mode. I did this, because my devices don’t publish much but when they do it’s pretty important they do so successfully.
Anyway, publishes being missed isn’t the real issue here to me, as that’s simply related to overall product constraints. The real problem I have is that after I call particle.connect() in my Original Code, the device occasionally blinks green endlessly for hours, sometimes until the battery goes dead alltogether. Usually the 3-minute timer described in my code kicks in correctly and prevents this, but not always.
As far as I understand, since particle.connect() is blocking, timers aren’t failproof and there isn’t a good way (?) to mitigate the issue FW side. Hence why I’m already adding in the HW Watchdog in my next version.
Note: trueReset() in my code puts the device into Deep Sleep for 30 seconds before waking it up. Any connection failures are therefore always followed by Deep Sleep.
Check the battery and voltage converter voltages during this constant flashing green connection issue because I saw that happen when the battery voltage was low and not when it was higher.
Plus it’s a cold time of year so colder temps usually cause battery voltages to drop vs warmer temps. Cellular RSSI will help determine if your the device has weak cellular signal as weather can affect signal strength also.
It’s definitely an RSSI issue. I have my devices deployed in a few locations. At our main site I’m getting RSSI values of -50 to -65 and things are going great; the couple of sites I’m having issues at show values of -80 to -95.
I’d rule out cold temperature as I had a few of them in a freezer (-18C) for months, and the voltage output remained satisfactory. In the field we usually don’t see the temperature drop below -5C.
The RSSI is one of the reasons I decided to go with Bell SIMs over the Particle ones. Can’t wait to test those and see whether it improves the situation.
I would save the date and time of the data you are trying to send in retainer memory and only clear it after a successful publish. That way you can just go back to sleep if it does not connect and know the data will eventually make it on the next successful connection.
Sounds like you have ruled out cold weather as the issue which is good.
@Vitesze, have you experienced an Electron doing this when using if (waitFor(Particle.connected, 180000)) in Threaded + Manual Modes?
I'm asking because I have Electrons deployed in a similar situation (very sensitive to wasting battery power) and haven't noticed this. But as I said before, I don't have near as many deployed as you do.
I step through the modem connect/disconnect process with "safe" delays (seen here), but I've also read where that shouldn't be necessary.
Maybe you need the "safe" delays with the Particle.process() calls?
1 Sec Delay after each action => for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
I even tried disconnecting the Cellular antenna during the connection process many times and could never get the Electron to hang-up and not go to sleep.
This Code Flow "should" mitigate your RSSI issues at the problem sites (similar to no antenna).
It’s too early to say yet if I have any blocking code with if (waitFor(Particle.connected, 180000)). I’ll need to wait a bit longer for that.
Thanks for your tips! I now have something like this:
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
void loop() {
....
Cellular.on();
for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
Particle.connect();
for (uint32_t ms = millis(); millis() - ms < 10000; Particle.process());
if (waitFor(Particle.connected, 180000)) {
Particle.publish(publish, data, PRIVATE);
for (uint32_t ms = millis(); millis() - ms < 5000; Particle.process());
...
}
else {
Particle.disconnect();
for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
Cellular.off();
for (uint32_t ms = millis(); millis() - ms < 2000; Particle.process());
trueReset();
break;
}
...
The delays I had previously very well could’ve impacted my code before too.
With the code above, I still appear to have some blocking issues (i.e. blinking green way beyond 180s). Additionally, shutting off the cellular also seems to take quite some time (i.e. breathing blue for 1-2m).
I observed this behaviour in multiple Electrons across my product in the past 10 days.
I will be able to test my new HW Watchdog feature soon, which should fix it partially (at least limiting the blocks to x minutes).However, it’s still concerning that this issue can be so prominent.
Blinking green does not indicate a blocking issue with Particle.connect() per se. Your device is searching for a cellular network, which can in fact take several minutes. Particle.connect() relies on there being a cellular connection. Thus, if you have no cellular connection, Particle.connected() will never return true.
Breathing blue means that you are in listening mode, which is a state of Cellular disconnection. For me Cellular.off() is pretty quick. Here is the code I use to perform a reset that includes the modem reset:
if (resetNow)
{
delay(1000);
SINGLE_THREADED_BLOCK()
{
// A reset was triggered somewhere, handling after operations complete
if (alsoResetModem)
{
// The reset is related to cellular connectivity, so also resetting modem first
log(LOG_LVL_INFO, LOG_GRP_WD,"Disconnecting from Particle cloud before resetting modem...");
Particle.disconnect();
delay(100);
log(LOG_LVL_INFO, LOG_GRP_WD,"Resetting Modem...");
#if Wiring_Cellular
// 16:MT silent reset (with detach from network and saving of NVM parameters), with reset of the SIM card
Cellular.command(30000, "AT+CFUN=16\r\n");
delay(100);
Cellular.off();
#elif Wiring_WiFi
WiFi.off();
#endif
delay(200);
}
// Now let's reset the electron
log(LOG_LVL_INFO, LOG_GRP_WD,"Resetting Device...");
reset_handler();
System.reset(reset_reason_code);
}
}
Regardless, if your observed problem is that a device is blinking green for a long, long time, the waitFor code you have above will technically work (though I’d add the Cellular command to fully reset too), but I recommend increasing your timeout beyond 180sec to maybe 240sec, which is where I’ve successfully had it. Keep in mind that if your location just doesn’t have Cell service, no firmware change can fix that.
In this code example, how could this occur though? I would expect the Electron here to attempt a connection for 3 minutes. If after 3 minutes no connection has been established, it should turn off the cellular and reset within a few seconds. The LED pattern I expect is:
Blinking Green - (Rapid-blinking Cyan) - Breathing Blue - Reset
I would expect the Breathing Blue phase to only last 1-3 seconds (based on how long it takes to actually turn off the cellular) but I noticed a few cases where it took as long as a few minutes.
if (waitFor(Particle.connected, 180000)) {
Particle.publish(publish, data, PRIVATE);
for (uint32_t ms = millis(); millis() - ms < 5000; Particle.process());
...
}
else {
Particle.disconnect();
for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
Cellular.off();
for (uint32_t ms = millis(); millis() - ms < 2000; Particle.process());
trueReset();
}
This is also in response to @justicefreed_amper , as I understand cell service may be poor and Particle.connected() won't return true, but this should still mean the device resets after exactly 3 minutes. I've seen it exceeding this amount by a few minutes a few times.
I don't believe (1) should ever happen, as Cellular.on() in my code is always followed by Particle.connect(). Would (2) be achieveable by calling Cellular.off() as well? Right after connecting, I publish my data and then immediately call Particle.disconnect() + Cellular.off()
I'm not aware of anything else in my firmware that could cause issues like this but I'm probably overlooking things. Connectivity is still a huge culprit with my devices for some reason.