Files
apress/deploy/uno-q/skills/arduino-uno-q/references/07-workshop-playbook.md
T
Omar SobhandClaude Opus 4.8 d2135a1938 feat(uno-q): ship the arduino-uno-q expert skill on every node by default
Vendors the comprehensive UNO Q skill (SKILL.md + 7 references/*.md) and installs
it into EVERY agent's workspace on each board, so agents know this board's
specifics (dual-brain arch, Bridge/RPC, pin tables, LED matrix + the
ArduinoGraphics-not-installed gotcha) instead of guessing generic Arduino.

Why per-agent workspace: ZeroClaw's read_skill returns only SKILL.md; the agent
reads references/*.md via the workspace-sandboxed file_read tool, so references
are only reachable under ~/.zeroclaw/agents/<alias>/workspace/skills/. A
shared/skills bundle surfaces the skill but its references get sandbox-blocked.

- push-skill.sh installs a SKILL.md+references skill into every agent workspace
  (discovers aliases from the board); provision-fleet runs it per board.
- config.template risk profile now allows + auto-approves read_skill + file_read
  so agents load skills without a human approver (webhook path is non-interactive).
- Flattened the folded 'description: >-' to single-line (ZeroClaw's frontmatter
  parser is a flat scanner, not full YAML).

Verified on board 65301572 with cloud/Sonnet-5: discovered arduino-uno-q →
read_skill(SKILL.md) → file_read references/04-bridge-rpc.md → correct
board-specific answer citing the file.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-16 09:14:00 -07:00

4.6 KiB

UNO Q — Workshop Playbook

Practical guidance for running a hands-on session with the board. Assumes the reader already understands the two-processor model (see SKILL.md).

Pre-flight checklist (per station)

  • Board + a known-good USB-C cable rated for 5 V / 3 A (or a multiport dongle with external PD — not Apple's, it's incompatible).
  • For SBC stations: HDMI monitor, USB keyboard/mouse via dongle, power to the dongle.
  • Decide the mode up front: SBC (self-contained, needs 4 GB variant recommended) vs Network Mode (students drive it from their laptops).
  • Each board: set a board name (becomes <name>.local), a password, and Wi-Fi during first-run. SSH turns on automatically after this.
  • If any facilitator laptop runs Linux, install the udev rules first (see setup reference) — otherwise App Lab connects silently to nothing.
  • Network allows mDNS / UDP 5353 (needed for Network Mode discovery). On locked-down campus Wi-Fi this is the usual blocker.
  • For enterprise/eduroam Wi-Fi, pre-stage the nmcli 802.1X command (see wireless reference).

Common failure modes → fixes

Symptom Likely cause Fix
App Lab shows no board (Linux PC, USB) Missing udev rules Install rules, reconnect board, restart App Lab
Board absent in Network Mode mDNS blocked Open UDP 5353; approve mdns-discovery.exe on Windows; confirm same subnet
Flash/upload "permission denied" (Linux) udev not applied Re-run rules, udevadm control --reload-rules && udevadm trigger, replug
Python can't reach the sketch router down / wrong function name systemctl status arduino-router; check the provide() name matches the call() string; verbose logs
Handler crashes / hangs Arduino API called from provide() (RPC thread) Use provide_safe(); never Serial.print/Bridge.call inside a handler
Nothing on a pin wrong logic level or wrong processor MCU I/O is 3.3 V; onboard RGB LEDs are active-low; confirm the sketch (not Python) owns the pin
Serial1 acting weird confusing header UART with router link Serial1 on D0/D1 is fine for external UART; never open the internal reserved transport / /dev/ttyHS1
Can't SSH no IP / SSH not set up ip addr show (wlan0) on the board; SSH is enabled once first-run setup completes

The canonical teaching example: "Python button decides, Arduino acts"

This one App ties the entire board together and is the best first exercise because it forces students to touch both processors and the Bridge.

Concept: the sketch owns an LED (a physical pin); Python owns the logic and calls across the Bridge to actuate it. Swap the LED for a relay/motor driver and you have real device control; swap the Python timer for a camera/AI Brick and you have an intelligent actuator.

MCU sketch (sketch.ino):

#include "Arduino_RouterBridge.h"
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Bridge.begin();
  Bridge.provide_safe("set_led_state", set_led_state);
}
void loop() {}
void set_led_state(bool state) {
  digitalWrite(LED_BUILTIN, state ? LOW : HIGH);  // built-in LED active-low
}

Linux Python (main.py):

from arduino.app_utils import *
import time
state = False
def loop():
    global state
    time.sleep(1)
    state = not state
    Bridge.call("set_led_state", state)
App.run(user_loop=loop)

Teaching beats:

  1. Run it → LED blinks, but emphasize the decision happened in Python on Linux, the action happened on the MCU.
  2. Break it on purpose: rename "set_led_state" on one side → show the router log error → fix. Cements the RPC contract idea.
  3. Extend: have Python read something real (time of day, a web request, a camera Brick) and gate the LED on it.
  4. Reverse it: MCU reads a real sensor and Bridge.call()s a Python function that logs/uploads it.

Progression for a full session

  1. Blink (App Lab example) — proves the MCU toolchain.
  2. Read a sensor in a sketch, print with Serial → App Lab console — proves I/O + debugging.
  3. Bridge example above — proves Linux↔MCU.
  4. Add a Brick (vision/audio) on the Python side — shows the payoff of the Linux half.
  5. Deploy: set the App to Run at startup and unplug the keyboard → it's now an appliance. Manage it over SSH + arduino-app-cli.

Deploying student projects headlessly

  • Copy the App to the board: scp -r * arduino@<IP>:~/ArduinoApps/<name>.
  • Start/stop/log via arduino-app-cli app start|stop|logs ~/ArduinoApps/<name>.
  • Autostart the finished one: arduino-app-cli properties set default user:<name>.