import math import sys if "lib" not in sys.path: sys.path.insert(0, "lib") if "../lib" not in sys.path: sys.path.insert(0, "../lib") from ws2812 import WS2812B import time # --- Roll: N buffers (length = max strip), gradient full -> off; sequence through strips --- N_BUFFERS = 32 # more buffers = smoother transition STRIP_CONFIG = ( (2, 291), (3, 290), (4, 283), (7, 278), (0, 275), (28, 278), (29, 283), (6, 290), ) strips = [] sm = 0 for pin, num_leds in STRIP_CONFIG: print(pin, num_leds) ws = WS2812B(num_leds, pin, sm, brightness=1.0) strips.append(ws) sm += 1 num_strips = len(strips) max_leds = max(ws.num_leds for ws in strips) # Color when "on" (R, G, B); GRB order in buffer ROLL_COLOR = (0, 255, 120) # cyan-green def make_gradient_buffers(n_buffers, max_leds, color): """Create n_buffers buffers, each max_leds long. Buffer 0 = full brightness, last = off. Gradient is logarithmic (perceptually smoother: more steps near full, fewer near off). GRB order.""" out = [] for j in range(n_buffers): # log gradient: scale = 255 * log(1 + (n - 1 - j)) / log(n) so 255 at j=0, 0 at j=n-1 if n_buffers <= 1: scale = 255 elif j >= n_buffers - 1: scale = 0 else: # 1 + (n_buffers - 1 - j) runs from n_buffers down to 1 scale = int(255 * math.log(1 + (n_buffers - 1 - j)) / math.log(n_buffers)) scale = min(255, scale) buf = bytearray(max_leds * 3) r = (color[0] * scale) // 255 g = (color[1] * scale) // 255 b = (color[2] * scale) // 255 for i in range(max_leds): o = i * 3 buf[o] = g & 0xFF buf[o + 1] = r & 0xFF buf[o + 2] = b & 0xFF out.append(buf) return out # N buffers: first full, last off, gradient between buffers = make_gradient_buffers(N_BUFFERS, max_leds, ROLL_COLOR) step = 0 delay_ms = 50 # Deadline-based loop: no extra pause at rotation wrap, smooth continuous roll next_ms = time.ticks_ms() while True: for i, strip in enumerate(strips): buf_index = (step + i) % N_BUFFERS strip.show(buffers[buf_index], 0) step += 1 # unbounded; wrap only in index so no hitch at cycle end next_ms += delay_ms # Sleep until next frame time (handles drift, no pause at wrap) while time.ticks_diff(next_ms, time.ticks_ms()) > 0: time.sleep_ms(1)