Time, Sync etc

Please can you give me a link to an article giving simple and complete information on setting time in Arduinos. I don't understand Unix commands. RTC commands don't seem to be self explanatory. I understand that there are 3 sorts of time, computer time, RTC time and Arduino time. Despite running an RTC, my sketches often get stuck on Compile time on reset. I would like to understand, in plain English what each command does! I have spent hours surfing and found many other cases of confusion, but no "Plain Words". For example, what do these lines do?

time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{
  return RTC.now().unixtime();
}

void setup () {
 //setTime(17,26,0,7,4,2013);
 RTC.begin();
 setSyncProvider(syncProvider);
//  RTC.now;  // Test to force initial sync, no.

Which RTC and Arduino are you using?

Pete

I have been using a Uno R3 and recently a Mega R3. The RTC is a DS1307 on Adafruits logger shield. Adafruit provides code, of course, but the various time instructions are used rather than explained. (No criticism intended!)

Adafruit provides code, of course, but the various time instructions are used rather than explained.

If you make a list of them (as used in your sketch), and describe which one(s) you don't understand, we can help you understand them.

I did not really want to bother someone to answer detailed questions; I had hoped someone had already written an idiots guide. I don’t know why I have the temerity to think I can use microprocessors!
I tried to include the whole sketch, which runs well enough, except that it reverts to compile time if the power fails. (PC is disconnected.) But that exceeded the allowed size.

Here are all the time lines which I want to understand and my comments in blue.

#include <RTClib.h> OK, includes the RTC library.

RTC_DS1307 RTC; I see what it is about but what does it do?

time_t syncProvider() //this does the same thing as RTC_DS1307::get() !! What is the thing?
{
return RTC.now().unixtime();
}
Unix time is the number of seconds since 1st Jan 1970. So does this read from the RTC that number of seconds, at that moment, so that date and time can be calculated and printed?

uint32_t syncTime = 0; // time of last sync() Sets the time of the last sync to current (RTC) time? I believe something causes the Arduino time to be synced with the RTC time at 5 minute intervals – presumably from the RTC library?

RTC.begin(); Wakes up the RTC.
if (! RTC.isrunning()) {
RTC.adjust(DateTime(DATE, TIME));
} If the RTC has not got a running time, it is updated with computer time? If a computer is connected.

setSyncProvider(syncProvider); //reference our syncProvider function instead of RTC_DS1307::get() Eh? Where is “(syncProvider)”. What does this DO? So the two calls are similar but must be different or the change would not have been made.

RTC_DS1307 RTC;  I see what it is about but what does it do?

It creates an instance of a class. Clocks are generic items. They all perform the same basic tasks, but the clock on the wall in your living room is a specific instance of the generic class clock. In the same way, RTC is an instance of the RTC_DS1307 class.

time_t syncProvider()     //this does the same thing as RTC_DS1307::get()  !! What is the thing?

It is a function. The name is not specifically meaningful. In this case, it is a function that is to be called when the RTC instance really needs to know what time it is. It performs a synchronization between the RTC instance's understanding of the time and the hardware's understanding of the time.

Unix time is the number of seconds since 1st Jan 1970.

Yes.

So does this read from the RTC that number of seconds, at that moment, so that date and time can be calculated and printed?

No. Your wall clock has no idea when January 1, 1970 was. The RTC class does, though. It can convert between the time it knows (like your wall clock) and the time of that Unix understands that time began, as a way of exchanging time information with other systems that have different understandings of time.

uint32_t syncTime = 0; // time of last sync()  Sets the time of the last sync to current (RTC) time?

This defines the last time that the RTC instance checked with the hardware to update the instance's concept of what time it is to match the hardware's understanding of what time it is.

I believe something causes the Arduino time to be synced with the RTC time at 5 minute intervals – presumably from the RTC library?

Yes. There are ways to define how often the syncing happens. If the Arduino is pretty accurate, and the cost of getting the correct time is high (as in getting time from an NTP time server), then the interval should be long. If the Arduino isn't very accurate, and the cost is small (as in accessing the DS1307 hardware) the interval should be small.

If the RTC has not got a running time, it is updated with computer time? If a computer is connected.

No. If the RTC is not running, start it running with the time and date that the sketch was compiled. This assumes that the clock is new (and, therefore, not yet running), so the clock is started running with the compile time (which might be a few seconds late).

Eh? Where is “(syncProvider)”.

syncProvider is the name of a function (the one you asked the first question about). That function will be called whenever a sync is to happen.

What does this DO?

It defines how the Arduino is to synchronize it's concept of time. The specified function will be called.

So the two calls are similar but must be different or the change would not have been made.

I don't understand the question. The setSyncProvider() function registers a callback. The syncProvider() function is called at specified intervals.

If you still have questions, feel free to keep asking.

Thank you for your reply. Being geriatric, I still don’t understand the code. Here are the first lines of my program.

#include <avr/wdt.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_BMP085.h>
#include <RTClib.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <Adafruit_RGBLCDShield.h>
#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>
#define PIN 3  // the pin for button/ rain gauge
#define STOP_SWITCH 2
 bool stopped = false;
RTC_DS1307 RTC;
time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{
  return RTC.now().unixtime();
}
uint32_t syncTime = 0; // time of last sync()

Why do I need to write “RTC_DS1307 RTC;”? Does it tell Arduino that an RTC exists?
Then the next line runs syncProvider() [from the Time library?] and this collects the Unix time saved at compile/load and passes it with " return RTC.now().unixtime();" to the RTC? If that were the case it seems that there would be no need for the later code

 RTC.begin();
  if (! RTC.isrunning()) {
  RTC.adjust(DateTime(__DATE__, __TIME__));
  }

in setup.

I was confused with your explanation of “time_t syncProvider()”. Once the Arduino is disconnected from the PC, surely the only useful synchronisation is FROM the RTC TO the Arduino?

Why do I need to write “RTC_DS1307 RTC;”? Does it tell Arduino that an RTC exists?

That line is equivalent to

ArduinoForumUser spiney;

It says that there is an instance of the ArduinoForumUser class, and that that instance name is spiney.

The line you asked about does not say that there is any hardware. It only says that if there is any hardware, the instance named RTC know how to interact with the hardware. The instance name could be myExternalHardwareInterface. Perhaps if it were, its use would be clearer.

Then the next line runs syncProvider() [from the Time library?

No. The next line is simply the definition of a function that may, or may not, actually ever be called.

and this collects the Unix time saved at compile/load and passes it with " return RTC.now().unixtime();" to the RTC?

No, it doesn’t. It asks the RTC instance to get the current time from the external hardware, and to convert that to the Unix time format (number of seconds elapsed since 00:00:00 on 1/1/1970).

If that were the case it seems that there would be no need for the later code

That not being the case, though, the following code is necessary. What it does is ask the RTC instance to wake up the external hardware, and to determine if the external hardware is currently keeping track of the time. If the external hardware is not, then the external hardware is told to start keeping track of time, and that now is whenever the sketch was compiled and linked.

Since there is only a second or two between compiling, linking, and uploading, and the sketch starting to run the first time, a brand new external clock (or one where the battery died and was replaced) should get a reasonably accurate initial time.

I was confused with your explanation of “time_t syncProvider()”. Once the Arduino is disconnected from the PC, surely the only useful synchronisation is FROM the RTC TO the Arduino?

The syncProvider() function is needed to keep the Time class apprised of the actual time. There are several ways that that can happen. One would be to ask the PC what time it is, and have an application running on the PC that understood the question and provided the correct answer. The drawback to this approach is that the Arduino must stay tethered to the PC at all times.

Another is to use an NTP provider. The drawback to this approach is that the Arduino must be wearing an ethernet shield and be connected to the internal at all times.

A third option is to attach an external RTC to the Arduino, and get the time from there.

In each case, the syncProvider() function is expected to contain the correct code to get the current time from some source, in the correct format. This function is the only place where the external time provider and the Time class meet. Nowhere else in your code should you actually talk to the external hardware to get the time.

Thank you.
Does “external hardware” always apply, in my system, to the PC?

Does “external hardware” always apply, in my system, to the PC?

No. External hardware refers the RTC.

Thank you. Having previously misunderstood RTC.adjust(DateTime(__DATE__, __TIME__)); and included it in another part of the code, I now see that it probably was the reason the Arduino returned to compile time each time there was a power outage. I have noticed a delay of over a minute between PC time and Arduino time printed on the monitor and I have suspected that the PC time might be saved during the verify operation. Evidently RTC Instance and RTC hardware should not be considered interchangeable.

and I have suspected that the PC time might be saved during the verify operation.

It is recorded when the compiler is invoked. After that, the compiler compiles the object module. The compiler may have other object modules to create, from other source files. When the compiler is done, the linker gets to run, combining bits and pieces of the object modules, to produce a hex file. Then, avrdude uploads the hex file to the Arduino, after the bootloader agrees to accept the upload. Once the upload is complete, the Arduino is reset, and, after determining that the reset was not in preparation for accepting a new sketch, it begins running the one stored in memory.

Depending on the PC, and the number of libraries involved, a delay of a minute or more is not unreasonable.

Evidently RTC Instance and RTC hardware should not be considered interchangeable.

No. The RTC instance needs to know about the hardware. The sketch does not.

I am still trying to understand Arduino Time. I would like an explanation of what this line is doing.

return RTC.now().unixtime();

It is in this snippet:-

RTC_DS1307 RTC;
time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{
  return RTC.now().unixtime();
}

uint32_t syncTime = 0; // time of last sync()

I have deliberately run this line:-

 Serial.println(RTC.now().unixtime());

and I see that I get the number of seconds from 1970 up to now, but where did that figure come from, and where is it being put, and for what reason? Sorry to ask for such basic info!

but where did that figure come from

It came from unixtime().

and where is it being put

It is being returned to the function that called syncProvider(). What that function does with it isn't clear from your snippets.

and for what reason?

Are you asking why syncProvider() is being called? Or, are you asking why syncProvider() returns the time relative to some seeming arbitrary date? If it's the latter, ask yourself how many PCs there were in the world on January 1st, 1970. How many of them had clocks? The answers, as I recall, are damned few and none.

Having every time-concerned application reference the same point in time as 0 provides an easy way to determine the order of dates. Simply determine when a date falls relative to that point in time, and one will be larger than the other, unless both are the same.

If Windows, Mac, and Unix/linux used different start dates, no one would be able to agree on anything. Microsoft would probably use a different start date for every version of Windows, and the start date would be proprietary.

Thank you for your reply. I understand the advantage of having unixtime. What I don't understand is where the various times are being held and in which direction the changes are being made. I understand that with the PC connected a compiler time is loaded into the Arduino and arduino time increments from then. I also understand that if RTC.adjust(DateTime(__DATE__, __TIME__)); is used an RTC will be corrected to the compiler time at that instant, but if that line was called again later, then the RTC time would again be set back to compiler time. So when I asked where the figure came from, I was wanting to know if it came from the RTC or whether it was going to the RTC. Next problem will be understanding the meaning of the various SyncProvider lines. It has to be that the SyncProdider function keeps the Arduino time updated from the RTC because that is the RTC purpose. My problem is understanding C++ code and the working of the various time libraries.