Date and time kept by RTC suddenly change

I have a Portenta Machine Control and using the RTC to keep the date/time for logging. However, after the Arduino has been running for some period (can be a few days or a week), the date and time is suddenly incorrect. For example today I noticed it was set to 2024-11-14 instead of 2024-11-12 and it has been running for about 10 days.

I don't have any logs for this change but I have seen in previous logs that the date/time suddenly changes at a particular moment without any reason. So it's not caused by the Arduino's clock drifting by a few seconds every day over a long period of time

I basically do what's in the example. Arduino_PortentaMachineControl/examples/RTC/RTC.ino at main · arduino-libraries/Arduino_PortentaMachineControl · GitHub

I initialize the clock once in setup() to set the correct date/time . Then I disable that code and reset the Arduino. The program then requests current date/time in the main loop() to timestamp any logs

Has anyone else seen this or know how to fix it?

Can you clarify that moment? Time of day? Time between resets?

I don't have any further details unfortunately. But with "particular" I didn't mean there was something special about the moment. I only mean it jumps from correct to incorrect time/date at once. I remember it jumped from 8pm to 22pm one time. But this last time it jumped ahead 2 days and several hours

I'm reading an analog input once every 10minutes and then print the result with a timestamp. So what I see in my logs is

  • "correct time/date - analog_input value 1"
  • "correct time/date + 10min - analog_input value 2"
  • "correct time/date + 20min - analog_input value 3"
  • "incorrect time/date - analog_input value 4"
  • "incorrect time/date + 10min - analog_input value 5"
/*
  FUNCTION: convert integer to string and padd with 0 to get nr_of_chars
*/
String padding(int value, int nr_of_chars)
{
  String s = String(value);
  int j = nr_of_chars-s.length();
  for (int i=0; i<j; i=i+1) {
    s = "0" + s;
  }
  return s;
}


/*
  FUNCTION: get current_date and current_time
*/
void GetDateTime() {
  // get current date & time
  int year=MachineControl_RTCController.getYear()+2000;
  int month=MachineControl_RTCController.getMonth();
  int day=MachineControl_RTCController.getDay();
  int hours=MachineControl_RTCController.getHours();
  int minutes=MachineControl_RTCController.getMinutes();
  int seconds=MachineControl_RTCController.getSeconds();

  // convert date & time to string  
  current_date=padding(year,4)+"-"+padding(month,2)+"-"+padding(day,2);
  current_time=padding(hours,2)+":"+padding(minutes,2)+":"+padding(seconds,2);
}

So then I just print global string vars current_date and current_time in my logging code.

It sounds like you’re experiencing some significant transients, possibly from a motor being switched with a relay or a mechanical switch. Could you post an annotated schematic showing your wiring setup, along with some clear photos? Please include links to the technical information for the hardware devices and be sure to show all power sources, including batteries and other supplies.

Hi sorry this sketch i made is all i have since i have no access to the setup now

I'm reading the value of 2 passive 4-20mA sensors that are powered by the Arduino. Based on the readings I'm controlling an actuator (johnson controls M9108-AGA-5) to turn a water valve using 2 relays (phoenix 2961105). The actuator is also using the same power supply as the Arduino. There are also waterpumps and waterheaters nearby but connected to 220V AC

I also created a webserver for configuraton on the Arduino (hence the ethernet connection) and i'm logging to USB stick (although that was not connected)

Nothing else is connected to the Arduino

Should I power the actuator with a completely different power supply maybe?

I don’t have one of these and am not familiar with them, but based on my experience with PLCs, I’ll take a guess. I don’t think that setup is necessary, but I can’t fully follow your sketch. For example, USB-A connects to the USB stick, while the micro-USB and Ethernet connect to the PC. However, you have the Portenta Control disconnected from the previously mentioned items. There are also various voltages involved, but it’s unclear what voltages are where or how they are derived. Ensure that all grounds are properly connected.

It is probably not your main problem but I'd look at sprintf() for formatting the time and date strings instead of the String class methods.

Edit

Maybe something like this:

/*
  FUNCTION: get current_date and current_time
*/
void GetDateTime() {
  // get current date & time
  // just to abbreviate the object name
  RtcControllerClass * rcc = &MachineControl_RTCController ;
  char buf[ 20 ] = {0} ;
  snprintf( buf, "%04d-%02d-%02d",  rcc->getYear()+2000, rcc->getMonth(), rcc->getDay() ) ; 
  current_date = String( buf ) ;
  snprintf( buf, "%02d-%02d-%02d",  rcc->getHours(), rcc->getMinutes(), rcc->getSeconds() ) ;
  current_date = String( buf ) ;
}

But if function GetDateTime() is called from an interrupt service routine I don't believe you can create/manipulate Strings in it because these use malloc/free in the background and these may not be re-entrant.

There is only one 24V adapter that powers everything. The portenta control powers the 4-20ma sensors (Analog In pins which include 24v out) and the relays via Digital Out pins which provide 24V when enabled . The valve connected to the relays (output side) is connected to the same power supply directly

The USB stick is only needed for writing logs. The ethernet cable for checking the status page. The microusb for programming. So these connections are all optional and can be disconnected at any time

I don't use advanced things as interrupts :). I use a simple main loop() that calls some functions.

void loop() { 
  GetDateTime();
  CheckUSB();
  CheckpH() 
  CheckTemperature();
  CheckValve();
  WebListenForClients();
  BlinkStatusLed();
}

so at the start of the loop i refresh the time and date strings. These then may be printed in the other functions so the time/date is not super accurate if there's some delay() used somewhere.