ArduinoCloud.getLocalTime() very inaccurate on MKR WiFi 1010

Hi all,

I'm using an Arduino MKR WiFi 1010 board. When I try out the Simple RTC sketch from the RTC Zero library, the RTC keeps time pretty well. Maybe loses or gains a second or two per day. Note, the Simple RTC sketch has to be manually initialised with time and date, and does not connect to wifi or sync with a NTP server. It's totally dependent on the SAMD RTC function and the clock source feeding it. So there can't be too much wrong with the underlying hardware and framework of the MKR 1010 RTC.

But when I call the ArduinoCloud.getLocalTime() function repeatedly (in a different sketch), the returned time gradually drifts (runs slow) by a minute or so per hour.

Is there some sort of restriction or requirement that I'm not aware of regarding how to call the ArduinoCloud.getLocalTime() function in order to get accurate time?

I'm aware that I can set TimeService.setSyncInterval(xxx) to force a frequent sync with an NTP server if I need more accurate time. But why is the time so badly inaccurate in the first place?

I thought I had read on this forum that the ArduinoCloud.getLocalTime() function uses the RTC Zero library, so there doesn't seem to be any reason why the time should not be much more accurate than it is.

You can see from the serial output I've attached that the function loses about 5 sec or so every time I call it, 5 minutes apart. Surely this can't be expected behaviour?

Any suggestions? Sketch and output below Thanks.

#include "arduino_secrets.h"
#include "thingProperties.h"
#include <U8x8lib.h>
#include <TimeLib.h>
#define TIMELOOPTIME 300000

tmElements_t timeStructure;
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE); 

bool toggle;
int timeLoopTimer;
unsigned long UnixTime;

void setup() {
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(9600);
  delay(1500);
  u8x8.begin();
  u8x8.setFont(u8x8_font_courB18_2x3_f);
  initProperties();
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  setDebugMessageLevel(4);
  ArduinoCloud.printDebugInfo();
    while(ArduinoCloud.getLocalTime() == 0){    
    ArduinoCloud.update(); 
    delay(500);
  }
  digitalWrite(LED_BUILTIN, LOW);
  timeLoopTimer = 200000;
}

void loop() {

  if ((millis() - timeLoopTimer) > TIMELOOPTIME){
    timeLoopTimer = millis();
    UnixTime = ArduinoCloud.getLocalTime();
    breakTime(UnixTime, timeStructure);  // breakTime breaks Unix seconds into HH, MM, SS etc.  

    toggle = !toggle;
    digitalWrite (LED_BUILTIN, toggle);
    u8x8.clearDisplay();
    u8x8.setCursor(0, 3);

    Serial.print("Unix Time:             ");
    Serial.println(UnixTime);   
    u8x8.print(timeStructure.Hour);
    Serial.print("timeStructure.Hour:    ");
    Serial.println(timeStructure.Hour);
    u8x8.setCursor(6, 3);
    u8x8.print(timeStructure.Minute);
    Serial.print("timeStructure.Minute:  ");
    Serial.println(timeStructure.Minute);
    u8x8.setCursor(12, 3);
    u8x8.print(timeStructure.Second);
    Serial.print("timeStructure.Second:  ");
    Serial.println(timeStructure.Second);
 }

  ArduinoCloud.update();  
}

Serial output:

14:45:24.489 -> Unix Time:             1720968324
14:45:24.489 -> timeStructure.Hour:    14
14:45:24.489 -> timeStructure.Minute:  45
14:45:24.489 -> timeStructure.Second:  24
14:50:24.448 -> Unix Time:             1720968617
14:50:24.487 -> timeStructure.Hour:    14
14:50:24.487 -> timeStructure.Minute:  50
14:50:24.487 -> timeStructure.Second:  17
14:55:24.496 -> Unix Time:             1720968911
14:55:24.496 -> timeStructure.Hour:    14
14:55:24.496 -> timeStructure.Minute:  55
14:55:24.542 -> timeStructure.Second:  11
15:00:24.594 -> Unix Time:             1720969204
15:00:24.594 -> timeStructure.Hour:    15
15:00:24.594 -> timeStructure.Minute:  0
15:00:24.594 -> timeStructure.Second:  4
15:05:24.669 -> Unix Time:             1720969498
15:05:24.669 -> timeStructure.Hour:    15
15:05:24.669 -> timeStructure.Minute:  4
15:05:24.669 -> timeStructure.Second:  58
15:10:24.683 -> Unix Time:             1720969791
15:10:24.683 -> timeStructure.Hour:    15
15:10:24.683 -> timeStructure.Minute:  9
15:10:24.683 -> timeStructure.Second:  51

hi @sciroccotorc i had a look at this issue some time ago. And the root cause seems to be the usage of RTC and WDT at the same time. If you try to disable the watchdog you should get more accurate time results.

Hi @pennam, thank you very much, that does seem to be the issue.

For anyone that's not aware, the watchdog can be disabled by including the "false" argument in setup() as follows:

ArduinoCloud.begin(ArduinoIoTPreferredConnection, false);

Of course, this does now mean that the watchdog is disabled and will not carry out the function for which it was intended, namely a reset of the processor when there are long-term loss of comms to the cloud, in the hope of re-establishing comms.

So you have to make a judgement call for your application; either, no reset of the processor and potential hanging / blocking behaviour (but time will be pretty accurate): or, reset of the processor on loss of comms for more reliable comms, but inaccurate time which you may have to compensate for by syncing with a NTP server using:

TimeService.setSyncInterval(sec);

Bearing in mind that the getLocalTime() time does resync once every 24 hours (IIRC) anyway.