I have written a data logging program for an Arduino Uno and Adafruit datalogger shield. I monitor the on/off state of a piece of equipment and record the elapsed times in a state as hh:mm:ss to the SD card. I use the RTC for a date/time stamp of the state changes. On or off times are on the order of minutes or hours, and possibly days.
I have written two versions of my code, both of which work fine.
One version records the elapsed time using millis() - saved_millis() and handles millis() rollover through the behavior of of unsigned longs. As long as there is some state change activity within the 49 day period all is well. I understand that I could write code to detect a 49 day rollover without activity but its not a likely situation. I have tested this version substituting micros() for millis().
A second version calculates elapsed time from the state change time stamp data from the RTC. I chose to detect and count midnight rollovers of the 24 hour clock in the calculation of elapsed times. The code for this version is a little more complex than the millis() based version, but appears to be robust over elapsed times of several days.
Is there any reason to use one version or the other?
If you are monitoring for a long period of time, the RTC is the way to go. Millis() is good for short-term accuracy, but as a clock, it will tend to drift over longer periods of time.
You needn't get too complex when using the RTC. If you are only interested in elapsed time (from what you say, it sounds like that is the case), then just set the clock to 00:00:00 every time you get an event, and when the next one happens, report the time and reset to 00:00:00.
If you're interested in when it went on or off as well as elapsed times, there is a small overheaed in calculating elapsed times across days, months, or years, but it's not overly difficult.
The RTC will know when its midnight after a power failure.
The Time library makes dealing with time values easy. Elapsed time can be calculated simply by subtracting two values. It works well with RTCs too.
The Time library defines the time_t data type. Under the covers, this is just a four-byte integer (i.e. unsigned long) that represents the number of seconds since 01Jan1970. In other words, same as is widely used in C programming, a.k.a. Unix epoch time.
The Time library uses the Arduino's system clock (which may not be terribly accurate) but then can sync it every five minutes (by default) with an RTC. This works well, with one small side effect. When the synchronization happens, depending on the relative speeds of the clocks, time may move ahead by two seconds, or backwards by a second, or not change for two seconds, etc.
[quote author=Jack Christensen link=topic=237297.msg1705142#msg1705142 date=1398987195]
Under the covers, this is just a four-byte integer (i.e. unsigned long) [/quote]
sp. "signed long" - it rolls-over in about 2038.
AWOL:
[quote author=Jack Christensen link=topic=237297.msg1705142#msg1705142 date=1398987195]
Under the covers, this is just a four-byte integer (i.e. unsigned long)
sp. "signed long" - it rolls-over in about 2038.
[/quote]
Usually, but the Arduino Time library differs in this regard.
Thanks for all the replys.
I will proceed with the RTC based approach.
I am using RTClib.h in my project, and the call DateTime now = RTC.now() contains now.unixtime() which I understand to be a "kind of" unix time. From review of the library, I think it is an unsigned 32 bit number, and I have cast the variables which are assigned this value as unsigned longs. What is coming back is a 10 digit number 1399XXXXXX (1.399 E9). I don't know if it will get to 4,294,967,295 or 2,147,483,647 and if it rolls over in 2038 or somewhere in a farther world is of no real concern to me.
Using now.unixtime() has certainly simplified the program from when I tracked and calculated daily rollover using the native hh:mm:ss data format of the DS1307.
I'm a newbie, and the experience of writing and testing the code version using millis() and coming to an understanding of unsigned longs, register rollover, and two's complement math was a great learning opportunity.
cattledog:
Using now.unixtime() has certainly simplified the program from when I tracked and calculated daily rollover using the native hh:mm:ss data format of the DS1307.
That's interesting. I just ask the DS1307 if it's midnight or one second past. Maybe you need to get smarter because you are checking elapsed times through midnight while all I want is to change the filename.