# Flash Force LED — hub listener (Pybricks; City / Technic / Prime hub). Emits VLL to a Micro Scout locally. # # Byte protocol (over BLE stdin from flash-force-led.html): # 0-34 = VLL command codes (sent once) # 200 = use HUB LED 201 = use 88005 Light # 220 = HOLD forward 221 = HOLD back 222 = RELEASE # While "holding", the hub repeats the motor frame until RELEASE or a ~1.5 s keep-alive # timeout (safety, in case the connection drops mid-hold). # # LED: green double-blink = started; soft green = ready; red flicker = sending (hub-LED mode). # Flash once via code.pybricks.com, then press the hub button (short) to start. # Imports the listener needs. Re-importing is harmless, so this is safe whether # you KEPT Pybricks' default template above or deleted it. from pybricks.pupdevices import Light from pybricks.parameters import Color, Port from pybricks.tools import wait, StopWatch from usys import stdin from uselect import poll # Works BOTH ways: paste over the default template, OR keep the template and # paste this below it. Reuse the template's `hub` if it already exists; otherwise # make one ourselves (only this firmware's hub class is importable). try: hub except NameError: try: from pybricks.hubs import CityHub as _Hub except ImportError: try: from pybricks.hubs import TechnicHub as _Hub except ImportError: from pybricks.hubs import PrimeHub as _Hub hub = _Hub() SCALE = 0.8 PORT = Port.A IDLE_GLOW = Color.GREEN * 0.3 HOLD_TIMEOUT = 1500 # ms without keep-alive -> stop repeating source = "hub" lamp = None repeat_code = None watch = StopWatch() def idle(): hub.light.on(IDLE_GLOW) def emit_on(): if source == "light" and lamp is not None: lamp.on(100) else: hub.light.on(Color.RED) def emit_off(): if source == "light" and lamp is not None: lamp.off() else: hub.light.off() def checksum(n): return 7 - ((n + (n >> 2) + (n >> 4)) & 7) def vll_send(code): def on(ms): emit_on() wait(round(ms * SCALE)) def off(ms): emit_off() wait(round(ms * SCALE)) bits = [] cs = checksum(code) for i in range(2, -1, -1): bits.append((cs >> i) & 1) for i in range(6, -1, -1): bits.append((code >> i) & 1) on(400) off(20) for b in bits: if b: on(20) off(40) else: on(40) off(20) on(20) off(60) on(120) emit_off() # startup: green double blink = running hub.light.off() for _ in range(2): hub.light.on(Color.GREEN) wait(120) hub.light.off() wait(120) kb = poll() kb.register(stdin) print("Flash Force LED ready") idle() while True: # drain all pending command bytes while kb.poll(0): data = stdin.buffer.read(1) if not data: break b = data[0] if b == 200: source = "hub" print("source: hub LED") idle() elif b == 201: try: lamp = Light(PORT) source = "light" print("source: 88005") except: source = "hub" print("88005 not found, using hub") idle() elif b == 220: repeat_code = 0 watch.reset() elif b == 221: repeat_code = 1 watch.reset() elif b == 222: repeat_code = None idle() else: emit_off() wait(60) vll_send(b) wait(150) idle() # repeat the held motor command if repeat_code is not None: if watch.time() < HOLD_TIMEOUT: emit_off() wait(20) vll_send(repeat_code) else: repeat_code = None idle() else: wait(10)