Buttons
hub.buttons (hub._buttons_module) covers the 5-way
directional pad (center = power button).
Level readers
Return the current held state:
if hub.buttons.center():
...
if hub.buttons.left():
...
Names: center, up, down, left, right.
Callbacks
Callbacks fire on rising edge (release → press). They are
dispatched automatically — the C firmware detects rising edges in the
hardware loop and schedules a dispatcher on the MicroPython task via
mp_sched_schedule. No poll call is needed in user code.
Each fired callback runs in its own new thread (_thread), so a
slow callback never blocks the main program or other callbacks.
Pressing a button again while its previous callback is still running
starts a second, concurrent copy. Keep in mind:
Callbacks share globals with the main program; guard shared state with
_thread.allocate_lock()if needed.Each LVGL call holds the GIL, so single widget calls from a callback are safe; a multi-step update may interleave with
lv.timer_handler()in the main loop and render half-updated for one frame.Each thread uses internal RAM for its stack; very rapid presses with long-running callbacks can run out (“can’t create thread” is printed and that press is skipped).
Exceptions in a callback are printed;
SystemExitends the callback silently.
Stopping callbacks
hub.stop_callbacks() delivers SystemExit to every callback
thread that is still running and returns how many were signalled. It
does not wait: each thread exits at its next bytecode or inside its
current time.sleep_ms. Called from inside a callback, it stops all
the other callback threads. Registrations are kept.
@hub.buttons.on("up")
def ticker():
n = 0
while True:
print("tick", n)
n += 1
time.sleep_ms(500)
@hub.buttons.on("down")
def stop_all():
hub.stop_callbacks()
When the program ends the runner calls the same stop, waits up to 100 ms for the threads to exit, then deletes any that are left.
Decorator form:
@hub.buttons.on("left")
def left_pressed():
print("<--")
@hub.buttons.on("center")
def center_pressed():
print("center")
Manual form:
hub.buttons.on("up", my_cb) # register
hub.buttons.on("up", None) # unregister
hub.buttons.off("up") # alt: unregister
Exiting a program
Holding the centre button for >= 2 s causes the C firmware to
schedule a KeyboardInterrupt on the MicroPython task. The runner
catches this and shows the “Done” screen. User code cannot suppress
it — treat it as a physical stop signal.
To exit from Python: hub.exit() (raises SystemExit, does not
return).
Power-off
Holding the centre button for >= 5 s triggers a hardware power-off in the C firmware loop. User code cannot suppress this.
To power off from Python: hub.powerOff() (does not return).