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

MicroPython doesn't have time.monotonic() or time.monotonic_ns() #9

Open
fred-cardoso opened this issue Aug 13, 2021 · 4 comments
Open
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@fred-cardoso
Copy link

Hi!

Not sure if you are supporting MicroPython or just targetting CircuitPython with this library.
I found out that MicroPython does not have the monotonic() method on the time module. I changed the monotonic call to time and monotonic to time_ns and I was able to make it run.
Not sure if these timers are good enough for this purpose, I haven't check that.

Any tip?

@Rybec
Copy link
Owner

Rybec commented Aug 13, 2021

I'm not officially supporting MicroPython, but I am generally willing to resolve MicroPython issues, so long as the fixes won't cause any problems for CircuitPython or desktop Python.

So here's the official Python documentation on these*:

time.monotonic()
time.time()
(*The _ns versions work the same as the respective non-_ns versions, except for the measurement unit is integer ns.)

The main difference is that time.monotonic() doesn't adjust for things like leap seconds or system clock syncs, while time.time() does. This makes time.time() poorly suited to situations where current time makes no difference but timing is critical. (Specifically, with time.time(), leap seconds and leap years will cause your clock to skip time or drop back in time, and your system time merely being slightly slow or fast could cause the same when resyncing time.) pyRTOS is one of those situations.

That said, on embedded devices, where there is no "system time" as such, this is probably irrelevant. For your uses, time.time() is probably identical to time.monotonic(), so that is probably a perfectly suitable fix.

This isn't something I can currently change in pyRTOS though, because I am supporting desktop Python, where the difference is very much relevant. (And I don't really want to make it dynamically determine which to use, because this would increase the size of pyRTOS and decrease performance.)

My suggestion: If you are using MicroPython, change your local pyRTOS to use time.time() and time.time_ns(). I doubt it will make any difference. While you are at it though, you might want to file a feature request/bug report on MicroPython, mentioning that they should be able to fix this merely by implementing the monotonic time functions as aliases of the regular ones. The monotonic fuctions are part of the Python 3 standard since 3.3 (time.monotonic()) and 3.7 (time.monotonic_ns()), so this should increase MicroPython compatibility with standard Python.

I hope this helps. Thanks for letting me know about this. Perhaps I should add a section to the documentation on MicroPython compatibility, noting this issue and the workaround.

@Rybec Rybec changed the title micropython: MicroPython doesn't have time.monotonic() or time.monotonic_ns() Aug 13, 2021
@Rybec Rybec self-assigned this Aug 13, 2021
@Rybec Rybec added the documentation Improvements or additions to documentation label Aug 13, 2021
@fred-cardoso
Copy link
Author

Hi @Rybec

Sorry for the delay on the follow up.

My suggestion: If you are using MicroPython, change your local pyRTOS to use time.time() and time.time_ns(). I doubt it will make any difference. While you are at it though, you might want to file a feature request/bug report on MicroPython, mentioning that they should be able to fix this merely by implementing the monotonic time functions as aliases of the regular ones. The monotonic fuctions are part of the Python 3 standard since 3.3 (time.monotonic()) and 3.7 (time.monotonic_ns()), so this should increase MicroPython compatibility with standard Python.

Yes, I exactly did that and it's working well. But to be honest I didn't had the chance to do tests with time critical tasks etc. You can close this issue 😃

Thanks for the clarification! Keep up with the good work.

@Rybec
Copy link
Owner

Rybec commented Aug 18, 2021

Thanks for the response!

I'm actually going to keep this open until I add a note on this to the documentation. Even if I can't fully support MicroPython, I would like to make it easy to adapt.

@gareins
Copy link

gareins commented Jul 21, 2023

time() for some reason returns integer only and time_ns() returns time() * 10e9 on my pico w. On the other hand, ticks work better so I solved this by adding a time.py to the root of the project with this contents:

# pyright: reportShadowedImports=false, reportWildcardImportFromLibrary=false

from utime import *

def monotonic():
    return ticks_ms() / 1000

def monotonic_ns():
    return ticks_us() * 1000

This means that time_ns has only microsecond precision, but this is good enough for me :)

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

No branches or pull requests

3 participants