Skip to content

More accurate time reporting #519

Description

@dhalbert

Several users have asked for time reporting that's more precise than the millisecond ticks provided by time.monotonic(). Use cases and proposals welcome here.

Activity

  1. added this to the Long term milestone on Jan 10, 2018
  2. CameronDevine commented on Jan 10, 2018

    @CameronDevine

    I was attempting to work with a 433Mhz radio transmitter which required writing to a pin at 200 microsecond intervals. Even if a function similar to the Arduino micros() had less than 1 microsecond resolution this would allow time calculations that are not possible with the time.monotonic() function.

  3. tannewt commented on Jan 10, 2018

    @tannewt
    Member

    @CameronDevine Interesting! How much data do you know you need to write ahead of time? Something like PulseOut might be adequate. It looks like it requires a carrier PWM signal though it could just be constant.

  4. dhalbert commented on Jan 10, 2018

    @dhalbert
    CollaboratorAuthor

    came from here: asking there as well: https://forums.adafruit.com/viewtopic.php?f=60&t=129222

  5. l8gravely commented on Mar 1, 2018

    @l8gravely

    I too would like to see something better than monotonic, since it's not stable and loses precision as time goes on. Or maybe I just need to learn the CircuitPython way to do longer term ramping up/down of a NeoPixel, while not doing a busy wait, so I can handle other inputs that come in.

    Right now I just try to do:

    timetofire = timer.Monotonic() + delay
    while True:
    now= timer.Monotonic()
    if (now > timetofire):
    timetofire = now + delay
    # do NeoPixel incremental update here

    continue on looking for keyboard input, etc.

    Does this make sense? I also wish it was more clearly documented what resolution monotonic is counting in, since it's not quite seconds, but maybe milliseconds?

  6. tannewt commented on Mar 5, 2018

    @tannewt
    Member

    @l8gravely On the SAMD21 it is millisecond.

    I'm still unsure we want to provide precise timing because we pause the VM from time to time to do other things. I'm worried about making timing promises we don't always keep. If we did, I think we could introduce a precisetime module for it.

    @l8gravely also follow #619 for a different way to do things concurrently.

  7. CameronDevine commented on Mar 6, 2018

    @CameronDevine

    Would it be possible to have a variable which states the approximate interval at which time.monotonic() is increased? This would save people form having to write code to guess what the interval is, since it appears to change based on which board is being used.

  8. jepler commented on Apr 9, 2018

    @jepler

    like @l8gravely I want a monotonic time source which doesn't lose precision. In my project, I want to show the seconds and fractions of seconds based on NTP time, but it starts to lose precision as the monotonic() value gets large.

    For me, directly exposing common_hal_time_monotonic(), possibly via the microcontroller module, seems like a good first step. I'm not sure whether exposing it as a 64-bit value (restricting it to devices with support for longs) is better, or exposing it as unix-style (seconds,microseconds} is better. The latter is sure less convenient for doing math on, and forces the choice of a fractional second size of microseconds or coarser (rather than nanoseconds or 2^-32s) in order to avoid overflows while doing arithmetic (+, -) on timestamps with limited integer precision available.

  9. tannewt commented on Apr 9, 2018

    @tannewt
    Member

    I was thinking we could add a precise_time module too.

  10. margaret commented on May 14, 2018

    @margaret

    I'm going to take a stab at this (pycon sprints)

  11. CBMalloch commented on Sep 10, 2018

    @CBMalloch

    I'm trying to sample a 1kHz modulated light beam at 100µs intervals. About every 1/32 sec I go into a coma for almost 1/32 sec while the system does its other things. More precise timing would not help unless we also had a "suspend the other system things for a mo while I do this time-critical thing" function...

  12. tannewt commented on Sep 11, 2018

    @tannewt
    Member

    @CBMalloch how is the light beam being interfaced to the microcontroller? We may be able to add a C helper for it.

    It's highly unlikely we'll ever allow for predictable timing in Python execution. There are too many critical things happening around the VM to do it.

  13. jak3kay commented on Oct 8, 2018

    @jak3kay

    As time.monotonic() becomes less precise over time I support having a precise_time module with a custom timer with millisecond precision. It would be very useful if the module had a resettable timer that is independent of the changing precision provided by time.monotonic(). A precise_time module could provide something like this to allow timing of events with higher precision:

    precise_time.reset() 
    # do processing 
    process_time = precise_time.time()
    
  14. parsko41 commented on Oct 22, 2018

    @parsko41

    Hi all,
    I'm also interested in a better timer. I'm more interested in knowing how long it takes to execute stuff. So, a read-only timer, to the usec would be very useful.

    I've been playing with this and just realized that time.monotonic() is only good to 1 decimal. But, learned that is dependent on time since last restarted or reset(?)

    Just wanted to chime in to say that I am also looking for the feature.

    Thanks,

    -Parsko

  15. gmparis commented on Nov 3, 2018

    @gmparis

    I'll chime in on this too, since I recently ran into this limitation after switching a project from Arduino to CircuitPython. The project requires events triggered with at least 0.1 second resolution, but using monotonic() begins to fail. The only fix is to have the device reset as the resolution limit approaches. This is insufficient for my use case. I can't think of another way around it.

    Even a rollover counter like millis() is preferable to monotonic(), as at least I can keep track of the rollovers and manage my own counter. Helping people port from Arduino also would argue for a millis()-like function, even if such does not exist in CPython.

    Thanks for listening!
    Greg

  16. tannewt commented on Nov 4, 2018

    @tannewt
    Member

    @gmparis time.monotonic_ns() will be released with the next 4.x alpha. Feel free to try a test build from here until then.

  17. tballas commented on Dec 13, 2018

    @tballas

    So, I just put 4.0.0 alpha 5 on my Trinket M0 expecting to be able to use time.monotonic_ns() This is what I get in REPL:

    Adafruit CircuitPython 4.0.0-alpha.5 on 2018-12-10; Adafruit Trinket M0 with samd21e18
    >>> import time
    >>> help(time)
    object <module 'time'> is of type module
      __name__ -- time
      monotonic -- <function>
      sleep -- <function>
      struct_time -- <class 'struct_time'>
    >>> time.monotonic_ns()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'module' object has no attribute 'monotonic_ns'
    >>>
    

    I wonder why it's not enabled?

  18. dhalbert commented on Dec 13, 2018

    @dhalbert
    CollaboratorAuthor

    We're only enabling time.monotonic_ns() on the Express builds. We need Python long integers for monotonic_ns() or else the values will wrap around after a few seconds. Unfortunately there's not enough room in the Trinket or Gemma builds for long integers (longints).

  19. tballas commented on Dec 13, 2018

    @tballas

    Ah, that's unfortunate to hear. Thank you for explaining.

  20. l8gravely commented on Dec 13, 2018

    @l8gravely
  21. framlin commented on Dec 19, 2018

    @framlin

    Hello, I am totally new to this circuitpython stuff.
    What I am looking for, is a timer-callback, that will be executed repeatedly after a certain period of time (something like setInterval(callback, period) in JavaScript).
    This should run asynchronous, that means, that my program is not sleeping, but could do other stuff meanwhile.
    Is that possible with circuitpython? If so, is there any example?

  22. dhalbert commented on Dec 19, 2018

    @dhalbert
    CollaboratorAuthor

    @framlin - sorry, we don't have callbacks or other asynchronous features right now (they are in MicroPython but we're not using them). We're working on coming up with simpler concurrency mechanisms that are easy to understand, e.g. #1380.

  23. zamfi commented on Mar 14, 2019

    @zamfi

    I was able to get this running on my Metro M0 Express, but it looks like time.monotonic_ns() still only returns a value with a resolution of milliseconds.

    Is there an equivalent to the micros() call available on the Arduino platform?

  24. kevinjwalters commented on Nov 11, 2019

    @kevinjwalters

    @dhalbert Why does it make the builds bigger, is this just because literal ints end up with a larger representation in mpy files? Would having yet another function to return (seconds, milliseconds) as an (int,int) tuple be another option to support all boards?

    (Discussion/issue in https://forums.adafruit.com/viewtopic.php?f=60&t=158501 reminded me of this)

  25. dhalbert commented on Nov 11, 2019

    @dhalbert
    CollaboratorAuthor

    @kevinjwalters The builds are bigger because we need longints to support time.monotonic_ns() values, which are larger than regular ints.

    We have talked about adding another function, but it would not be in time, because we don't want to add new functionality to a standard module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions