Open ladyada opened 2 years ago
Looks like @dhalbert removed pulseio for the itsybitsy m0 express in commit 843598ec. I tested this with an itsybitsy m0 express and rcwl-1601 and it does work but the accuracy is terrible without pulseio.
We traded off pulseio
against other things when we needed space. Perhaps the library should not attempt to work without pulseio
.
I discovered that time.monotinic has limited accuracy. For the m0 it seems to be about 1000 microseconds. time.monotonic_ns seems to be about 183 microseconds.
Switching to monotonic_ns could reduce the problem but only to an accuracy of about 3 meters. Could something be done to improve the timing accuracy (possibly by modifying circuitpython?)
not really, the chip just isnt fast enough - faster chips can bitbang read the GPIO, the samd21 cannot!
I looked at the circuitpython code a bit and it looks like for the samd port the monotonic_ns function is timed off the rtc running at 16384hz so the resolution should be about 61us but for some reason I can only get a difference of 183us (I get a difference of 183us 25% of the time and 0 75% of the time). I think that means you could time an event as short as ~45us if the function returned a more precise value on the samd21.
I tested how fast you can check the pin and if the python is optimized some I think you can check the pin value in a loop while incrementing a timeout counter in ~41us per loop on the samd21. Combining these, you could time the echo as short as 45us with a precision of 61us but right now it's 183us for a reason I don't understand. That's about 3cm (I was incorrect when I said 3 meters in my last comment)
Just putting this info out there to better decide if pulseio should be required. 🙊
Continuing to try this on the Gemma M0 constrains you a lot. It would be easier if you replaced it with a QT Py RP2040 (not SAMD21) or some other small board, if form factor is an issue.
Precise timing in Python is never going to be a strong suit: there may be garbage collection delays, there are background task delays (such as processing USB interrupts), etc. That's our motivation for writing C-level code like pulseio
to do the timing-sensitive things.
I tried to use the HC-SR04 with my FT232H which doesn't have pulseio (to my knowledge). It wasn't working well with the original code. So I looked into it and changed time.monotonic()
to time.perf_counter()
. After that it worked better.
(As a side note, time.monotonic()
is as precise as time.monotonic_ns()
, it is just that the first one returns a float whereas the second one return a int. time.perf_counter()
is more precise. See perf_couter() in python documentation)
I was still unsatifyed with the results. Since the timing is critical and there was an unnecessary variable declaration (pulselen = None
and a _USE_PULSEIO
check, I removed them and now, it looks like it is a bit more accurate particularly at small distances.
I would recomand to make 2 functions, one for pulseio and one without and select which one to use in the init. This way you would have a fully optimise functions for each case. Hopefully, I was clear enough for you to make the change if you want to. Otherwise, if you want me to do a pull request, let me know! Thanks for this wonderfull resource!
from https://forums.adafruit.com/viewtopic.php?f=62&t=190920&p=924044#p924041
Behavior
Which is just random - no relation to distance of anything in front of the sensor. It's always just jumping between 0.0 and 17.xx
Description
No response
Additional information
No response