Suggestions for RTC code and updating display

Hello all:

Adding a RTC clock to a project I am working on and it will display the time on a OLED display using the U8G2 library. Have it all working, the clock gets updated in the main loop, where there is some not critical timing but nonetheless I only want to update the display every second. Accurate clock is expected but if the display isn't updated exactly every second on the display it's not a big deal if the processor is busy for 50ms doing something else in the main loop.

Here is the code that I am using that I am using with all the project code stripped out. I thought it would be best just to test when the second changes and then update the display with the correct time. I struggled quite a bit with the date and time variables so this is where I ended up. Seems to work fine, but, but wondering if what I have done is the most efficient or is there a better way.

#include "RTClib.h"

RTC_PCF8563 rtc;

 DateTime currentTM;
 DateTime oldTM;

void setup() {

Serial.begin(9600); /* Define baud rate for serial communication */

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
 }

  if (!rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
  
  // Comment out below lines once you set the date & time.
    // Following line sets the RTC to the date & time this sketch was compiled
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  
    // Following line sets the RTC with an explicit date & time
    // for example to set January 27 2017 at 12:56 you would call:
    // rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));
 }
   rtc.start();
   delay(500);
     
 }

void loop() {

 currentTM = rtc.now();


 if (currentTM.second()!= oldTM.second()) {
    oldTM = currentTM; 
    //UPDATE OLED
 }


}

https://github.com/jandrassy/KitchenTimerClock/blob/master/KitchenTimerClock/KitchenTimerClock.ino

Thanks for the suggestion, looking through it and it appears the author is utilizing millis() every second to update the display. I am using the millis() for some other timing in my project so I guess no reason why I couldn't do the same.

Just curious if anyone can see anything wrong with my approach of just monitoring the seconds change to trigger a refresh/update?. Seems to work, not sure if one is any better than the other. Suppose if the RTC clock failed the display may not refresh vs the millis that would till refresh, but just display no/incorrect time.

If you want a real acccurate RTC you have to use a hardware-RTC.

The frequency of a microcontroller is a little dependant on tolerances of the oscilator-components and temperature.

WHcih microcontroller do you use. Some of the chips have a built-in RTC (Like ESP32 or teensy 4.0)

best regards Stefan

Just curious if anyone can see anything wrong with my approach of just monitoring the seconds change to trigger a refresh/update?

One way or another that's exactly what I do. I like to use an ESP8266 to get NTP time, but the principal is the same.

Just curious if anyone can see anything wrong with my approach of just monitoring the seconds change to trigger a refresh/update?

I do not like calling rtc.now() and the I2C communication every pass through loop. My preference is to use the time library for the current time and monitoring if the second has changed, and have the time library synched periodically to the rtc with setSynchProvider().

cattledog: I do not like calling rtc.now() and the I2C communication every pass through loop. My preference is to use the time library for the current time and monitoring if the second has changed, and have the time library synched periodically to the rtc with setSynchProvider().

Interesting approach, what is the issue with the I2C communication every loop, does it make it more likely to cause a hangup, data corruption etc?, or just to avoid unnecessary processor time polling the RTC?

I presume one downside is if the internal clock is way off it would be constantly having to update, but suspect that would typically not be the norm.

what is the issue with the I2C communication every loop, does it make it more likely to cause a hangup, data corruption etc?, or just to avoid unnecessary processor time polling the RTC?

Yes.

But then again I may just be superstitious and the processor is happier than I am.

I presume one downside is if the internal clock is way off it would be constantly having to update, but suspect that would typically not be the norm.

Synchronization is on a periodic schedule. Default for the time library is synch every 5 minutes.

StefanL38: If you want a real acccurate RTC you have to use a hardware-RTC.

The frequency of a microcontroller is a little dependant on tolerances of the oscilator-components and temperature.

WHcih microcontroller do you use. Some of the chips have a built-in RTC (Like ESP32 or teensy 4.0)

best regards Stefan

Project is for a nano, but memory usage is becoming a problem, I do have a ESP32 and thought of porting the project over. Is the ESP32 internal RTC the same accuracy or close to the accuracy of a external chip/module.

If using the ESP32 one could just connect to the internet thing and update the time once a day. On the other hand my ESP32 controlling the plants environment gets the time from the inet once a boot. I've not rebooted it in several months; the ESP32 keeps spot on time.

I wanted to avoid the internet for the device, passwords change, connection issues etc, have seen examples where the time is set upon initial programming using NTP and the pc. If the internal RTC on the ESP32 is that good may be all that's needed once a year or so if at all.

StefanL38: WHcih microcontroller do you use. Some of the chips have a built-in RTC (Like ESP32 or teensy 4.0)

... or STM32

By the way, in my clock code, I poll the RTC every 100 ms, not constantly in loop().

aarg: ... or STM32

By the way, in my clock code, I poll the RTC every 100 ms, not constantly in loop().

How are you polling, by a interrupt or using millis() ?

Bryanpl: Project is for a nano, but memory usage is becoming a problem, I do have a ESP32 and thought of porting the project over. Is the ESP32 internal RTC the same accuracy or close to the accuracy of a external chip/module.

You can often save a considerable amount of dynamic memory (ram) by using the F() macro when printing text, as an example in the code you posted:

  if (! rtc.begin()) {
    Serial.println(F("Couldn't find RTC"));
    while (1);
 }

The F() macro stores the text in program memory instead of ram, and should work with any library that inherits from the print() class.

 if (currentTM.second()!= oldTM.second()) {
    oldTM = currentTM;
    //UPDATE OLED
 }

If you are really short on memory, there is no need to save the entire DateTime structure for oldTM, a byte will suffice to save currentTM.second(), and all you care about is if the second has changed.

Bryanpl: How are you polling, by a interrupt or using millis() ?

millis()

Idahowalker: If using the ESP32 one could just connect to the internet thing and update the time once a day. On the other hand my ESP32 controlling the plants environment gets the time from the inet once a boot. I've not rebooted it in several months; the ESP32 keeps spot on time.

I suppose one of the downsides to the ESP32 RTC is no built-in battery backup, so unless on boot updating the time from the net one would have to incorporate some battery back up or use a external RTC.

in my project I linked in first comment the time is kept with millis(). It is a Mini with crystal oscillator. the code contains millis correction. the I2C RTC used is fake and drifts badly so it is good only to backup time. but even with a good RTC I would not request time over I2C in every loop

I have been going over your code and it has given me some ideas, I like the alarm functionality. From other posters as well, polling the RTC in every loop certainly does not appear to be necessary. I suppose the only gotcha that could occur is if the RTC gets updated when the alarm timer just starts or finishes and throws it out if the original timing was way out, but really not that big of a deal I suppose.

Off topic, but this had me stumped

clockHour = (clockHour < 23) ? (clockHour + 1) : 0;

. Looked up the “?” and learned something new. Ternary conditional operator.

Bryanpl:
Off topic, but this had me stumped

clockHour = (clockHour < 23) ? (clockHour + 1) : 0;

. Looked up the “?” and learned something new. Ternary conditional operator.

the ternary operator it is 50 years old

in a few days I will publish on GitHub an alarm clock project with Wemos D1 mini (esp8266) connecting to WiFi only for a moment to get NTP time and using SoftAP for configuration (with WiFiManager).