syncTime with deep sleep

Hi All,

I have some electrons out in the wild that wake up, check a sensor, send some data, then go back to sleep. I’m using SYSTEM_MODE(SEMI_AUTOMATIC); and SYSTEM_THREAD(ENABLED); with System.sleep(SLEEP_MODE_DEEP, SLEEP_NETWORK_STANDBY);

My time drifts after a while, and my data publishes are now early by a few minutes. I want to get the Time back on track.

I’ve seen the docs on Particle.syncTime, but am a bit confused about how to proceed. If I put code in my loop to check when the last syncTime happened, will the electron know when the last sync occurred? I believe that millis is reset when the Electron wakes, which leads me to expect that it might not know.

I considered putting syncTime into the setup routine, but don’t want to spend excess data on checking the time every wake cycle, as I’m trying to minimize data use.

Thanks,
J

Usually Particle.syncTime() is called automatically on reconnect, so I'd suspect there might be something else at play too

How do you calculate your sleep time?
When you say

I can't see a sleep periode provided.

Since you are using SEMI_AUTOMATIC and SYSTEM_THREAD(ENABLED) your code might not keep the device awake long enough for the auto-sync to come through and get applied.
You could try using waitFor(Time.isValid, 60000); to wait up to on minute for the sync to finish and then go to sleep.

Sorry, that got cut out, here is the full routine for sleep, I’m waking every 20 minutes (a second before the minute, actually) and the way I know (or think) the time is out of whack is that the publishes appear before the hour by a few minutes. If I flash a new version, the time is as I’d expect, typically 10-20 seconds after the wake time once the unit has made it’s first connection to the cellular network.

void sleep() {
  checkTime();
    if (currentMinute < 20) {
      System.sleep(SLEEP_MODE_DEEP, (((19 - currentMinute) * 60) + (59 - currentSecond)),SLEEP_NETWORK_STANDBY);
    }
    if (currentMinute < 40) {
      System.sleep(SLEEP_MODE_DEEP, (((39 - currentMinute) * 60) + (59 - currentSecond)),SLEEP_NETWORK_STANDBY);
    }
    if (currentMinute < 60) {
      System.sleep(SLEEP_MODE_DEEP, (((59 - currentMinute) * 60) + (59 - currentSecond)),SLEEP_NETWORK_STANDBY);
    }
}

void checkTime() {
    currentHour = Time.hour();
    currentMinute = Time.minute();
    currentSecond = Time.second();
}

This seems overly complicated to me :wink:

Time.local() (or Time.now() since you aren’t exactyl interested in the hour) will give you the current time in seconds since midnight (1.1.1970).
So if you do Time.local() % (20*60) you will get the number of seconds since the last 20-minute boundary and with 20*60 - Time.local() % (20*60) you get the number of seconds to sleep till the next boundary.
No need to deconstruct the UNIX epoch time just to partly “reassemble” it again in the next step.

This would simplify your code above to

  System.sleep(SLEEP_MODE_DEEP, 20*60 - Time.local() % (20*60), SLEEP_NETWORK_STANDBY);

If you want, you can subtract the extra second to wake just before the boundary.
If for some reason the result would be less than some threshold, you could also prevent the device from going to sleep at all

const int wakeBound      = 60 * 20;
const int wakeOffset     = 1; 
const int sleepThreshold = 5;
...
  waitFor(Time.isValid, 10000);  
  int secToSleep = wakeBound - Time.local() % wakeBound - wakeOffset;
  if (secToSleep > sleepThreshold)
    System.sleep(SLEEP_MODE_DEEP, secToSleep, SLEEP_NETWORK_STANDBY);
1 Like

That’s cool, I like it! I’ll put that into place. Much more elegant than the way I was working.
I haven’t previously used modulus…

I’m just sort of bashing my way thru :slight_smile:

But I’m still at a loss to understand why the time of my publishes drifts off with my current code.

Do you think this code will somehow not drift off the way my prior code did? I’ll certainly give it a try.

Thx
J

Have you got a timestamp in the data field of the publish or are you just relying on the timestamp the event gets once it has arrived in the cloud?
If you suspect a discrepancy between your device’s RTC and the actual time (the cloud timestamp should be correct at any time, just reflecting the latency of transport), you should see that when comparing both on one event.
Also when you have poor receiption you might see some extra seconds due to retries.

No, I don’t have a timestamp data field. I was mainly relying on the timestamp in Thingspeak, which is where I view my data. It isn’t a case of the data being delayed (for instance by having a poor connection causing retries, it’s been a case of the data publishing early, most recently it was off by about 2 minutes.

I had considered that the time at Thingspeak could be off, but then I’d flash a new firmware version, and the timing would be correct again. The Thingspeak and webhook timestamps are usually less than a second apart.

I’ve put up a new version of the firmware and will be interested to follow it to see if it slowly gets out of whack again or not. Looking back it appears to take about 15 days to lose one minute, every now and then (about monthly - hard to tell as I still flash new firmware occasionally, which rectifies the issue) it fixes itself.

J

You can always add a deliberate call to Particle.syncTime() once a day.