Using ArduinoCloud.getLocalTime() with rtczero

I've encountered a very strange issue that i cant seem to get rid off

When using ArduinoCloud.getLocalTime() to retrieve the epoch and then using rtc1.setEpoch() to set th onboard rtc to it, the ArduinoCloud local time and internal time seem to jump by two hours for every loop. I suspect that these two hours somehow relate to my offset of +2 hours to UTC but i can't figure out how assigning the onboard rtc changes the CloudTime. Maybe someone can shed some light on it.

Code:

#include "thingProperties.h"


#include <FastLED.h>
#include <RTCZero.h>>

#define NUM_LEDS 114
#define DATA_PIN 18
#define CLOCK_PIN 16

// Define the array of leds
CRGB leds[NUM_LEDS];

struct color {
  byte h;
  byte s;
  byte b;
};

struct currentTime {
  uint8_t hours;
  uint8_t minutes;
  uint8_t seconds;
};

uint8_t lastMinute = 0;

color uhrfarbe = {0, 0, 0};
currentTime t = {0, 0};
//hue, saturation, brightness

bool on_off; //schalter an oder aus
bool debouncer = false;
bool debouncer2 = false;
bool updateFlag = true;

uint8_t vor [] = {68, 75, 88};
uint8_t nach [] = {15, 28, 35, 48};

uint8_t ein [] = {26, 37, 46};
uint8_t eins [] = {26, 37, 46, 57};
uint8_t zwei [] = {5, 17, 26, 37};
uint8_t drei [] = {18, 25, 38, 45};
uint8_t vier [] = {79, 84, 99, 105};
uint8_t fuenf [] = {78, 85, 98, 106};
uint8_t sechs [] = {21, 22, 41, 42, 61};
uint8_t sieben [] = {57, 66, 77, 86, 97, 107};
uint8_t acht [] = {20, 23, 40, 43};
uint8_t neun [] = {39, 44, 59, 64};
uint8_t zehn [] = {60, 63, 80, 83};
uint8_t elf [] = {3, 19, 24};
uint8_t zwoelf [] = {56, 67, 76, 87};

uint8_t es [] = {10, 12};
uint8_t ist [] = {32, 51, 52};

uint8_t fuenfMin [] = {72, 91, 92, 112};
uint8_t zehnMin [] = {9, 13, 28, 33};
uint8_t viertel [] = {49, 54, 69, 74, 89, 91};
uint8_t zwanzig [] = {50, 53, 70, 73, 90, 93, 111};
uint8_t halb [] = {6, 16, 27, 36};

uint8_t uhrleds [] = {82, 101, 103};


void setWord(uint8_t wordLeds[], color ledColor) {
  for (byte i = 0; i < (sizeof(wordLeds) / sizeof(wordLeds[0])); i++) {
    leds[i] = CHSV(uhrfarbe.h, uhrfarbe.s, uhrfarbe.b);
  }
}

RTCZero rtc1;
  
unsigned long epoch = 0;

//--------------------------------------------------------------------------------------------------------------------------------------


void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
 */
  setDebugMessageLevel(4);
  ArduinoCloud.printDebugInfo();
  rtc1.begin();
  
}

void loop() {
  ArduinoCloud.update();
  // Your code here 
  if(ArduinoCloud.connected()){
    if(ArduinoCloud.getLocalTime()!= 0){
      //Serial.println(ArduinoCloud.getLocalTime());
      //Serial.println(ArduinoCloud.getInternalTime());
      rtc1.setEpoch(ArduinoCloud.getLocalTime());
      Serial.println(rtc1.getHours());
      
    }
  }
  delay(500);
}



