raspberrypi/pico-micropython-examples

neopixel_ring.py Green led timing issue?

HyFy2SyFy opened this issue · 1 comments

When using a RGBW Neopixel ring and the green neopixel led is being used the pixels_fill() and pixels_show() methods take longer to execute. Has a noticeable effect on fast color fade in and outs. Tested on RGBW 12 Neopixel ring. Any ideas as to what is causing the issue and any possible fixes?

Timing tests of pixels_fill() and pixels_show() methods

Fill took 0.842 milli seconds for color: RED
Show took 12.763 milli seconds for color: RED

Fill took 1.542 milli seconds for color: YELLOW
Show took 14.026 milli seconds for color: YELLOW

Fill took 1.539 milli seconds for color: GREEN
Show took 13.988 milli seconds for color: GREEN

Fill took 1.541 milli seconds for color: CYAN
Show took 14.054 milli seconds for color: CYAN

Fill took 0.815 milli seconds for color: BLUE
Show took 12.76 milli seconds for color: BLUE

Fill took 0.823 milli seconds for color: PURPLE
Show took 12.746 milli seconds for color: PURPLE

Fill took 0.822 milli seconds for color: WHITE
Show took 12.761 milli seconds for color: WHITE

Fill took 1.557 milli seconds for color: WHITE(RGB)
Show took 14.082 milli seconds for color: WHITE(RGB)

Fill took 0.829 milli seconds for color: ORANGE
Show took 12.771 milli seconds for color: ORANGE

Adapted code for RGBW Neopixel -
`# Example using PIO to drive a set of WS2812 LEDs.

import array, time
from machine import Pin
import rp2

NUM_LEDS = 12
PIN_NUM = 22
brightness = 0.2

@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=32)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()

sm = rp2.StateMachine(1, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))

sm.active(1)

ar = array.array("I", [0 for _ in range(NUM_LEDS)])

def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
for i,c in enumerate(ar):
r = int(((c >> 8) & 0xFF) * brightness)
g = int(((c >> 16) & 0xFF) * brightness)
b = int((c & 0xFF) * brightness)
w = int(((c >> 24) & 0xFF) * brightness)
dimmer_ar[i] = (w<<24) + (g<<16) + (r<<8) + b
sm.put(dimmer_ar, 0)
time.sleep_ms(10)

def pixels_set(i, color):
green = color[1]<<24
red = color[0]<<16
blue = color[2]<<8
white = color[3]
ar[i] = red + green + blue + white

def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)

def color_chase(color, wait):
for i in range(NUM_LEDS):
pixels_set(i, color)
time.sleep(wait)
pixels_show()
time.sleep(0.2)

def wheel(pos):
if pos < 0 or pos > 255:
return (0, 0, 0, 0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3, 0)
pos -= 170
return (pos * 3, 0, 255 - pos * 3, 0)

def rainbow_cycle(wait):
for j in range(255):
for i in range(NUM_LEDS):
rc_index = (i * 256 // NUM_LEDS) + j
pixels_set(i, wheel(rc_index & 255))
pixels_show()
time.sleep(wait)

BLACK = (0, 0, 0,0)
RED = (255, 0, 0,0)
YELLOW = (255, 125, 0,0)
GREEN = (0, 255, 0,0)
CYAN = (0, 255, 255,0)
BLUE = (0, 0, 255,0)
PURPLE = (180, 0, 255,0)
WHITE = (0,0,0,255)
WHITE_RGB = (255,255,255,0)
ORANGE = (255,40,0,0)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE, WHITE_RGB, ORANGE)
COLORNAMES = ('BLACK', 'RED', 'YELLOW', 'GREEN', 'CYAN', 'BLUE', 'PURPLE', 'WHITE', 'WHITE(RGB)', 'ORANGE')

print("fills")
for color in COLORS:
pixels_fill(color)
pixels_show()
time.sleep(0.2)

print("chases")
for color in COLORS:
color_chase(color, 0.01)

print("rainbow")
rainbow_cycle(0)

print("Timing tests of pixels_fill() and pixels_show() methods")
index = 0
for color in COLORS:
if index > 0: # Skip color BLACK
tic = time.ticks_us() # Start timer
pixels_fill(color)
toc = time.ticks_us() # Stop timer
print("")
print("Fill took {} milli seconds for color: {}".format((toc - tic) / 1000, COLORNAMES[index]))
tic = time.ticks_us() # Start timer
pixels_show()
toc = time.ticks_us() # Stop timer
print("Show took {} milli seconds for color: {}".format((toc - tic) / 1000, COLORNAMES[index]))
time.sleep(0.5)
index += 1`

Probably the best place to ask would be the MicroPython forums, https://forum.micropython.org/viewforum.php?f=21.