Spec source: docs/SAUL-TEE-SYSTEM-REFERENCE.md (hal, 2026-04-04) stm32_protocol.py — rewritten for inter-board UART protocol (ESP32 BALANCE ↔ IO): - Frame: [0xAA][LEN][TYPE][PAYLOAD][CRC8] @ 460800 baud (was STX/ETX/CRC16) - CRC-8 poly 0x07 over LEN+TYPE+PAYLOAD - New message types: RC_CHANNELS(0x01), SENSORS(0x02), LED_CMD(0x10), OUTPUT_CMD(0x11), MOTOR_CMD(0x12), HEARTBEAT(0x20) mamba_protocol.py — updated CAN IDs and frame formats: - Orin→BALANCE: DRIVE(0x300) f32×2 LE, MODE(0x301), ESTOP(0x302), LED(0x303) - BALANCE→Orin: FC_STATUS(0x400) pitch/vbat/state, FC_VESC(0x401) rpm/current - VESC node IDs: Left=56, Right=68 (authoritative per §8) - VESC extended frames: STATUS1(cmd=9), STATUS4(cmd=16), STATUS5(cmd=27) - Replaced old MAMBA_CMD_*/MAMBA_TELEM_* constants can_bridge_node.py — updated to use new IDs: - ORIN_CMD_DRIVE/MODE/ESTOP replace MAMBA_CMD_VELOCITY/MODE/ESTOP - FC_STATUS handler: publishes pitch→/can/imu, vbat_mv→/can/battery - FC_VESC handler: publishes rpm/cur→/can/vesc/left|right/state - VESC STATUS1 extended frames decoded per node ID (56/68) - Removed PID CAN command (not in new spec) CLAUDE.md — updated with ESP32-S3 BALANCE/IO hardware summary + key protocols Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.1 KiB
3.1 KiB
SaltyLab Firmware — Agent Playbook
Project
SAUL-TEE — 4-wheel wagon robot (870×510×550 mm, 23 kg). Two ESP32-S3 boards + Jetson Orin for AI/ROS2.
Full hardware spec:
docs/SAUL-TEE-SYSTEM-REFERENCE.md
Embedded boards
| Board | Hardware | Role |
|---|---|---|
| ESP32-S3 BALANCE | Waveshare Touch LCD 1.28 (CH343 USB) | QMI8658 IMU, PID balance loop, CAN→VESCs (SN65HVD230, 500 kbps) |
| ESP32-S3 IO | Bare DevKit (JTAG USB) | BTS7960 motors, TBS Crossfire (UART0) + ELRS failover (UART2), NFC/baro/ToF (I2C), WS2812 LEDs, horn/headlight/fan/buzzer |
Key protocols
- Orin ↔ BALANCE: CAN 500 kbps via CANable2 (slcan0). Cmds 0x300–0x303, telemetry 0x400–0x401
- BALANCE ↔ IO: UART 460800 baud, frame
[0xAA][LEN][TYPE][PAYLOAD][CRC8] - VESC IDs: Left = 56, Right = 68
Team
| Agent | Role | Focus |
|---|---|---|
| sl-firmware | Embedded Firmware Lead | ESP32-S3 firmware (PlatformIO), QMI8658 IMU, PID, VESC CAN, inter-board UART |
| sl-controls | Control Systems Engineer | PID tuning, IMU sensor fusion, real-time control loops, safety systems |
| sl-perception | Perception / SLAM Engineer | Jetson Orin, RealSense D435i, RPLIDAR, ROS2, Nav2 |
Status
Architecture migrated from Mamba F722S/BlackPill → ESP32-S3 BALANCE + IO (PR #712, 2026-04-04).
Repo Structure
projects/saltybot/SALTYLAB.md— Design docUSB_CDC_BUG.md— USB peripheral conflict detailsTEAM.md— Team roles specification
Branch Strategy (issue #28)
Variant branches
| Branch | Purpose |
|---|---|
saltylab |
Stable — SaltyLab 2-wheel balance bot (promoted from saltylab-dev) |
saltylab-dev |
Integration — SaltyLab balance bot; agents target this branch |
saltyrover |
Stable — 4-wheel rover variant |
saltyrover-dev |
Integration — rover variant |
saltytank |
Stable — tracked tank variant |
saltytank-dev |
Integration — tank variant |
main |
Shared code only (IMU drivers, USB CDC, balance core, safety) |
Rules
- Agents branch FROM
<variant>-devand PR back TO<variant>-dev - Shared/infrastructure code (IMU drivers, USB CDC, balance core, safety) goes in
main - Variant-specific code (motor topology, kinematics, config) goes in variant branches
- Stable branches get promoted from
-devafter review and hardware testing - Current SaltyLab team works against
saltylab-dev
Git Workflow
- Branch naming:
<agent>/<slug>(e.g.,sl-firmware/usb-cdc-fix) - For shared code targeting
main:<agent>/bd-<id>-<slug> - Before every push:
git fetch origin && git rebase origin/<base-branch> - Gitea:
gitea.vayrette.com/seb/saltylab-firmware
Communication
- Report progress to max via MQTT:
AGENT_NAME=<agent> ~/agent-mqtt/agent-send max "<message>" - Check inbox:
~/agent-mqtt/agent-read 2>/dev/null | tail -15 - Prioritize messages from max (PM)
Beads (Task System)
cd /Users/seb/AI/saltylab-firmware
br list # List open beads
br update <id> --claim # Claim a bead
br close <id> --reason "Done. PR #N"
br comment <id> "message"