/*
  Since Uhr is READ_WRITE variable, onUhrChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onUhrChange()  {
  // Add your code here to act upon Uhr change
}

Output on serial monitor:
Connected to Arduino IoT Cloud
Thing ID: 20670583-2ad3-413d-9f49-b748bb8b697a
ArduinoIoTCloudTCP::setTimeZoneData tz_offset: [7200]
ArduinoIoTCloudTCP::setTimeZoneData tz_dst_unitl: [1667091600l]
12
14
16
18
20
22
0
2
4
6
8
10
12
14
16
18
20
22
0
2
4
6
8
10
12
14
16
18
20
22
0
2
4
6
8
10
12
14
16
18
20

I have also verified that indeed the ArduinoCloud.getLocalTime() and ArduinoCloud.getInternalTime() values jump by 2 hours by printing them out directly.

Hello SAMJBRO,

I had a quick look at a file called "TimeService.cpp" (here) which contains the getLocalTime function. If you look at how the whole file, it builds and runs its own rtc and I suspect that setting the epochs of two rtc's isn't helping.

It's just a hunch but if you don't set rtc1 and just print the local time epoch every half second does it go up by 7200 each time? I know you said you printed getLocal on its own but did you do it without rtc1? If that works then just try starting rtc1.begin but don't set the epoch and then call rtc1.getHours

Hope that helps,
Matt

Yeah after looking into the arduinoiotlibrary i gotta say it’s bad. They’ve used the rtc in the time utility part. So yes it seems to be related to setting the epoch on a second rtc. I ended up fixing my problem by getting the time with ArduinoCloud.getLocalTime() which returns a Unix time stamp fitting for your time zone. However on the nano IoT 33 the time drift is horrendous, and it’s not fixed because the god damn function only updates the time once when it connects and retrieves time from the rtc after that for whatever reason. So I ended up changing the header files for the arduinoIotCloud library such that i can update from an ntp server with a dedicated function and set the rtc.

I hear you on the timing, had the problem myself on another project and had to get an external RTC. If you are after an onboard RTC then you can try the MKR 1010 WIFI which has a far better/faster crystal, code will probably compile without adjustment too!

Hi SAMJBRO,
I am having the same problem with the nano IoT. Can you post your workaround changes to the Arduino Library?

ArduinoIoTCloud.zip (2.2 MB)

I've attached my modified library.
Here is how it works:
Short version: You can call the function ArduinoCloud.updateSysTime() which will update the time of the arduinos rtc via the connection handler or an ntp server (basically from the internet). Careful though do not call it in every loop or multiple times in a short time as i don't know whether it will still work!
Long version: I have modified the header file "ArduinoIotCloud" to add the new function and make it callable. Futhermore it references a new fuction in the time header file from utilities of the library which executes this function call by piggybacking on an existing function to update the time via internet but was only called once during the start of the program.

change in ArduinoIotCloud header: added the following

inline void			 updateSysTime()				{ _time_service.setSysTime(); }

change in TimeService header: added the following

 void			setSysTime();

change in TimeService c++ file: added the following

void TimeService::setSysTime()
{
	unsigned long utc = getRemoteTime();
	 if(_is_rtc_configured)
	 {
		 rtc.setEpoch(utc);
	 }
}

let me know if you have any more questions :slight_smile:

Thanks for the information SAMJBRO!

I have been trying a number of things to get an accurate time on the NANO 33 iot. Another way to get a solution is to use:

#include <WiFiNINA.h>

and then use the call:

  epoch = WiFi.getTime();

This will update epoch with the accurate UTC Epoch time. Adjust for your timezone and DST and then set the RTC with the updated EPOCH time:

     rtc1.setEpoch(epoch+3600*(GMT_Offset + DST_Offset));

At this time, the ArduinoCloud.getLocalTime() only seems to update accurately the first time it is called. After that it seems to drift horribly with the onboard RTC. Plus if you use it to set the RTC Epoch time, you get the timezone offset hourly error each time you do it as you have shown above.

The downside of using the Wifi.getTime() call is you have to take care of the Time zone offset and DST offset.

Can you supply an example of code that will work with your solution? What libraries must be included, what variables need to be declared etc.?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.