Combining RTClib.h and TimeLib.h

Hello everyone

I wanted to combine the RTClib.h for it's ability to set time through the compiler and the TimeLib.h for its time_t variable and the ease of handling time and time calculations.

Here is my code relevant for the combination:

#include <Wire.h>
#include <RTClib.h>
#include <TimeLib.h>

RTC_DS3231 rtc; //Initialize RTC object
DateTime nowRTC = 0;
time_t nowTime = 0;

void setup()
{
Serial.begin(9600); // for debugging

#ifdef AVR
Wire.begin();
#endif
rtc.begin();
/*Sanity check*/
if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
}
if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time! ...");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // set the time after power has been lost
    Serial.println("Time set!");
}
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // comment out after use and reupload
 
nowRTC = rtc.now();
nowTime = nowRTC.unixtime();
setSyncProvider(nowTime);
/*Sanity Check Time.h*/
if (timeStatus() != timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");
}

void loop()
{
nowRTC = rtc.now();
nowTime = nowRTC.unixtime();
setTime(nowTime);

/*For Debugging*/
Serial.print("The Time is: ");
Serial.print(hour());
Serial.print(" : ");
Serial.print(minute());
Serial.print(" : ");
Serial.println(second());
Serial.print("The Date is: ");
Serial.print(day());
Serial.print(".");
Serial.print(month());
Serial.print(".");
Serial.println(year());
}

Now what happens is that the Arduino gives me the message: "Unable to sync with the RTC". The time seems to work ok. But the date is completly off. Instead of 28.07.2019 it gave me 65.03.2019.

What might be wrong in my code?

Could anyone tell me at the same time how to use the macros of TimeLib.h? For instance:
#define elapsedSecsToday(time) ((time) % SECS_PER_DAY)

Thank you all!

moses

I have seen sketches that combine those two libraries, but it is asking for trouble.
Can you use the TimeLib library and write the conversion from DATE en TIME yourself ?
You can use this DateTime function and the conv2d() function.

Hello Koepel

Thank you for the answer and the link.

I will gladly look at the suggested conversion. How ever I am quite new to coding therefore I am not yet convinced that I will be able to do so. This is also why I cannot yet see and understand what kind of trouble something like combining two libraries that are based on different concepts might have.

I was wondering what if I used the unixtime of the RTClib? Would I be able to do similar things as with the Time library or are there a lot of possibilities missing? Thank you.

Cheers,

moses

The base of most clocks is the number of seconds since 1970, that is the unixtime, also called "epoch". The TimeLib can easier deal with that than the Adafruit library.

I have seen others combining those libraries, but I think that in the end it is easier to convert the DATE and TIME to a format that the TimeLib understands.

Instead of the DateTime() function with conv2d() from the Adafruit library, I like this more: Can you format __DATE__ ? - #10 by RichardBronosky - Programming Questions - Arduino Forum.

I did not carefully check how to combine this with the TimeLib, but it is possible to set the TimeLib with the compiler date and time with this sketch:

#include <Wire.h>
#include <TimeLib.h>               // Paul Stoffregen TimeLib pjrc.com

char buffer[80];                   // only used to show the date and time in the loop()

void setup() 
{
  Serial.begin( 9600);

  // Test if the RTC is available and running.
  // See also the examples of the TimeLib how to use the SyncProvider and
  // how to test with timeStatus() if the time was set.
  // When that fails, this is how to fallback to the compiler date and time.
  
  static const char compiler_time[] = __DATE__ " " __TIME__;
  static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  char monthbuf[16];
  int h, m, s, d, y;
  sscanf( compiler_time, "%s %d %d %d:%d:%d", monthbuf, &d, &y, &h, &m, &s);
  int mnth = (strstr( month_names, monthbuf) - month_names)/3 + 1;
  setTime( h, m, s, d, mnth, y);        // set the time for the TimeLib

  // Don't forget to turn the RTC on and update the time to the RTC
} 

void loop() 
{
  sprintf( buffer, "%4d-%02d-%02d %02d:%02d:%02d", year(), month(), day(), hour(), minute(), second());
  Serial.println( buffer);
  delay( 1000);
}

Try using this to set the time:

Remember that, in order to get it to work, you will need to insert the correct time yourself. For how to do that, see the comments within the code there.

Your syntax for the setSyncProvider() is not correct. See this example code.

#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
#include "RTClib.h"
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
RTC_DS1307 RTC;
//RTC_DS3231 RTC;

uint32_t syncProvider()
{
  return RTC.now().unixtime();  //either format works
 // DateTime now = RTC.now();
 // uint32_t s = now.unixtime();
 // return s;
}

void setup(void)
{
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  setSyncProvider(syncProvider);   // the function to get the time from the RTC
  if(timeStatus() != timeSet) 
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");      
}

void loop(void)
{
  timeDateDisplay();  
  delay(1000);
}

void timeDateDisplay(void)
{
 
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year()); 
  Serial.println(); 
  Serial.print("Unix Time ");
  Serial.println(now());
  Serial.println();
}

void printDigits(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

cattledog:
Your syntax for the setSyncProvider() is not correct. See this example code.

Normally with the RTClib that would be rtc.now() wouldn't it? But I tried to work around that with my code because of the DateTime / time_t incompatibility.

odometer:
Try using this to set the time:
https://github.com/millerlp/RTClib/blob/master/examples/settime_exact/settime_exact.ino
Remember that, in order to get it to work, you will need to insert the correct time yourself. For how to do that, see the comments within the code there.

My goal was more to have the time set automatically especially if the RTC loses power or some other reasons. For now through the compiler. Later on maybe wifi.

moserroger:
My goal was more to have the time set automatically especially if the RTC loses power or some other reasons. For now through the compiler. Later on maybe wifi.

I hope that you are aware that a line like this

  static const char compiler_time[] = __DATE__ " " __TIME__;

requires you to re-compile (not just re-upload) your code every time you wish to reset the time.

What sort of RTC are you using? Is it a battery-backed RTC? (for example, a Chronodot)

If you have problems with the RTC losing the time on you, then it might be caused by a problem with whatever you have it hooked up to (wrong voltage, incorrect wiring, etc.) I know this because I have had such problems.

As for the problem of resetting the time, here is one solution I came up with:
https://forum.arduino.cc/index.php?topic=408565.0

odometer:
requires you to re-compile (not just re-upload) your code every time you wish to reset the time.

What sort of RTC are you using? Is it a battery-backed RTC? (for example, a Chronodot)

As for the problem of resetting the time, here is one solution I came up with:
Two-button clock - Exhibition / Gallery - Arduino Forum

  • Yes I am aware of the need to recompile.
  • it is a ds3231 battery-backed.
  • There is no problem of the rtc loosing time. I just thought it might be more convinient to have it set automatically. Don't quite know why I found this ideal.
  • Thank for the idea of the solution with the display. I could only have a short look and need therefore to look into it a bit deeper. But it looks very interesting.

moserroger:

  • There is no problem of the rtc loosing time. I just thought it might be more convinient to have it set automatically. Don't quite know why I found this ideal.

Why is having the RTC set to the compile Time / Date any better than whatever value it picks up on power-up? The key is not to lose power in the first place.

You mentioned WiFi. If you have that, you don't need the RTC at all. Just use the TimeLib.h library to keep time using internal millis() and true it up every 10 minutes or so using NTP.