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
Slow bitbanging with python 3.5+ #72
Comments
Also note that this problem probably affects a bunch of other Pimoroni libs... |
Thank you for detailing this- I suspect if you'd come to me with a surface level symptom and not this in-depth analysis I'd have spent a whole day scratching my head. It's appreciated! Interestingly the sleeps were only added relatively recently here- 7a92169 In response to this issue: #62 It appeared that under certain conditions it's was possible to set and clear the GPIO pins before the change had propagated to hardware. The short sleep ensured a pin state change actually resulted in a physical voltage level change that was picked up by the APA102s. In this case a switch to SPI would, indeed, fix the problem but the non-standard pins used mean using a dtoverlay and adding a lot of complexity that I'd really like to avoid in what's intended to be a simple add-on board for beginners. From what I understand, This same issue will apply to Rainbow HAT at the very least- pimoroni/rainbow-hat@860b330 |
I am now having trouble getting it to work at all with any delay on any python version. Oddly the |
Do you have any references for the code behind this change? I did some digging through CPython on GitHub but couldn't turn up anything like a smoking gun. There were a few changes ~4 years ago, which I believe corresponds to the release of 3.5. On Linux it looks like it leans on |
No, I could not find the specific change. It would require a bisect as there are loads of changes. |
Actually measuring this - with the main loop
|
That is what I was seeing before, but now everything has gone weird. I'm making a fresh image and re-testing. |
The weirdness was caused by having them on a 20cm cable. Everything works fine with no cable. The slow sleep just causes slow framerate. Also noticed some other weird stuff not really related to this bug, see discord. |
In the Blinkt core library
time.sleep(0.0000005)
is used to time GPIO changes.The minimum amount of time that
time.sleep(n>0.000001)
can sleep under Linux is about 60 microseconds on a fast desktop machine, or about 100 microseconds on a Pi Zero. If you ask fortime.sleep(0)
then the function essentially becomes a no-op, which takes about 0.5 usec on desktop and about 14 usec on Pi Zero.However, if you ask for
time.sleep(0.0000001>n>0)
(ie less than 1 usec but more than 0) then the behaviour has changed in Python 3.5+. In earlier versions, this would be treated as 0 and you get the fast no-op sleep. In 3.5+ you get the slower minimum real sleep.So in practice
time.sleep(0.0000005)
runs about 7x slower on Python 3.5 than on previous versions. Under Python 2 it was already sleeping for up to 28x longer than you asked for, and now under Python 3.5+ it is sleeping for a total of 200x longer. This means it takes on order of 0.1 seconds to bit bang all the pixels. This causes the examples to run at half speed because they havetime.sleep(0.1)
in the main loop, and in my testing thelarson.py
example does not work at all due to this issue.You can get the same behaviour as Python 2 by simply changing to
time.sleep(0)
or calling some other no-op/busy loop. Perhaps you don't even need the sleeps at all. Switching to the kernel SPI as suggested on #65 would also solve the problem.The text was updated successfully, but these errors were encountered: