Reputation: 66
I wrote a python script using the rpi_ws281x
library that can animate an led strip attached to my rpi. The time it takes to run strip.show()
in color_fade
takes longer than when updating it directly in the run_animation
function. The delay is consistent too. I'm curious what's happening and if it can be fixed.
import threading
import time
from guy import Guy,http
import json
import sys
import requests
from rpi_ws281x import Color, PixelStrip, ws
from rgbw_colorspace_converter.colors.converters import RGB, Hex
def set_sec(color, first, last):
last += 1
for i in range((last-first)):
strip.setPixelColor(first + i, color)
strip.show()
def color_fade(color_from, color_to, time_len, start_led, end_led):
step_len = 5
steps = int(time_len/step_len)
step_R = (int(color_to[0]) - int(color_from[0])) / steps
step_G = (int(color_to[1]) - int(color_from[1])) / steps
step_B = (int(color_to[2]) - int(color_from[2])) / steps
step_W = (int(color_to[3]) - int(color_from[3])) / steps
r = int(color_from[0])
g = int(color_from[1])
b = int(color_from[2])
w = int(color_from[3])
print("start")
for _ in range(steps):
# This runs consistently slower, even with no delays/sleeps
start_time = time.time()
c = Color(int(r), int(g), int(b), int(w))
set_sec(c, start_led, end_led)
end_time = time.time()
print(f"Update time: {end_time - start_time} seconds") #0.03s
#time.sleep(step_len / 1000)
# Fading code, intentionally disabled
#print(r)
#print(step_R)
#r += step_R
#g += step_G
#b += step_B
#w += step_W
print("end")
killpills = {}
def run_animation(anim, loop, index):
if (loop):
print(killpills)
while killpills["anim" + str(index)]:
for i in range(len(anim)):
color = Hex(anim[i]["color"]).rgbw
if (anim[i]["tran"] == 'jump'):
if (anim[i]["type"] == 'bulb'):
requests.post('http://' + anim[i]["ip"] + '/cm?cmnd=color%20' +
str(color[0]) + ',' + str(color[1]) + ',' + str(color[2]) + ',' + str(color[3]))
elif (anim[i]["type"] == 'strip'):
# This runs quickly, even when looping it a bunch
start_time = time.time()
color = Color(color[0],color[1],color[2],color[3])
set_sec(color, int(anim[i]["start"]), int(anim[i]["end"]))
end_time = time.time()
print(f"Update time: {end_time - start_time} seconds") #0.01s
time.sleep(int(anim[i]["time"])/1000)
elif (anim[i]["tran"] == 'fade'):
if (not i == len(anim)-1):
color_fade(color, Hex(anim[i+1]["color"]).rgbw, int(anim[i]["time"]), int(anim[i]["start"]), int(anim[i]["end"]))
else:
color_fade(color, Hex(anim[0]["color"]).rgbw, int(anim[i]["time"]), int(anim[i]["start"]), int(anim[i]["end"]))
else:
for i in range(len(anim)):
color = Hex(anim[i]["color"]).rgbw
if (anim[i]["tran"] == 'jump'):
if (anim[i]["type"] == 'bulb'):
requests.post('http://' + anim[i]["ip"] + '/cm?cmnd=color%20' +
str(color[0]) + ',' + str(color[1]) + ',' + str(color[2]) + ',' + str(color[3]))
elif (anim[i]["type"] == 'strip'):
color = Color(color[0],color[1],color[2],color[3])
set_sec(color, int(anim[i]["start"]), int(anim[i]["end"]))
time.sleep(int(anim[i]["time"])/1000)
elif (anim[i]["tran"] == 'fade'):
if (anim[i]["type"] == 'bulb'):
speed = int(int(anim[i]["time"])/500)
if (not i == len(anim)-1):
color2 = Hex(anim[i+1]["color"]).rgbw
requests.post('http://' + anim[i]["ip"] + '/cm?cmnd=color%20' +
str(color[0]) + ',' + str(color[1]) + ',' + str(color[2]) + ',' + str(color[3]))
requests.post('http://' + anim[i]["ip"] + '/cm?cmnd=Fade2%20' + '1')
requests.post('http://' + anim[i]["ip"] + '/cm?cmnd=Speed2%20' + str(speed))
requests.post('http://' + anim[i]["ip"] + '/cm?cmnd=color%20' +
str(color2[0]) + ',' + str(color2[1]) + ',' + str(color2[2]) + ',' + str(color2[3]))
requests.post('http://' + anim[i]["ip"] + '/cm?cmnd=Fade2%20' + '0')
elif (anim[i]["type"] == 'strip'):
if (not i == len(anim)-1):
color_fade(color, Hex(anim[i+1]["color"]).rgbw, int(anim[i]["time"]), int(anim[i]["start"]), int(anim[i]["end"]))
def init_leds(pin, count):
global strip
# LED strip configuration:
LED_COUNT = count # Number of LED pixels. (900)
LED_PIN = pin # GPIO pin connected to the pixels (must support PWM!). (12)
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0
# LED_STRIP = ws.SK6812_STRIP_RGBW
LED_STRIP = ws.SK6812W_STRIP
# Create PixelStrip object with appropriate configuration.
strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
class index(Guy):
def play_anim(self, i):
global killpills
animation = []
killpills["anim" + str(i)] = True
for step in settings["anims"][i]["order"]:
print(step)
for light in settings["lights"]:
if (light["name"] == step["name"]):
animation.append({"type": "bulb", "ip": light["ip"],
"tran": step["tran"], "time": step["time"], "color": step["color"]})
for strip in settings["strips"]:
if (strip["name"] == step["name"]):
for group in strip["groups"]:
if (step["group"] == group["name"]):
animation.append({"type": "strip", "pin": strip["pin"],
"start": group["start"], "end": group["end"],
"tran": step["tran"], "time": step["time"], "color": step["color"]})
anim_thread = threading.Thread(target=run_animation, args=(animation, settings["anims"][i]["loop"], i))
anim_thread.start()
def stop_anim(self, i):
global killpills
killpills["anim" + str(i)] = False
app = index()
app.serve()
Irrelevant code chunks have been removed.
I know it's not a hardware limitation because setting the leds in the while loop directly in run_animation
refreshes plently quickly.
I've tried removing extra loops and moving the color_fade
call to the root of run_animation
but the delay still exists. I've tried putting the set_sec
code directly into color_fade
which changed nothing. The only thing that made it run faster was removing the strip.show()
command.
Upvotes: 1
Views: 53