RTC D3231 setSyncProvider Timealarms Headache

Hi everyone,

i tried a lot now, but still can't find the error in this code. The Problem is the setSyncProvide.
Maybe also a overload on Library's. I checked the sodaq Library and Timelib.h, but i couldn't find a solution.
I want to sync the rtc time with the internal time to use it with the timealarms.

The timealarm tiggers a relay.

Without the rtc modul it works very well. (Just using the settime in setup)

I am still a beginner, so i hope you guys can help me out here.

Thanks in advance!

Tobi

// Library for RTC-Modul
#include <Wire.h>
#include "Sodaq_DS3231.h"
// Library for the Time Alarm functions
#include <TimeLib.h>
#include <TimeAlarms.h>

const int signal = 11;

char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

void setup()
{

Serial.begin(9600); // set up Serial library at 9600 bps
Wire.begin();
rtc.begin();
setSyncProvider(rtc.now);
rtc.now();

Alarm.alarmRepeat(07, 30, 0, MorningAlarm);

pinMode(signal_coffee, OUTPUT);
digitalWrite(signal_coffee, HIGH);
}

uint32_t old_ts;

void loop() {
digitalClockDisplay();
Alarm.delay(1000); // wait one second between clock display

DateTime now = rtc.now(); //get the current date-time
uint32_t ts = now.getEpoch();

if (old_ts == 0 || old_ts != ts) {
old_ts = ts;
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.date(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.print(' ');
//Serial.print(weekDay[now.dayOfWeek()]); Does not work with this line.
// It'S sample code and works in the original
Serial.println();
Serial.print("Seconds since Unix Epoch: ");
Serial.print(ts, DEC);
Serial.println();
}
}

// functions to be called when an alarm triggers:
void MorningAlarm(){
Serial.println("Coffee Machine is on");
digitalWrite(signal, HIGH);
delay(1000);
digitalWrite(signal, LOW);
delay(1000);
digitalWrite(signal, HIGH);
}

void digitalClockDisplay()
{
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println();
}

void printDigits(int digits)
{
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

You didn't really explain what the actual problem is. What part isn't working?

 setSyncProvider(rtc.now);

I am not familiar with the Sodaq rtc library, but that code looks wrong give the other time commands shown in the code you posted.

Here is the syntax I have used with other RTC libraries, and I would try as follows

setSynchProvider(synchProvider);

Then define a function

uint32_t syncProvider()
{
 
 ts = now.getEpoch();
 return ts

}

if now.get Epoch() is not returning Unix time, use the syntax which returns it.

I don't know what rtc.now does, but here is the thing, the setsyncprovider needs to have access to a callback function that directly reads the chip time and send back the time_t and it is simply defined as time_t Function() (see time_t(*getExternalTime)(); in timelib.h)

Also if it is in a class the function must be static, this may be your issue however you didn't explain your problem, is it compiling issue or just shows wrong time?
There could be other function in your rtc library that is specifically for this purpose and it would be then marked as static - look for get() etc,, also look inside, it has to read from the chip, not just return some variable read elsewhere.
The reason is that the time.h will periodically poll that callback to get and sync the time (every 5 min or so I think)

Now the last maybe obvious thing, does your RTC actually shows correct time? Did you set the time?, Does it even runs? Did you make sure it is not halted? (If it has battery then straight from manuf, it would be in halt mode and the time will be frozen). Normally a new chip needs to be initialized and set correct time. Look for an example in your rtc library and simply set the time (make new sketch to start the clock and set correct time, that's all).
Also your program will need to have itself ability to set the time by user, because the RTC time will drift up to few minutes per month.

I see the code was mostly some copy paste, because the rtc.now can't be both returning time_t and DateTime structure as you imply in various parts of your code so you really need to look into this.
Also don't call variables the same name like a function name (now = rtc.now()) because as your code grows you will be not able to recognize tail from its head.

cattledog was on right track, but no cigar, ts = now.getEpoch(); will not read time from RTC so your static function if none is suitable is in the RTC lib that returns time_t (I would be surprised if not) would be

time_t syncProvider()
{

return rtc.now().getEpoch();
}

that is all based on the deduction from your code snip.

I actually just finished project based on time.h and timealarms and RTC and I can tell you those time libraries are very cleverly designed (although I couldn't help but "improve" them a bit)
See my clock:
https://forum.arduino.cc/index.php?topic=402345.0
It is very rewarding project, I have literally 200 bytes free in program memory as I put every function I wanted on that clock. Now if I want to add something I have to shuffle code around so it shrinks few bytes...

Oscarko:
Also your program will need to have itself ability to set the time by user, because the RTC time will drift up to few minutes per month.

Not if it's a DS3231. More like a few seconds a month.

Thanks guys.

The Code from Oscarko works. And i figured out what my problem was. Thanks for the detail explanation.