Does calling time_t t = now(); over and over cause a RTC to loose time?

I have just started playing with a DS3231 RTC for a new project im working on and have found its loosing minutes over the course of half an hour.

I have a feeling its to do with the fact im calling the time_t t = now() function within each loop thats updating the LCD display which I read somewhere causes a very small time loss due to it taking a reading. Since my printCurrentTime function is being called constantly its taking that reading many times per second.

The problem is if I call the time_t t = now() in the setup() function then my entire time/date reads zero so im forced to do it in the function at the moment.

Any suggestions? Note I cannot add any delay() into my main loop for other reasons.

My print time function

int printCurrentTime(){
  time_t t = now();
  int _second = second(t);
  int _minute = minute(t);
  int _hour = hour(t); 
  int _day = day(t);
  String _month = "";
  int _year = year(t);
  int tempMonth = month(t);
  
  if(tempMonth==1){_month = "January";}
  if(tempMonth==2){_month = "February";}
  if(tempMonth==3){_month = "March";}
  if(tempMonth==4){_month = "April";}
  if(tempMonth==5){_month = "May";}
  if(tempMonth==6){_month = "June";}
  if(tempMonth==7){_month = "July";}
  if(tempMonth==8){_month = "August";}
  if(tempMonth==9){_month = "Seprember";}
  if(tempMonth==10){_month = "October";}
  if(tempMonth==11){_month = "November";}
  if(tempMonth==12){_month = "December";}
  
  if(_second<10){
    LCD.setColor(0, 0, 255);
    LCD.print("",69,302);
    LCD.printNumI(_second,74,302);
  }
  else{ LCD.printNumI(_second,69,302);}
  
  LCD.setColor(255, 255, 255);
  LCD.printNumI(_hour,20,302);
  LCD.print(":",36,302);
  LCD.printNumI(_minute,45,302);
  LCD.print(":",61,302);
  
  LCD.printNumI(_day,110,302);
  LCD.print(_month,132,302);
  LCD.printNumI(_year,205,302);
}

make your update frequency conditional

int printCurrentTime()
{
  // less than a second since last update?
  if (millis() - lastTimeDisplay() < 1000) return 0;
  lastTimeDisplay = millis(); // update lastTimeDisplay 

  time_t t = now();
  int _second = second(t);
  ...

you can reduce the amount of RAM used by your code by using smaller datatypes uint8_t is unsigned int of 8 bits 0…255

  uint8_t _second = second(t);
  uint8_t _minute = minute(t);
  uint8_t _hour = hour(t); 
  uint8_t _day = day(t);
  String _month = "";
  uint16_t _year = year(t);
  uint8_t int tempMonth = month(t);

if the month is found do not test the others. (you better make an array of the month names)

  if (tempMonth == 1) {_month = "January";}
  else if (tempMonth == 2) {_month = "February";}
  else if (tempMonth == 3) {_month = "March";}
  else if (tempMonth == 4) {_month = "April";}
  else if (tempMonth == 5) {_month = "May";}
  else if (tempMonth == 6) {_month = "June";}
  else if (tempMonth == 7) {_month = "July";}
  else if (tempMonth == 8) {_month = "August";}
  else if (tempMonth == 9) {_month = "Seprember";}
  else if (tempMonth == 10) {_month = "October";}
  else if (tempMonth == 11) {_month = "November";}
  else if (tempMonth == 12) {_month = "December";}

Why do only the seconds have a leading zero?

  if(_second<10)
 {
    LCD.setColor(0, 0, 255);
    LCD.print("",69,302);
    LCD.printNumI(_second,74,302);
  }
  else{ LCD.printNumI(_second,69,302);}
  
  LCD.setColor(255, 255, 255);
  LCD.printNumI(_hour,20,302);
  LCD.print(":",36,302);
  LCD.printNumI(_minute,45,302);
  LCD.print(":",61,302);
  
  LCD.printNumI(_day,110,302);
  LCD.print(_month,132,302);
  LCD.printNumI(_year,205,302);
}

Great tips ill implement them and finish the lading zero code i was working on!

Should I been creating a lastTimeDisplay function somewhere??

Yep, as global variable - type - unsigned long

Horendus: I have a feeling its to do with the fact im calling the time_t t = now() function within each loop thats updating the LCD display which I read somewhere causes a very small time loss due to it taking a reading.

I've read posts from other people reporting similar behaviour. I think you need to control how frequently you read the RTC. You do already have a reasonable accurate timer in the Arduino so it's capable of timing short intervals perfectly satisfactorily for itself. Is there any need to read the RTC more often than once per second?

The only reason I was calling the RTC over and over was because I was finding time_t t = now() was returning Zero if called during the setup() function where I thought it should be placed.

The way I thought the library worked was you can call time_t t = now() anywhere once, then make sure you declare setSyncInterval(seconds) in the setup so the arduinos software clock sync with the hardware RTC on regualr intervals.

Can anyone explain the correct way I should be handling this?

Horendus: The way I thought the library worked was you can call time_t t = now() anywhere once, then make sure you declare setSyncInterval(seconds) in the setup so the arduinos software clock sync with the hardware RTC on regualr intervals.

I assume you're using the DS3231RTC library, although there have been several versions of it and you didn't say which version you're using. I haven't used that library myself but by my reading of the documentation calling now() merely reads the clock - it doesn't set it. You need to configure the library by calling setSyncProvider(getTimeFunction) to set the external time provider and setSyncInterval(interval) to set the number of seconds between re-syncs. It looks as if you can also explicitly set the time yourself.

There is a working example in the playground and others such as http://www.pjrc.com/teensy/td_libs_DS1307RTC.html which I expect would show you how the library is expected to be used - if this is the library you're using.

The DS1307 and similar chips do not, I believe, have any problems about being read multiple times, they guarantee correct reading even when the clock is changing under your feet by using shadow registers for the interface - when a I2C start condition occurs the true clock state is copied to the shadow registers and the results are read from those.

If the library you use does the right thing (just reading the time registers with a single transaction) there shouldn't be any issues like this. Clock accuracy depends on the crystal, its ground-plane and the backup battery.

In particular the xtal oscillator is ultra low power and sensitive to noise from nearby circuitry - the xtal should be mounted over a ground plane on the board and no high-current wiring (such as supply traces) should run near it. When the RTC is a separate break-out board that just means keep it away from other circuitry.