Time library tmElements_t time_t tm

Hoping to get some advice from experts on C/C++ time functions
I want to set the time of my DS1307 Real Time Clock accurately (+/- 1 sec or better). Using the example TimeRTCset in the IDE I am able to do this, but it is limited to receiving the input time in time_t form (seconds since noon 1 Jan 1970). (e.g. 1326758400 which equals 00:00 17 Jan 2012). My goal is to set the time from GPS time which is provided in the form sec, min, hr, day, mon, yr.

So I dived into Time.cpp and DS1307RTC.cpp to figure out what’s possible. One big question I have, there are many mentions of “system time”as distinct from RTC time, but what IS this mythical “system time”??? for example the following code appears in timeRTCset, and both must be executed or it doesn’t work:
RTC.set(t); // set the RTC and the system time to the received value
setTime(t);

But here’s the rub. The following code will work:
RTC.set(1294911050);
setTime(1294911050);

and so will this:
(note this code alone only sets time temporarily, i.e. doesn't survive reset)
setTime(9,30,50,13,1,2012); // sec, min, hr, day, mon, yr

but this won’t because the “set” routine in DS1307RTC doesn’t support the time elements form (whereas Time.cpp does):
RTC.set(9,30,50,13,1,2012); // sec, min, hr, day, mon, yr
setTime(9,30,50,13,1,2012); // sec, min, hr, day, mon, yr

I found the “maketime” routine in Time.cpp which takes time elements as input and outputs time_t. If I could access this my problem would be resolved, but I haven’t figured this out (my limited C/C++ skills are being tested!). Here’s the beginning of maketime in Time.cpp:

time_t makeTime(tmElements_t &tm){

How can I use this routine from my sketch? Or perhaps better still – how would I add this to DS1307RTC.cpp?
TIA

but what IS this mythical “system time”???

The time that Arduino is aware of.

for example the following code appears in timeRTCset, and both must be executed or it doesn’t work:

It would if you are syncing with the RTC regularly.

I found the “maketime” routine in Time.cpp which takes time elements as input and outputs time_t. If I could access this my problem would be resolved, but I haven’t figured this out

The tmElements_t object is a structure. You can create an instance of the structure, populate the members of the structure, and then pass the structure to makeTime.

However, the easiest way to do it is to call setTime() with the values that you want, then call now() which also returns a time_t object that you call RTC.set() with.

setTime(9,30,50,13,1,2012);
time_t t = now();
RTC.set(t);

excellent thanks PaulS I'll give that a go.

but the concepts are still not quite clear to me when you say "system time" is Arduino time. As far as I know the Arduino has no clock? (that's why I've attach an RTC). But if now() is reading this system/Arduino time I guess it must have the ability to keep clock time once it's been initialised? Perhaps there is some relationship here between system/arduino time and millis()?

and what did you mean by "it would [work] if you are syncing with the RTC regularly".

As far as I know the Arduino has no clock? (that's why I've attach an RTC).

True. But it has a second hand, so if you tell it the second, minute, hour, day, month,and year, it can do a reasonable job of keeping time.

But if now() is reading this system/Arduino time I guess it must have the ability to keep clock time once it's been initialised?

Not terribly accurately, and not across resets, which are the real reasons for an RTC.

Perhaps there is some relationship here between system/arduino time and millis()?

There is.

and what did you mean by "it would [work] if you are syncing with the RTC regularly".

The Arduino doesn't keep real accurate time. Your RTC does. Periodically, the Arduino should ask the RTC what time it is. This is called syncing.

The setSyncProvider() function is used to define what function to call whenever a sync is required. Generally, you would specify some RTC function, like RTC.get().

Use setSyncInterval() to define how often to sync.

Look at the examples...

excellent info again, thanks.

so now() will drift unless synced occasionally - I'd best learn to use those sync functions!

I note TIME_DRIFT_INFO appears in Time.cpp also. Is there a separate drift compensation mechanism, or is this just part of the syncing you've described?

That is a symbol that you can define to enable populating a variable that records how far the clocks have drifted. I'm not sure what use you'd make of that data. Perhaps if the drift is consistently small, you might opt to increase the sync interval, especially if syncing from an NTP server.

OK I'm guessing since drift is typically linear I could populate the variable with a fixed correction and then compensate the drift regularly (reducing need to sync). But I wonder, is it for drift of the RTC or drift of the Arduino time?

pushing my luck PaulS (given you're so helpful) perhaps you could offer some suggestions for a (possibly) related problem I've been having using time library to read my GPS... as described here:

OK I'm guessing since drift is typically linear I could populate the variable with a fixed correction and then compensate the drift regularly (reducing need to sync). But I wonder, is it for drift of the RTC or drift of the Arduino time?

The variable is an output - it tells you how much drift there was. The RTC is more accurate than the Arduino, for keeping time. The RTC library simply reports how much drift occurred, without assigning blame.

I looked at your other thread, too.

PaulS:
... without assigning blame.

:slight_smile: well put. (of course Drift is a difference ... doh!)

many thanks again for your top quality guidance PaulS. Judging by your post count you don't eat, sleep or drink, just post, right ? 8)

PaulS your clarification on two aspects would be much appreciated:

  1. time.cpp has syncInterval = 300 seconds as the default value. I understand this means that once I've setSyncProvider to the RTC, the Arduino time is synced to the RTC every 5 minutes by default. Does this syncing will happen "automatically" in the background ? If so I can't see where in time.cpp this happens, it seems to me syncing occurs only when now() is called ??

  2. I added #define TIME_DRIFT_INFO to my sketch but could not figure out how to extract the drift information e.g. the compiler complains if I try to include sysUnsyncedTime ?

ninja2:
what IS this mythical “system time”???

The Time library is a software RTC. When it refers to "system time" it is referring to the current time according to the software RTC. In addition, the software RTC can optionally be synchronized with a hardware RTC by using the setSyncProvider() function, typically in setup():

    setSyncProvider(RTC.get);

Calling setSyncProvider() immediately sets the system time from the RTC, and it will then resync every five minutes. This default resync interval can be overridden by calling setSyncInterval().

ninja2:

  1. time.cpp has syncInterval = 300 seconds as the default value. I understand this means that once I've setSyncProvider to the RTC, the Arduino time is synced to the RTC every 5 minutes by default. Does this syncing will happen "automatically" in the background ? If so I can't see where in time.cpp this happens, it seems to me syncing occurs only when now() is called ??

It actually only happens when now() is called and the sync interval has been exceeded. No point in resyncing unless now() is called. How could you know? If a tree falls in the forest ... XD

Jack, thanks for input.

As I read them your two posts above seem to contradict:

  1. "Calling setSyncProvider() immediately sets the system time from the RTC, and it will then resync every five minutes."

  2. "It actually only happens when now() is called ..."

item 1) implies automatic syncing whereas 2) implies manual syncing. what am I missing here ?

item 1) implies automatic syncing whereas 2) implies manual syncing. what am I missing here ?

