04Firmware
Five subsystems, each its own folder under firmware/ — flash or
swap a board without touching the rest. No vendor tools required: the REV
SPARK CAN stack is reverse-engineered natively, and every setup task a vendor
GUI would do ships as a script. The per-folder master table is
firmware/CLAUDE.md.
Overview
| Subsystem | Path | Board | Flash |
|---|---|---|---|
| Swerve base | firmware/swerve_drive/ | Teensy 4.1 | PlatformIO |
| Arms link | firmware/openarm/ | Teensy 4.1 | PlatformIO |
| Lift | firmware/lift/ | RP2040 Pico | MicroPython (mpremote) |
| ORCA hands | firmware/orca_hand/ | none — host-driven | no flash; servos close their own loops |
| Neck | host-driven | none | Dynamixel pair over the U2D2, yaw on CAN |
Base Teensy — swerve drive
cd firmware/swerve_drive
pio run -e teensy41 -t upload
- Speaks UDP :8888 to the host over native Ethernet, and drives the six SPARK controllers on REV's CAN protocol at 1 Mbit.
- The SPARK protocol was reverse-engineered end to end — the full writeup
(29-bit extended IDs, frame layout) is
firmware/swerve_drive/rev_can_protocol.md. You never need REV's Windows-only Hardware Client. - Static address
192.168.124.10— see the network plan.
Arms Teensy — CAN gateway
cd firmware/openarm
pio run -e mabel_main -t upload # main arms firmware
pio run -e mabel_armlink -t upload # ArmLink UDP↔MIT-CAN Ethernet gateway
- Runs both arm CAN buses (DaMiao MIT mode, 1 Mbit, 500 Hz) behind one
Ethernet link. The ArmLink wire contract is
firmware/openarm/include/armlink_protocol.h+hardware_bridge/docs/ARMLINK.md. - Setup tools ship as PlatformIO envs — no DaMiao assistant needed:
tool_can_scanner,tool_change_motor_id,tool_set_zero_pos,tool_clear_faults,tool_read_limits,tool_switch_mode,tool_teleop_cli,tool_sine_sweep. Usetool_change_motor_idfor the one-motor-at-a-time ID assignment during arm assembly.
The reference robot in these docs ran a pre-release arms build
(
openarm-dual, at 192.168.124.11) that predates the
in-repo ArmLink gateway (192.168.125.10, host lane set by
hardware_bridge/install/setup_arms_lane.sh). For a new build,
flash the in-repo envs above and use the 192.168.125.x lane; the
software resolves either through its port-agnostic Teensy discovery.
Lift Pico — MicroPython
pip install mpremote
firmware/lift/tools/deploy.sh # copies the module set + main.py to the Pico
- Cascaded position + velocity loop on the Pico (BTS7960 + quadrature encoder), simple line protocol over USB serial @115200.
- Host-side API + console:
firmware/lift/host/; the only firmware folder with its own README — read it.
deploy.sh resolves the Pico by USB identity
(usb-MicroPython*). Never use mpremote connect auto:
the first serial port on the robot's hub is the base Teensy.
Hands — servo setup, no flash
python firmware/orca_hand/feetech/setup/precheck.py # pings servo IDs 1..17 on a chain
- All logic is host-side Python; the Feetech servos close their own position loops. The wire is standard STS/SCS packets with one SYNC_WRITE per control tick for all 17 motors.
- ID assignment and per-servo setup replace the Feetech debugger — tools in
firmware/orca_hand/feetech/. Assign IDs before stringing tendons (02 · Hands). - Deep dives:
firmware/orca_hand/docs/orca_firmware.pdfandorcahand_api.pdf(built from the.texalongside).
CAN bring-up helpers
firmware/can_up.sh # SocketCAN up — handles gs_usb and slcan adapters
firmware/can_scan.sh # who's on the bus
firmware/can_down.sh
macOS has no SocketCAN; the tools fall back to a gs_usb-over-libusb backend, so bench setup works from a Mac too.
Firmware completion check
- Base Teensy answers ping at its address and echoes the UDP protocol
tool_can_scannersees IDs 1–7 on each arm bus- Lift Pico answers on USB serial; encoder counts move when the screw is turned by hand
precheck.pyreports 17/17 on each hand chain- Neck: both Dynamixels respond on the U2D2; yaw motor answers on CAN