-
Notifications
You must be signed in to change notification settings - Fork 43
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
Very slow #21
Comments
Yes it's software SPI. Your best bet is to inspect the source code and try to figure out a more efficient method without the abstraction. I didn't think it would be that slow on a Pi 1. I'll take a look when I get chance. |
I'm not much familiar with SPI, just tried to look up something. Is there a documentation of the RGB tree implementation anywhere? I mean like timing, etc. It seems that HW implementation is very often silently expected. I mean like several node.js SPI libraries, none of them supporting SW SPI, only HW (mentioning node.js as I know it better than Python). |
Not that I know of, but the underlying SPI code is here: https://github.com/gpiozero/gpiozero/blob/master/gpiozero/spi_devices.py#L52 and the tree-specific stuff is here: https://github.com/ThePiHut/rgbxmastree/blob/master/tree.py |
It is indeed slow, I'm using it on a Pi Zero. But there's a workaround. You can assign directly to the tree.value property, which is a tuple made up of as many tuples as you have LEDs on your tree. Which means you could code a loop and for each iteration, build a tuple made of all the colors you'd like, then assign it to tree.value. So in my opinion, you could try that before going deeper. I've already experimented a bit on it but I intend to keep going to develop something with some effects. |
Yes, but that's actually what's pretty slow, e.g. just changing tree.color, which internally changes tree.value in a single step results in one-by-one LED changes (for the older/slower Pi). However, I found a solution. It's Node.js based, mainly because I'm more familiar with node than python, but also I found a good library that works really fast: https://www.npmjs.com/package/pigpio. A simple code that goes through red, blue and green colors for all the 25 LEDs is so fast, that you don't even see the individual colors, just a jittery white! So, probably 100x or more faster than the Python code. ;-) Just needs to be run as root, but it's not a big deal for me. |
@jirihajek Could you share some code using |
Sure, the basics are actually very easy, here's how to send a bit:
There might be some timeout needed after the clock pin write, but it works like this fine on my old Pi. And this does all the other basic stuff needed to update all the LEDs:
Note that Just finishing Blockly visual language implementation to let my son program the LED tree from his iPad... ;-) |
Thanks for sharing @jirihajek . Will have a look into Blockly. sounds interesting. I've been creating different lighting sequences over here. If I get it working I'll translate them into nodejs and try to do more sequences. There were a few things that I tried when using the Python module that didn't work out due to the slowness. Ideally I would like to circle back and improve the tree.py module once I understand what's going on. |
For Python users, the speed improves a lot if you use the pigpio library instead of rpigpio. (This may be the same library suggested by jirihajek; it has a Python interface as well as Node.) You have to install the pigpio and python3-pygpio packages, and then you have to run the examples with the environment variable GPIOZERO_PIN_FACTORY set to "pigpio". The pigpio daemon has to be started as well. For some reason this is about ten times faster than rpigpio. On my RPi 3B, assigning to "tree.color" takes about 22 milliseconds with pigpio, but about 270 milliseconds with rpigpio. pigpio still uses software SPI, but the speed is similar to driving the SPI pins directly with GPIO.output from within the tree "value" method. |
I just updated a generic library for APA102 LED strips, see https://github.com/tinue/apa102-pi |
If anyone is still interested in this, since I also wasn't happy with CPU usage of rpigpio, based on jirihajek's comment I put together a full Node.js version of onebyone.py using pigpio: https://github.com/karabaja4/nodexmastree |
TL;DR: the above comments solve the slow SPI message sending either by not using a Pi zero, stripping the Python layers, rewriting it in C++ or by bulk setting the LEDs. The latter solution is far simpler, here is a snippet: import random
from tree import RGBXmasTree
from typing import Tuple, List, Sequence
def saturated_random_color(max_brightness:int=1) -> Tuple[float]:
colors = [random.random() * max_brightness, random.random() * max_brightness, 0.]
random.shuffle(colors)
return tuple(colors) # need not be tuple
def random_colors(prior: Sequence[Tuple[float, float, float]], unchanged_probability:float=.80, max_brightness:float=1):
"""
It actually is a bit too fast, hence ``unchanged_probability``.
"""
colors = []
for i in range(24):
# change off pixels to on
if prior[i] == [0.0, 0.0, 0.0]:
colors.append( saturated_random_color(max_brightness=max_brightness) )
# chance to keep a pixel colour
elif random.randint(0,100)/100 < unchanged_probability:
colors.append( prior[i] )
# apex always on
elif i == 3:
colors.append( saturated_random_color(max_brightness=1.) )
# c
elif random.randint(0,1):
colors.append( saturated_random_color(max_brightness=max_brightness) )
else:
colors.append( (0.0, 0.0, 0.0) )
return colors
def main():
tree = RGBXmasTree()
try:
values: Sequence[Tuple[float, float, float]] = [(0,0,0) for i in range(24)]
while True:
values = random_colors(values)
tree.value = values
except KeyboardInterrupt:
tree.close()
print('closed') |
@matteoferla that is nice and simple. |
Hi, my tree works, but is very slow. Setting a single value takes about a second (or more). I found out that it's device specific, it's slow on the old Pi 1.2B, but works fine on Pi 4B. Is it because of the software based SPI transfer? Any idea how to make this faster?
I'd need to use it on the old Pi and in the current state it's hard to code any meaningful effect, as you literally see the LEDs changing one by one.
Thanks!
The text was updated successfully, but these errors were encountered: