raspberrypi / pico-micropython-examples

Examples to accompany the "Raspberry Pi Pico Python SDK" book.
BSD 3-Clause "New" or "Revised" License
1.01k stars 228 forks source link

neopixel_ring.py Green led timing issue? #36

Closed HyFy2SyFy closed 3 years ago

HyFy2SyFy commented 3 years ago

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(): dimmerar = 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`

aallan commented 3 years ago

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