From f8515bdddeca81af19d812253587f474a16e3b06 Mon Sep 17 00:00:00 2001 From: jimmy Date: Sat, 23 Dec 2023 09:03:16 +0000 Subject: [PATCH] Switch to async --- ws2812b.py | 206 ++++++++++++++++++++++++++++------------------------- 1 file changed, 110 insertions(+), 96 deletions(-) diff --git a/ws2812b.py b/ws2812b.py index 2cfb56e..384de56 100644 --- a/ws2812b.py +++ b/ws2812b.py @@ -1,96 +1,110 @@ -# Example using PIO to drive a set of WS2812 LEDs. - -import array, time -from machine import Pin -import rp2 -from random import randint -from time import sleep - -# Configure the number of WS2812 LEDs. -NUM_LEDS = 256 -PIN_NUM = 0 -brightness = 0.2 - -@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) -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() - -class WS2812B: - def __init__(self, num_leds, pin_num, brightness): - # Create the StateMachine with the ws2812 program, outputting on pin - self.sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(pin_num)) - - # Start the StateMachine, it will wait for data on its FIFO. - self.sm.active(1) - - # Display a pattern on the LEDs via an array of LED RGB values. - self.ar = array.array("I", [0 for _ in range(num_leds)]) - self.num_leds = num_leds - self.brightness = brightness - - ########################################################################## - def pixels_show(self): - dimmer_ar = array.array("I", [0 for _ in range(self.num_leds)]) - for i,c in enumerate(self.ar): - r = int(((c >> 8) & 0xFF) * self.brightness) - g = int(((c >> 16) & 0xFF) * self.brightness) - b = int((c & 0xFF) * self.brightness) - dimmer_ar[i] = (g<<16) + (r<<8) + b - self.sm.put(dimmer_ar, 8) - time.sleep_ms(10) - - def pixels_set(self, i, color): - self.ar[i] = (color[1]<<16) + (color[0]<<8) + color[2] - - def pixels_fill(self, color): - for i in range(len(self.ar)): - self.pixels_set(i, color) - - def color_chase(self, color, wait): - for i in range(self.num_leds): - self.pixels_set(i, color) - time.sleep(wait) - self.pixels_show() - time.sleep(0.2) - - def wheel(self, pos): - # Input a value 0 to 255 to get a color value. - # The colours are a transition r - g - b - back to r. - if pos < 0 or pos > 255: - return (0, 0, 0) - if pos < 85: - return (255 - pos * 3, pos * 3, 0) - if pos < 170: - pos -= 85 - return (0, 255 - pos * 3, pos * 3) - pos -= 170 - return (pos * 3, 0, 255 - pos * 3) - - - def rainbow_cycle(self, wait): - for j in range(255): - for i in range(self.num_leds): - rc_index = (i * 256 // self.num_leds) + j - self.pixels_set(i, self.wheel(rc_index & 255)) - self.pixels_show() - time.sleep(wait) - - BLACK = (0, 0, 0) - RED = (255, 0, 0) - YELLOW = (255, 150, 0) - GREEN = (0, 255, 0) - CYAN = (0, 255, 255) - BLUE = (0, 0, 255) - PURPLE = (180, 0, 255) - WHITE = (255, 255, 255) - COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE) \ No newline at end of file +# Example using PIO to drive a set of WS2812 LEDs. + +import array, time +from machine import Pin +import rp2 +from time import sleep +import uasyncio as asyncio + +# Configure the number of WS2812 LEDs. +NUM_LEDS = 256 +PIN_NUM = 0 +brightness = 0.2 + +@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) +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() + +class WS2812B: + def __init__(self, num_leds, pin_num, brightness, sm): + # Create the StateMachine with the ws2812 program, outputting on pin + self.sm = rp2.StateMachine(sm, ws2812, freq=8_000_000, sideset_base=Pin(pin_num)) + + # Start the StateMachine, it will wait for data on its FIFO. + self.sm.active(1) + + # Display a pattern on the LEDs via an array of LED RGB values. + self.ar = array.array("I", [0 for _ in range(num_leds)]) + self.num_leds = num_leds + self.brightness = brightness + + ########################################################################## + async def pixels_show(self): + self.sm.put(self.ar, 8) + await asyncio.sleep(0.00001) + + def pixels_set(self, i, color): + self.ar[i] = (int(color[1]*self.brightness)<<16) + (int(color[0]*self.brightness)<<8) + int(color[2]*self.brightness) + + def pixels_fill(self, color): + for i in range(len(self.ar)): + self.pixels_set(i, color) + + async def color_chase(self, color, wait): + for i in range(self.num_leds): + self.pixels_set(i, color) + await asyncio.sleep(wait) + await self.pixels_show() + await asyncio.sleep(0.2) + + def wheel(self, pos): + # Input a value 0 to 255 to get a color value. + # The colours are a transition r - g - b - back to r. + if pos < 0 or pos > 255: + return (0, 0, 0) + if pos < 85: + return (255 - pos * 3, pos * 3, 0) + if pos < 170: + pos -= 85 + return (0, 255 - pos * 3, pos * 3) + pos -= 170 + return (pos * 3, 0, 255 - pos * 3) + + + async def rainbow_cycle(self, wait): + for j in range(255): + for i in range(self.num_leds): + rc_index = (i * 256 // self.num_leds) + j + self.pixels_set(i, self.wheel(rc_index & 255)) + await self.pixels_show() + await asyncio.sleep(wait) + + BLACK = (0, 0, 0) + RED = (255, 0, 0) + YELLOW = (255, 150, 0) + GREEN = (0, 255, 0) + CYAN = (0, 255, 255) + BLUE = (0, 0, 255) + PURPLE = (180, 0, 255) + WHITE = (255, 255, 255) + COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE) + + +async def run(pin, sm): + ws = WS2812B(10, pin, 1, sm) + ws.pixels_fill(ws.RED) + while True: + await ws.rainbow_cycle(0) + + + +if __name__ == "__main__": + loop = asyncio.get_event_loop() + asyncio.create_task(run(0,0)) + asyncio.create_task(run(17,1)) + asyncio.create_task(run(18,2)) + loop.run_forever() + + + +