There is no ANSI C function that provides better than 1 second time resolution but the POSIX function gettimeofday provides microsecond resolution. The clock function only measures the amount of time that a process has spent executing and is not accurate on many systems.
I always use the clock_gettime() function, returning time from the CLOCK_MONOTONIC clock. The time returned is the amount of time, in seconds and nanoseconds, since some unspecified point in the past, such as system startup of the epoch.
As it was already mentioned here that there is no proper ANSI solution with sufficient precision for the time measurement problem, I want to write about the ways how to get a portable and, if possible, a high-resolution time measurement solution.
The first one uses a monotonic clock counter (sometimes it is called a tick counter) which counts ticks with a predefined frequency, so if you have a ticks value and the frequency is known, you can easily convert ticks to elapsed time. It is actually not guaranteed that a monotonic clock reflects the current system time in any way, it may also count ticks since a system startup. But it guarantees that a clock is always run up in an increasing fashion regardless of the system state. Usually the frequency is bound to a hardware high-resolution source, that's why it provides a high accuracy (depends on hardware, but most of the modern hardware has no problems with high-resolution clock sources).
The second way provides a (date)time value based on the current system clock value. It may also have a high resolution, but it has one major drawback: this kind of time value can be affected by different system time adjustments, i.e. time zone change, daylight saving time (DST) change, NTP server update, system hibernation and so on. In some circumstances you can get a negative elapsed time value which can lead to an undefined behavior. Actually this kind of time source is less reliable than the first one.
When implementing a portable solution it is worth to consider a fallback strategy: use a monotonic clock if available and fallback to time stamps approach if there is no monotonic clock in the system.
There is a great article called Acquiring high-resolution time stamps on MSDN about time measurement on Windows which describes all the details you may need to know about software and hardware support. To acquire a high precision time stamp on Windows you should:
OS X (macOS) has its own Mach absolute time units which represent a monotonic clock. The best way to start is the Apple's article Technical Q&A QA1398: Mach Absolute Time Units which describes (with the code examples) how to use Mach-specific API to get monotonic ticks. There is also a local question about it called clock_gettime alternative in Mac OS X which at the end may leave you a bit confused what to do with the possible value overflow because the counter frequency is used in the form of numerator and denominator. So, a short example how to get elapsed time:
The main idea to prevent an overflow is to scale down the ticks to desired accuracy before using the numerator and denominator. As the initial timer resolution is in nanoseconds, we divide it by 1000 to get microseconds. You can find the same approach used in Chromium's time_mac.c. If you really need a nanosecond accuracy consider reading the How can I use mach_absolute_time without overflowing?.
The clock_gettime call is your best way on any POSIX-friendly system. It can query time from different clock sources, and the one we need is CLOCK_MONOTONIC. Not all systems which have clock_gettime support CLOCK_MONOTONIC, so the first thing you need to do is to check its availability:
The best fallback strategy is to use the gettimeofday call: it is not a monotonic, but it provides quite a good resolution. The idea is the same as with clock_gettime, but to get a time value you should:
IRIX has the clock_gettime call, but it lacks CLOCK_MONOTONIC. Instead it has its own monotonic clock source defined as CLOCK_SGI_CYCLE which you should use instead of CLOCK_MONOTONIC with clock_gettime.
Solaris has its own high-resolution timer interface gethrtime which returns the current timer value in nanoseconds. Though the newer versions of Solaris may have clock_gettime, you can stick to gethrtime if you need to support old Solaris versions.
If base is TIME_UTC, the tv_sec member is set to the number of seconds since an implementation defined epoch, truncated to a whole value and the tv_nsec member is set to the integral number of nanoseconds, rounded to the resolution of the system clock. (321)
man clock_gettime says that this measure may have discontinuities if you change some system time setting while your program runs. This should be a rare event of course, and you might be able to ignore it.
The best precision you can possibly get is through the use of the x86-only "rdtsc" instruction, which can provide clock-level resolution (ne must of course take into account the cost of the rdtsc call itself, which can be measured easily on application startup).
Well if you can state your requirements for the max +/- error in milliseconds over a one hour period perhaps it would shed light on the possibilities or difficulties involved. Note that the source of any basic timing error is mostly due to unit to unit variation of the 16Mhz crystal or ceramic resonator used in most arduino boards which drive the basic clocking speed of the controller. Adding to this variation is crystal padding capacitor value variation tolerance and of course error due to ambient temperature variation for all those mentioned parts. Suffice it say that there will be some basic timing error for any crystal controlled device, but if that error is significant or not can only be answered by the designer of a given application or project.
So while there will always be some basic timing error for any arduino board in general, there is nothing to prevent one from measuring the specific error for one's specific board and using some compensating 'correcting factor' in software to improve the situation for that specific piece of software, e.i. a unit to unit calibration function. This of course is limited by the accuracy and resolution capabilities of the test equipment used by the user to measure the error. Typically one needs to have test equipment measurement accuracy of ten times the accuracy of specification to be meet.
Also keep in mind that there is the arduino defined micros() function that can measure up to a 70 min period, with a 4 microsecond 'step' count resolution. It too is no more accurate then the crystal time base, but in your case might be accurate enough and an improvement over using the millis() function for the same period in question.
Edit: forgot to mention that the Arduinos with crystals will usually be +/- 20ppm and the Arduino Uno with resonator will be +/- 100ppm. So, almost a thousand times more inaccurate than you need (based on my assumption of how accurate you need the measurements).
It's an oven-controlled oscillator. Temperature drift is managed by heating the crystal up to a regulated temperature. It will take about one minute to warm up before the readings will be accurate. Also, the accuracy will degrade up to 10ppb per day and 300ppb per year, so be prepared to test and replace these as needed. This is also an OCVXO, which would let you use an external voltage to adjust the frequency a tiny amount to compensate for aging. You'll need to calibrate these every few days of operation for best results.
The racing takes place on 2 and 3 March, but if the contest is popular, it could become an event every quarter. In that case, I'd want something all would agree is accurate enough so the fastest robot wins.
I'd probably go with a clone or purpose-built board with a decent crystal, 20 or 30 ppm. It's important to be fairly accurate, but it's more important that it be consistent from one run to the next, as opposed to being atomic-clock accurate. With such a crystal, it might be a couple tenths of a second off after an hour if I did the maths right. We mostly just need to know who is fastest. I assume this is not a competition that takes place at several locations but then the actual times (as opposed to rankings) are compared between locations. That would require identical and probably traceable timing equipment.
You said the timer would have to go up to 59 minutes, 59 seconds. That a huge difference from 3 minutes. If you go back and use my calculations, you can easily see what PPM is acceptable for your requirements. For 5 minutes I'm getting 1.67ppm, which is a lot easier to set up! Correctly communicating your requirements is key.
If you can make sure your eventual solution really doesn't change temperature between races, you may do a lot better than the raw specs would indicate. The quoted PPM variation is usually over the operating temperature range. Put it all in a box with no ventilation, maybe a nice thermal mass in there too. Let it sit at the race location for a few hours.
I would have thought that if you're timing robots scurrying about, aiming for millisecond resolution is overkill. If you limit yourself to hundredths of a second, you will probably still find that accuracy is more than you need. Do you have an existing timing mechanism? How often do you get results that tie within a hundredth of a second?
I have noticed that the MacOS' version of the date command is not interpreting the %N format sequence as nanoseconds but simply prints N to the output when I started using my .bashrc script from Linux, that's using it to measure how long executed commands run, on a MacOS machine.
To obtain milliseconds since the Epoch, you can truncate the last three digits of microseconds to get milliseconds with $EPOCHREALTIME::-3 and avoid the (expensive) call to date or other external programs.
Update: Another alternative in pure Bash that works only with Bash 4.2+ is the same as above, but use printf to get the date. It will definitely be faster, because no processes are forked off the main one.
c80f0f1006