Is the Particle.keepAlive() function needed in automatic mode? Can someone advise me on the most reliable way to deploy an electron longterm without losing connectivity?

In our application the device will be charged via solar panel. I have noticed that if the battery pack drops below 2.7 volts the undervoltage lockout kicks in and powers down the device. If the battery charges back up to say 2.75 - 2.8 V the electron powers up but fails to reconnect and goes to listening mode. This puts us in a state that is not desirable.

The best thing to do is never get in this situation so we will oversize the battery and solar panel. However, if it did happen I would like to recover i.e, wait for the voltage to reach 3.3V before reconnecting.

Can someone suggest using Automatic, Semi-Automatic, or Manual modes to accomplish a robust link?

Since the Electron uses connectionless UDP you need to tell the grid from time to time that you are still there although you’ve not been sending data.Particle.keepAlive() just sets the interval how often your grid needs to hear of you, so you just call it once and the rest will be done in the background for you.

But the way more interesting question is the other part of your post about the power down/up hysteresis (which seems too narrow).

Maybe that would be a better title to attract attention to the bigger problem.

@Scruff, Thanks for chiming in. So to clarify, Particle.keepAlive() is needed even in AUTOMATIC mode?

Hysteresis:
Maybe the particle team meant to have this behavior? I need to re-simulate this but I believe the device stays connected (?led still breathing cyan) and powered on until the ~2.7V UVLO mark. The device will power up at ~2.75 volts but does not re-connect and goes to listening if I turn the voltage up to 3.3 without reseting the device it stays in listening mode. If I manually press the reset button when the voltage has recovered to ~3.3V the device will reconnect. So there is hysteresis baked in there somewhere but reconnection is lost due to listening mode. This Is why I was thinking SemiAutomatic or Manual modes.

SYSTEM_MODE(SEMI_AUTOMATIC);
setup(){
// Read fuel gauge, check for greater than 3V
}
loop(){
if(!charged){
//go to sleep for a while and check back in 15 minutes?
}
else{
// Do the stuff we need to do
// reconnect to network and resume computing
}
}

Sending “keep alive packets” is needed if your device should stay connected but calling Particle.keepAlive() is only required if you are using a third party SIM which isn’t happy with the default interval between two “keep alive packets” and needs shorter periods.

And for the hysteresis, I’m not quite sure how it actually is set and how it should work.
In my tests I had my Electron drain the battery to 3.0V 0% SoC (fuel gauge readings) and then went into blinking cyan never reconnecting to the cloud due to too little power to finish the task, but it never switched off for over half an hour. But in AUTOMATIC mode I don’t see any point in further draining the battery once we passed that lower limit and also no use in powering back up before we got to a point to at least sustain - let’s say 10min of continous connection.

Having said this I must admit I’ve not really done any representative, repetetive testing but only had a few full charge/discharge cycles over the course of just short a week.

But reading your experience (and what I’ve read reported by others) I thought to see a pattern here.
Maybe @BDub could chime in here as he’s just recently updated the docs on the charging of the Electron.

Sending “keep alive packets” is needed if your device should stay connected but calling Particle.keepAlive() is only required if you are using a third party SIM

@ScruffR, Thanks for your insight. I will do a bit more testing on the UVLO and Hysteresis. In the above statement are you saying that if you are using a Particle SIM card in AUTOMATIC mode you do not actually need to call the keepAlive() function (pings are sent for us)? You said that sending keep alive packets is needed to stay connected but only need to call keepAlive() if you have a third party SIM can you clear that up a little please.

To repeat it:Particle.keepAlive() does not send the pings but only “sets the timer” how frequently the background task should do the pinging for us (call Particle.keepAlive() only once in setup() and leave the rest to the system).
For Particle SIMs the default timer interval is perfect and won’t need to be set explicitly.

I’ve been testing a program using an Electron and a 3rd Party SIM (Rogers in Canada, coincidentally the same network that the Particle SIM cards use). The keep alive period seems to be about 150 seconds.

The program I’m now using to test is a simple light logger that publishes 6 readings every 6 mins. Based on the tips in @rickkas7’s tutorial on 3rd Party SIMs, I assumed keepAlive would not be necessary, so I omitted it to see what happens. The result is that the Particle.publish events do not make it to the Particle cloud. When I include Particle.keepAlive(150), the program works great. Any idea why this would be?

What statement exactly made you think keepAlive() would not be required?
I think to remember that’d only apply if you don’t use the Particle cloud (cell doesn’t need it) or your code keeps in touch with the cloud at least once in 150s - but your 6min are twice that.

“These return data channels take up resources on the carrier network, so they like to clean up the unused ones to free up the resources. The Particle SIM has an unusually long timeout of 23 minutes. Most carriers use a timeout of between 30 seconds and several minutes.
When the return channel is freed, the Electron will continue to breathe cyan, because it doesn’t know that it has occurred. Also, it will still be able to send data to the cloud, so things like Particle.publish will work, and will also restart the return channel if it has been cleaned up.”

That’s apparently my fault. I thought that without a sufficiently short keep alive the return UDP packet path would be lost, and therefore any cloud-to-device operations, like OTA, subscribe, variables and functions would fail. But I thought outbound packets like publish would still work. I might have been wrong about that.