Sleep with Network Standby on Electron

Hi there. I’d like to use the System.sleep() function with Network Standby to get the lowest power state from the board without having to re-register with the network at every wake-up. So with core firmware 0.5.1 I’m making the following call:


I have a few questions:

  1. I call System.sleep() at the end of loop() and then expect everything to be tickety-boo when loop() is called again. However, what I’m finding is that when loop() is called after waking up from sleep the code in loop() stalls for some time and, also, the device re-handshakes with the server (the log says “device came on-line”) when it first publishes after waking up. If, however, I insert a 5 second delay at the start of loop() this problem goes away. I think the reason is that my Serial.printxx() debugging calls are stalling because USB has not sorted itself out and, for some reason, the core firmware is deciding that it needs to re-handshake. Is this expected behaviour? Aside from conditionally-compiling out all my calls to Serial.printxx(), is there another way to avoid having to insert the 5 second delay?

  2. I don’t want the system to wake up on any pin rising or falling: is there a null or NC pin I can specify in the call to System.sleep() to indicate this?


1 Like

I am using sleep() with SLEEP_NETWORK_STANDBY too and noticed the same that the log says device came online every time. But does this really mean that the device is doing the handshake again ? :open_mouth:

I’m going by the LED flashing cyan (first slowly, then quickly), which I think means it’s performing a handshake:

The handshake with the Particle cloud is not the heavy thing SLEEP_NETWORK_STANDBY should prevent.
It rather avoids the heavy impact of renegotiating with the cell towers.

Apart from not seeing this as a problem, do you mean when you add the delay you don't get the "device came online" message and a different color blink pattern?

Understood, but it costs me money and time for no reason that I can see. And why would a 5 second delay work around it?

Yes, that’s correct.

What is the blink sequence you see then?

With no 5 second delay I see slow then rapid flashing cyan and the web log shows “device has come on-line” (or whatever the words are) followed by my published data. If I add a 5 second delay at the start of loop() I see breathing cyan only and I do not see “device has come on-line”, I just see my published data.

@RobMeades, what SYSTEM_MODE have you specified (if any) for your app? Do you have SYSTEM_THREAD enabled? Cloud connectivity would be lost during sleep so upon waking, the cloud connection would need to be re-established. Adding the 5 second delay may be “hiding” the cloud re-connection since the background tasks will run during the delay. You may be able to achieve the same results by waiting for Particle.connected() to be true. Have you tried this?

1 Like

SYSTEM_MODE is the default (I have not specified one). SYSTEM_THREAD is not enabled, I’m just using one boring loop. Under these circumstance is it possible for handshaking to be performed and me not know about it? Would Particle.connected() benefit me under these circumstances?

@RobMeades, the default is single threaded, AUTOMATIC mode. In such case, the firmware will need to get processing time to reconnected to the cloud, explaining why adding the delay(5000); works since, for long delays, the firmware automatically calls Particle.process() so as not to block the system firmware. With SYSTEM_THREAD(ENABLED), the system firmware and the user app get their own threads so the re-connection happens without the delay being necessary. HOWEVER, in either case, you should always make sure to check Particle.connected() to be sure you have connectivity before doing any cloud operations. This is just good practice!

I highly recommend adding SYSTEM_THREAD(ENABLED) to your app, along with checking for OR waiting for Particle.connected() at the start of your app. BTW, checking this way will guarantee the “real” wait for the cloud to reconnect instead of an assumed 5 sec time. :wink:

1 Like

Aaaah, that makes a lot of sense. I’m still not sure I understand why I see the “device came on-line” message in one case and not the other though. Why would running the processor from RTC require a new handshake under any circumstances? Nothing has been lost and time has been retained.

@RobMeades, you are deep sleeping the processor during which time the cloud connection will not be maintained. However, the cellular connection to the carrier will be maintained by the Ublox module (since you specified SLEEP_NETWORK_STANDBY). The “device came on-line” message may be an artifact of the Particle Dashboard and I’m not sure why you get it in one instance and not the other. Replace the delay(5000) with the following and try it again:

waitUntil(Particle.connected);   // wait until cloud connection re-established

Sure Particle.connected() became false (aka connection to the Particle servers got lost) the moment you sent the device to sleep (not for the server as UDP is connectionless anyway, but for the device).

And retaining the time has only to do with the RTC but nothing with the Particle cloud connection.

But the STM32F205 maintains RTC even during deep sleep, there is no reason to lose time. Still don’t understand why any re-handshaking is required.

I’m still confused. I don’t see why the state of particle connection is affected by processor state. The network connection is still there, the RAM is still there, the time is still there, nothing has changed, the processor just happens to be sleeping. What’s that got to do with the particle connection?

But it could have!

Default SYSTEM_MODE(AUTOMATIC) requires an active cloud connection in order to run your code, but while sleeping (which could have been for days) your device could have been taken anywhere, even to a place without cell network, but to actually know if the cloud is available your device needs to check - how would it do that without trying to talk to the cloud?

@RobMeades, since you have SYSTEM_MODE(AUTOMATIC) specified (by default), the Electron will re-establish its (secure) connection to the Particle Cloud not (just) for synchronizing time but to allow your app to use cloud code like Particle.variable(), Particle.function(), Particle.publish, etc. If you don’t use any of these in your code, you should consider running in SYSTEM_MODE(SEMI_AUTOMATIC).

Ah, so the device goes into particle-not-connected state to mirror what the server-side sees? The network connection is there in all cases, of course, but the networks don’t implement a means to wake up a device when a downlink IP packet is sent from the server so, as far as the server is concerned, the device is disconnected.

I suppose my expectation was that the application controls processor state as it knows how the device is being used, what might happen to it, etc.; the application is built for the device for that very purpose. For instance, if the device is nailed to a wall and so can’t go anywhere. The application also needs to save power appropriately. In this case I have an accelerometer attached and so I know perfectly well when motion is occurring and it causes me to wake up.

I think you’re right that SEMI_AUTOMATIC is for me: don’t connect until it is required. One question: in SemiAutomatic operation, what governs when a new handshake is required?

1 Like

Your code needs to call Particle.connect().

Since UDP is connectionless the servers see the device disconnected most the time (but report it connected even if it isn't - don't ask ;-))

1 Like