Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting Millisecond Extension #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

LabbiqX
Copy link

@LabbiqX LabbiqX commented Feb 24, 2015

I need it in some of my projects.

I need it in some of my projects.
@PaulStoffregen
Copy link
Owner

I do not believe this is a good implementation. At the very least, some sort of integration with the now() function is needed, so the pair together returns numbers representing the same time. I'm not exactly sure how that should be done, but at least something is needed.

Even if this were implemented well, whether or not to include it would also depend on opinion from @michaelmargolis

Later this year, I do plan to very seriously look at improving this Time library. Discussion is here: #3 (comment) Perhaps this millisecond function should be considered? Michael, any thoughts?

At the moment, I'm working on Teensy-LC, so I can't do much with libraries like Time, other than bug fixes, until Teensy-LC is released.

@andrewjaykeller
Copy link

+1 - I need Time with a project of mine.... openbci.com time synchronization between an SDK like processing/node.js and an arduino

@PaulStoffregen
Copy link
Owner

@michaelmargolis - Looks ok to me. Any objections?

@blackketter
Copy link

I've built a little C++ library for my own use that, among other things, provides time in milliseconds as a 64-bit signed integer, for both wall-clock now() time and millis() uptime. The larger range prevents the problems with rollover and absolute and relative times can be handled as a single scalar value with simple arithmetic. I suppose it's marginally slower in some cases but I haven't had a case where that was an issue, at least on Teensy. I'd be happy to contribute any of this if there's any interest.

@michaelmargolis
Copy link
Collaborator

I avoided millisecond support in the library because the values would not be monotonic when the time was periodically synchronized to an external time provider. I felt that this could cause problems for less experienced users that tried to do ‘more accurate’ time arithmetic using millisecond values.

I am open to hearing how we could address this issue.

@PaulStoffregen
Copy link
Owner

The same can easily happen for seconds, if the Arduino clock and sync provider disagree too much.

@PaulStoffregen
Copy link
Owner

@blackketter Can 64 bit integers work on AVR? I suppose I could do some tests to find out.... Even though my own work is now mostly focused on 32 bit ARM, for widely used libraries like Time we really do need to restrict ourselves to stuff that works on 8 bit AVR.

@michaelmargolis
Copy link
Collaborator

The same can easily happen for seconds, if the Arduino clock and sync provider disagree too much.
The default sync interval was chosen so resync occurs well before the clock drifts more than a second. Assuming that the sync provider remains accessible, the seconds value will remain monotonic (even if using a ceramic resonator).

@blackketter
Copy link

int64_t is supported and works fine on my Arduino Uno here with this simple loop incrementing a 32 and 64 bit integer for a millisecond:

 int32_t x32 = 0;
  unsigned long n = millis();
  while (n == millis()){};
  n = millis();
  while (n == millis()) {
    x32++;
  }
  Serial.print("int32_t: ");
  Serial.println(x32);

  int64_t x64 = 0;
  n = millis();
  while (n == millis()){};
  n = millis();
  while (n == millis()) {
    x64++;
  }
  x32 = (int32_t)x64;
  Serial.print("int64_t: ");
  Serial.println(x32);

On the Uno, I get results like:

int32_t: 524
int64_t: 288

And on Teensy3 (96MHz):

int32_t: 15965
int64_t: 13682

I suspect that concerns about performance, even on 8-bit AVR, are premature optimization.

Re: monotonicity shouldn't be a requirement for a wall-clock time function (daylight savings time, which is a worthy goal, breaks that pretty hard).

@michaelmargolis
Copy link
Collaborator

monotonicity shouldn't be a requirement for a wall-clock time function
Indeed, but what about applications involving measurement of intervals of time?

@blackketter
Copy link

Indeed, but what about applications involving measurement of intervals of time?

Not sure what you mean by intervals in this case:

  • For wall-clock time, subtracting two time scalars will give you an interval in milliseconds (or seconds). In this case the values have specific time and date meanings you'll get the calculated difference between those two time values, independent of the clock changing in the middle.
  • If you want to measure time intervals of the running system (i.e. how long did some operation take) you should use millis() or its 64-bit equivalent. This is independent of the wall-clock time and will be as accurate as the millis() clock.

If 64-bit millisecond units are used for both wall-clock and uptime (i.e. now64() and millis64()), relative calculations are trivial.

This presents the problem of the RTC and the millis() clock not being in sync and for some systems (without crystals) may drift considerably. I'm not sure how big a problem that may be, but I suspect that applications that are running on systems that need very accurate millis() should probably get crystals or be calibrated appropriately.

@blackketter
Copy link

FWIW, I posted that Clock library I've been using that provides a C++ interface to Time and provides a 64-bit millisecond interface. Seems to work for both Teensy3 and Uno.

https://github.com/blackketter/Clock

@michaelmargolis
Copy link
Collaborator

If you want to measure time intervals … you should use millis() or its 64-bit equivalent
I disagree with the above for the following reason.

Many people use this library to measure intervals of time, the TimeRTCLog example sketch provided with the library illustrates how the time of day functions can be used with the display of event intervals. I would not want to lose the consistency between time of day functions and time duration functions.

For logging applications that require consistency with a wall clock, a common technique is to add functionality to convert the internal system time (typically synched to UTC) to local time zone and DST for wall clock display.

I would agree that adding this capability to the library would be beneficial and don’t see a problem adding a cosmetic milliseconds value to some new function that renders system time as local time. Would that addresses the requirement for millisecond extension?

However, I don't feel comfortable providing millisecond precision to the internal system time if it cannot be made monotonic. Correct me if I misunderstand, but I think you are saying that because the Arduino crystal can drift, the system time can’t guaranteed to be monotonic, so having the extra precision does not create a new problem.

However the drift in a typical Arduino board with crystal is in the order of a couple of seconds per day, syncing every 5 minutes (the default) ensures that time will be set to the current second well before it could drift non-monotonically. But I don’t see how that would be practical with millisecond precision system time. This may not be an issue in a clock display but could look like a bug in an application that dealing with event intervals that could be within a second or a month.

@blackketter
Copy link

All good.

millis() (and micros()) uptime sources are monotonic (i.e. they go up and never go down), but may not be linear or accurate to real-world time (depending on the hardware and environment.) They also likely have higher resolution.

An RTC may be more accurate, but may not be monotonic (i.e. may go down due to changes to DST, user resetting or drift compensation). Current RTCs have second resolution, but an RTC based on NTP would certainly have sub-second resolution.

I think any new API should provide identical units for time (i.e. milliseconds or microseconds) and allow the user to use the timebase appropriate for their application, depending on the need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants