Pico panels get static IPs on 10.1.1.10–14 with per-panel LED counts, Makefile deploy targets, and Python examples for animations, sync tests, and direct Pi SPI control. Co-authored-by: Cursor <cursoragent@cursor.com>
100 lines
2.9 KiB
Python
Executable File
100 lines
2.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Two strips showing different patterns at the same time."""
|
|
|
|
import argparse
|
|
import sys
|
|
import time
|
|
|
|
from leds import LedStrips, board_family, board_model, default_dual_strip_configs, pi5_setup_hint
|
|
|
|
|
|
def _describe(cfg) -> str:
|
|
if cfg.backend == "pio":
|
|
return f"GPIO {cfg.pin} → {cfg.device}"
|
|
if cfg.backend == "ws281x":
|
|
return f"GPIO {cfg.pin} (channel {cfg.channel})"
|
|
return f"/dev/spidev{cfg.spi_bus}.{cfg.spi_device}"
|
|
|
|
|
|
def _wheel(pos: int) -> tuple[int, int, int]:
|
|
pos = pos % 256
|
|
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 chase(strip, color: tuple[int, int, int], step: int) -> None:
|
|
count = len(strip)
|
|
strip.fill((0, 0, 0))
|
|
strip[step % count] = color
|
|
|
|
|
|
def rainbow(strip, offset: int) -> None:
|
|
for i in range(len(strip)):
|
|
strip[i] = _wheel(offset + i * 256 // max(len(strip), 1))
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="WS2812 dual-strip demo")
|
|
parser.add_argument(
|
|
"-n",
|
|
"--count",
|
|
type=int,
|
|
nargs=2,
|
|
default=[200, 200],
|
|
metavar=("STRIP0", "STRIP1"),
|
|
help="LED count per strip (default: 10 10)",
|
|
)
|
|
parser.add_argument(
|
|
"--brightness",
|
|
type=float,
|
|
default=0.25,
|
|
help="brightness 0.0-1.0 (default: 0.25)",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
print(f"Board: {board_model()}")
|
|
cfg0, cfg1 = default_dual_strip_configs(
|
|
args.count[0], args.count[1], brightness=args.brightness
|
|
)
|
|
print(f"Strip 0: {cfg0.backend} → {_describe(cfg0)} (red chase)")
|
|
print(f"Strip 1: {cfg1.backend} → {_describe(cfg1)} (rainbow)")
|
|
|
|
step = 0
|
|
try:
|
|
with LedStrips(args.count[0], args.count[1], brightness=args.brightness) as strips:
|
|
while True:
|
|
# strip 0: red dot chasing along the strip
|
|
chase(strips[0], (255, 0, 0), step)
|
|
|
|
# strip 1: rainbow scroll — completely independent
|
|
rainbow(strips[1], step * 4)
|
|
|
|
strips.show()
|
|
step += 1
|
|
time.sleep(0.05)
|
|
except KeyboardInterrupt:
|
|
print("\nStopped.")
|
|
return 0
|
|
except FileNotFoundError as exc:
|
|
print(f"Error: {exc}", file=sys.stderr)
|
|
if board_family() == "pi5":
|
|
print("\n" + pi5_setup_hint(args.count[0], args.count[1]), file=sys.stderr)
|
|
return 1
|
|
except OSError as exc:
|
|
print(f"Error: {exc}", file=sys.stderr)
|
|
if board_family() == "pi5" and "No such file" in str(exc):
|
|
print("\n" + pi5_setup_hint(args.count[0], args.count[1]), file=sys.stderr)
|
|
return 1
|
|
except Exception as exc:
|
|
print(f"Error: {exc}", file=sys.stderr)
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|