scottlawsonbc / audio-reactive-led-strip

:musical_note: :rainbow: Real-time LED strip music visualization using Python and the ESP8266 or Raspberry Pi
MIT License
2.71k stars 641 forks source link

Optimization improvements for the raspberry pi? #160

Open iceonfire1 opened 6 years ago

iceonfire1 commented 6 years ago

This project is great, super fun to use / play with. The major issue I encountered was getting a decent fps on the raspberry pi.

I ran the code through the basic python profiler and noticed these lines from _update_pi() in led.py was taking a lot of time:

if np.array_equal(p[:, i], _prev_pixels[:, i]): continue

Commenting it out, as:

# Update the pixels for i in range(config.N_PIXELS): # Ignore pixels if they haven't changed (saves bandwidth) #if np.array_equal(p[:, i], _prev_pixels[:, i]): # continue strip._led_data[i] = rgb[i] # _prev_pixels = np.copy(p) _prev_pixels = p

(sorry about the line indents, IDK how this comment formatting works)

Took me from ~5fps -> ~18fps on the pi zero w and from ~20 to >60fps on the pi 3b+, with 240 led's.

I'm assuming the comment is about network bandwidth and this step is unnecessary for the pi, since the led's are all updated in each step anyway. Can anyone confirm this, though?

Does anyone else have suggestions for optimizations for the pi? It'd be pretty cool if I could use a zero w instead of a 3b+ for this.

andrealbers commented 5 years ago

This worked for me pretty good. I‘m using a RPi 3 running on 70fps without problems (before max. 25 FPS).

dkaulukukui commented 5 years ago

dude!!! thats amazing. I just went from <10 fps to 30 fps on the Pi Zero.

joeybab3 commented 5 years ago

I think you're right, seems like everyone has had better results with this who has tried.

It appears that that line is just to say essentially if the array of pixels is the same as last time then don't send it, but I could see this causing a computational overhead to replace the network overhead.

meesvandenberg commented 5 years ago

`def _update_pi(): """Writes new LED values to the Raspberry Pi's LED strip

Raspberry Pi uses the rpi_ws281x to control the LED strip directly.
This function updates the LED strip with new values.
"""
global pixels, _prev_pixels
# Truncate values and cast to integer
pixels = np.clip(pixels, 0, 255).astype(int)
# Optional gamma correction
p = _gamma[pixels] if config.SOFTWARE_GAMMA_CORRECTION else np.copy(pixels)
# Encode 24-bit LED values in 32 bit integers
r = np.left_shift(p[0][:].astype(int), 8)
g = np.left_shift(p[1][:].astype(int), 16)
b = p[2][:].astype(int)
rgb = np.bitwise_or(np.bitwise_or(r, g), b)
# Update the pixels
for i in range(config.N_PIXELS):
    # Ignore pixels if they haven't changed (saves bandwidth)
    # Update the pixels 
    for i in range(config.N_PIXELS): 
        # Ignore pixels if they haven't changed (saves bandwidth) 
        #if np.array_equal(p[:, i], _prev_pixels[:, i]): 
        # continue 
        strip._led_data[i] = rgb[i] 
        # _prev_pixels = np.copy(p) 
        _prev_pixels = p
        strip._led_data[i] = rgb[i]
_prev_pixels = np.copy(p)
strip.show()`

I have this in my led.py but the fps rate is decreasing. Can someone help me?

senchden commented 4 years ago

I can confirm it too. Went from 3-4 fps to 11-12 with 144 LEDs.

lflondonol92 commented 4 years ago

I just try this in my Pi Zero but I am still getting 4-5 FPS. Could you please check if I am doing something wrong? `def _update_pi(): """Writes new LED values to the Raspberry Pi's LED strip

Raspberry Pi uses the rpi_ws281x to control the LED strip directly.
This function updates the LED strip with new values.
"""
global pixels, _prev_pixels
# Truncate values and cast to integer
pixels = np.clip(pixels, 0, 255).astype(int)
# Optional gamma correction
p = _gamma[pixels] if config.SOFTWARE_GAMMA_CORRECTION else np.copy(pixels)
# Encode 24-bit LED values in 32 bit integers
r = np.left_shift(p[0][:].astype(int), 8)
g = np.left_shift(p[1][:].astype(int), 16)
b = p[2][:].astype(int)
rgb = np.bitwise_or(np.bitwise_or(r, g), b)
# Update the pixels
for i in range(config.N_PIXELS):
    # Ignore pixels if they haven't changed (saves bandwidth)
    #if np.array_equal(p[:, i], _prev_pixels[:, i]):
    #    continue

    strip._led_data[i] = int(rgb[i])
#_prev_pixels = np.copy(p)
_prev_pixels = p
strip.show()`