Every time now() is called, the Time library checks to see if enough time has passed to require re-syncing. If so, it syncs and then returns the time. If not, it returns the time immediately.

As Jack said, it you only require knowing the time every half hour, there is no reason to sync 6 times while you aren't looking.

If you care about the time every second, like for updating a clock display, then most of the time that you call now() it will return immediately with the time. Every 5 minutes, there will be a pause while syncing occurs.

ninja2:
Jack, thanks for input.

As I read them your two posts above seem to contradict:

  1. "Calling setSyncProvider() immediately sets the system time from the RTC, and it will then resync every five minutes."

  2. "It actually only happens when now() is called ..."

item 1) implies automatic syncing whereas 2) implies manual syncing. what am I missing here ?

Yeah thought about that afterwards, it does sound like a contradiction. Paul said it better. So the sync interval is the most frequently the software will resync itself from the hardware RTC, depending on how often now() is called.

OK think I've got it now. There is no automatic syncing, it has to be done manually (i.e. by calling now() )
And even then syncing will be ignored if it is called sooner than the syncInterval after last now().
sound right?

There is no automatic syncing

Wrong. The syncing IS automatic.

it has to be done manually (i.e. by calling now() )

It is triggered by a call to now(), if enough time has elapsed since the last sync.

And even then syncing will be ignored if it is called sooner than the syncInterval after last now().

Yes. Though "ignored" should be "deemed unncessary".

PaulS:
Wrong. The syncing IS automatic.

I think your meaning for automatic is different from mine. If it were automatic in my world it would sync every syncInterval without having to call now().

But I do understand that's not how it works, thanks for advice from you and Jack C.

Perhaps you mean it's automatic in sense a call to now() triggers a syncing automatically, without having to add any other code?

Perhaps you mean it's automatic in sense a call to now() triggers a syncing automatically, without having to add any other code?

I mean that it is automatic in the sense that you do not have to explicitly sync. It happens on an as-needed basis when you want to know the current time. That is my definition of automatic.

OK .... all sorted then. cheers