A lot of my drivers use time.sleep_ms() and time.sleep_us() for accurate timing, however, CircuitPython on the ESP8266 seems to be missing those.
time.sleep() takes a float so use that. I removed time.sleep_ms and time.sleep_us because they don't exist in CPython and I want code to port to CPython.
Floats require memory allocation and can't express accurate timing. They are also not available on all ports of MicroPython.
How accurate does your timing need to be? We could add functions outside of time for it if its really needed.
CircuitPython only supports SAMD21 and ESP8266 which both have floats.
Well, time.sleep_us() lets me set delays with 1碌s precision, though in practice just executing that command will take more. But that's not the important part.
More importantly, I would like my libraries to work both for MicroPython (including the ports that don't have floats) and for CircuitPython (at least the ESP8266 port, which claims to be retaining compatibility with MicroPython, at least from what I've heard so far about it). I suppose I could do something like:
try:
from time import sleep_us
except ImportError:
from time import sleep
def sleep_us(us):
sleep(us/1000000)
but it seems like a hack. If there is no other way, I will have to just do that.
I guess at some point I will need to develop a library similar to Python's six for dealing with this kind of things.
Why do you need 1us precision in a driver? Please provide an example.
CircuitPython's goals do not vary per port. The compatibility comment about ESP8266 only relates to keeping the machine module around rather than removing it.
time is incompatible with MicroPython in favor of being compatible with CPython. Thats also why we have monotonic instead of ticks_ms.
Another way to do your import would be to try and import utime which is only available on MicroPython.
But then I would still need to somehow create the sleep_us function on CircuitPython.
Is there a chance for having utime in CircuitPython?
Hi @deshipu,
I'm trying to understand the discussion here. I'm following that utime exists in MicroPython, and CircuitPython uses time for consistency with CPython and better handling of boards that cannot provide 1us precision reliably.
Answering @tannewt's question or providing similar information would help me understand possibilities and tradeoffs. Thanks!
Why do you need 1us precision in a driver? Please provide an example.
I don't have a particular use case where I would need 1碌s precision (the time it takes to execute the Python code calling the sleep functions would be much longer than that). That was just one example of how using floats differs from using integers.
The particular problem I have is that I wrote a number of device drivers for MicroPython. Those drivers need some delays, and use time.sleep_ms() and time.sleep_us() functions for them where appropriate. It would be nice to be able to also use the same drivers under CircuitPython, at least on the ESP8266, without having to write a special version, or to use nasty boilerplate code like the example above.
If that is not possible, it's fine, I will just add to the documentation that they don't work in CircuitPython and move on. I initially thought that the missing functions are a bug, since it's not documented anywhere -- that's why I reported it -- but now I see this is a deliberate incompatibility. I reopened the issue to point out the differences between time.sleep and time.sleep_ms and time.sleep_us, but I think that by now we all have the full information, and this can be closed.
Thanks @deshipu. That helps my understanding. I appreciate the clarification.
@tannewt Any additional thoughts on keeping compatibility with CPython in CircuitPython while improving @deshipu's ability to use the device drivers based on utime?
I think I can have a separate utime.py module, with sleep_ms and sleep_us functions implemented in terms of time.sleep(). Then I can just tell users to put that module on their boards together with my drivers if they are using CircuitPython. This seems like the best solution for this problem so far. Those functions still can't be used inside interrupt handlers (because they allocate memory to create the floats) and they will introduce additional delays (both for the function call and for creating the float), but it will mostly work.
I'm open to having a separate utime module for compatibility with MicroPython. However, I don't think doing that is worth the tradeoff.
The benefit is that the drivers work across all existing MicroPython boards including the WiPy, which is the main board without float support. The detriment is that utime will not teach folks how to use CPython and the code will not be portable to CPython without another library. To me, the benefit isn't worth it. My preference would be to use time.sleep and NOT support MicroPython boards without float support. We'd still support the majority of boards, PyBoard, Teensy, ESP8266.
@willingc Thanks for asking clarifying questions!
What's your recommendation for the interrupt handler code for avoiding memory allocation for the floats?
It shouldn't be an issue because floats are not separate objects with representation C. https://github.com/adafruit/circuitpython/blob/master/py/mpconfig.h#L71
Ah, I was wrong, I thought they are regular python objects. Thanks, that solves all the issues.
Most helpful comment
Ah, I was wrong, I thought they are regular python objects. Thanks, that solves all the issues.