Byonoy L96 — LED bar#

The L96 has a 20-pixel addressable RGB front bar on the chassis. PyLabRobot exposes two methods to drive it:

Method

Use for

set_led_color(color, effect)

Single color across all 20 pixels, optionally animated by the firmware (BREATHING, CYLON, RAINBOW, …)

set_led_colors(colors)

Per-pixel control — supply a list of up to 20 RGB triplets. Fast enough for real-time animation.

Connect#

We’ll talk to the device’s driver directly, so the bar can be driven without setting up a plate read.

from pylabrobot.byonoy import byonoy_l96

base, reader = byonoy_l96(name="l96")
await reader.setup()
drv = reader.driver

Solid colors#

The simplest call: one color, SOLID effect (the default). The firmware snaps the bar to that color.

import asyncio

await drv.set_led_color((255, 0, 0))     # red
await asyncio.sleep(1)
await drv.set_led_color((0, 255, 0))     # green
await asyncio.sleep(1)
await drv.set_led_color((0, 0, 255))     # blue
await asyncio.sleep(1)
await drv.set_led_color((0, 0, 0))       # off

Built-in effects#

The firmware can animate the base color for you. Pass duration_ms to set how long the effect runs before reverting to firmware control. Use force=True to override an unexpired previous duration.

Effect

Behavior

SOLID

Snap to color (default)

BREATHING

Pulse brightness

BLINKING

Flash on/off

CYLON

Bouncing dot across the bar

RAINBOW

Cycle through hues (ignores supplied color)

PROGRESS

Fill progressively, driven by effect_state (0–255)

await drv.set_led_color((0, 255, 0), "breathing", duration_ms=6000)
await asyncio.sleep(6)

await drv.set_led_color((255, 0, 255), "cylon", duration_ms=4000, force=True)
await asyncio.sleep(4)

await drv.set_led_color((0, 0, 0))   # back to off

Per-pixel control#

set_led_colors(colors) takes a list of up to 20 (r, g, b) triplets, one per pixel (left to right). Shorter lists are zero-padded; longer ones are truncated.

# Left half red, right half blue
await drv.set_led_colors([(255, 0, 0)] * 10 + [(0, 0, 255)] * 10)
await asyncio.sleep(2)

# Rainbow gradient across the bar
import colorsys
def hue(i, n=20):
  r, g, b = colorsys.hsv_to_rgb(i / n, 1, 1)
  return (int(r * 255), int(g * 255), int(b * 255))

await drv.set_led_colors([hue(i) for i in range(20)])
await asyncio.sleep(3)

# Every other pixel
await drv.set_led_colors([(0, 255, 0) if i % 2 == 0 else (0, 0, 0) for i in range(20)])
await asyncio.sleep(2)

await drv.set_led_colors([(0, 0, 0)] * 20)   # off

Animation recipe: KITT scanner#

A back-and-forth scanner with a fading trail — the kind of thing you’d want as a “robot is busy” indicator. Frame rate is set by how fast you call set_led_colors; ~30 fps is comfortable.

import asyncio

N = 20
trail = 4         # length of the fading trail
decay = 0.45      # brightness ratio per trail step
step_s = 0.06     # ~16 fps; lower for faster

def frame(head):
  px = [(0, 0, 0)] * N
  for k in range(trail + 1):
    v = int(255 * (decay ** k))
    if 0 <= head - k < N:
      px[head - k] = (v, 0, 0)   # red trail
  return px

positions = list(range(N)) + list(range(N - 2, 0, -1))   # 0..19..1
for _ in range(3):                                       # 3 ping-pong cycles
  for head in positions:
    await drv.set_led_colors(frame(head))
    await asyncio.sleep(step_s)

await drv.set_led_colors([(0, 0, 0)] * 20)

Animation recipe: walking dot#

Simplest possible animation — one bright pixel marches across the bar. Useful as a progress indicator with a known step count.

for pos in range(20):
  px = [(0, 0, 0)] * 20
  px[pos] = (0, 255, 0)
  await drv.set_led_colors(px)
  await asyncio.sleep(0.15)

await drv.set_led_colors([(0, 0, 0)] * 20)

Teardown#

await drv.set_led_color((0, 0, 0))   # ensure bar is off
await reader.stop()

Reference#

  • set_led_color(color, effect, *, duration_ms=0, force=False, low_power=False) — single uniform color, optional firmware-driven effect.

  • set_led_colors(colors) — list of up to 20 (r, g, b) triplets, one per pixel. Pads with black; truncates if longer.

  • Both methods live on reader.driver. Source: pylabrobot/byonoy/driver.py.