- docs/: rewrite AGENTS.md, wiring-diagram.md (SAUL-TEE arch); update SALTYLAB.md, FACE_LCD_ANIMATION.md, board-viz.html, SALTYLAB-DETAILED refs - cad/: dimensions.scad FC params → ESP32-S3 BALANCE params - chassis/: ASSEMBLY.md, BOM.md, ip54_BOM.md, *.scad — FC_MOUNT_SPACING/ FC_PITCH → TBD ESP32-S3; Drone FC → MCU mount throughout - CLAUDE.md, TEAM.md: project desc → SAUL-TEE; hardware table → ESP32-S3/VESC - USB_CDC_BUG.md: marked ARCHIVED (legacy STM32 era) - AUTONOMOUS_ARMING.md: USB CDC → inter-board UART (ESP32-S3 BALANCE) - projects/saltybot/SLAM-SETUP-PLAN.md: FC/STM32F722 → BALANCE/CAN - jetson/docs/pinout.md, power-budget.md, README.md: STM32 bridge → CAN bridge - jetson/config/RECOVERY_BEHAVIORS.md: FC+Hoverboard → BALANCE+VESC - jetson/ros2_ws: stm32_protocol.py → esp32_protocol.py, stm32_cmd_node.py → esp32_cmd_node.py, mamba_protocol.py → balance_protocol.py; can_bridge_node imports updated - scripts/flash_firmware.py: DFU/STM32 → pio run -t upload - src/ include/: ARCHIVED headers added (legacy code preserved) - test/: ARCHIVED notices; STM32F722 comments marked LEGACY - ui/diagnostics_panel.html: Board/STM32 → ESP32-S3 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
185 lines
7.7 KiB
Markdown
185 lines
7.7 KiB
Markdown
# AGENTS.md — SAUL-TEE Agent Onboarding
|
||
|
||
You're working on **SAUL-TEE**, a 4-wheel wagon robot. Read this entire file before touching anything.
|
||
|
||
**Full system reference:** `docs/SAUL-TEE-SYSTEM-REFERENCE.md`
|
||
|
||
## Project Overview
|
||
|
||
A 4-wheel wagon robot (870×510×550 mm, 23 kg) with three compute layers:
|
||
|
||
1. **ESP32-S3 BALANCE** (Waveshare Touch LCD 1.28) — QMI8658 IMU, PID drive / stability loop, CAN bus master for VESCs. Safety-critical layer. Firmware in `esp32/balance/`.
|
||
2. **ESP32-S3 IO** (bare board) — RC input (TBS Crossfire + ELRS failover), BTS7960 motor drivers, I2C sensors (NFC/baro/ToF), WS2812 LEDs, accessories. Firmware in `esp32/io/`.
|
||
3. **Jetson Orin Nano Super** — AI brain: ROS2, SLAM, Nav2, perception. Sends high-level velocity commands over CAN (0x300–0x303). Receives telemetry on CAN (0x400–0x401).
|
||
|
||
```
|
||
Orin (CAN 0x300-0x303) ←→ TBS Crossfire / ELRS (CRSF @ 420000)
|
||
│ │
|
||
▼ CAN 500kbps │ inter-board UART 460800
|
||
ESP32-S3 BALANCE ───────────────── ESP32-S3 IO
|
||
QMI8658 IMU BTS7960 × 4 motor drivers
|
||
PID loop NFC / baro / ToF (I2C)
|
||
SN65HVD230 CAN WS2812 LEDs
|
||
│ Horn / headlight / fan / buzzer
|
||
▼ CAN 500kbps
|
||
VESC left (ID 68) VESC right (ID 56)
|
||
│ │
|
||
Hub motors FL/RL Hub motors FR/RR
|
||
```
|
||
|
||
## ⚠️ SAFETY — READ THIS OR PEOPLE GET HURT
|
||
|
||
This is not a toy. 4× hub motors + 36V × high-current VESCs can crush fingers, break toes, and throw the 23 kg frame. Every firmware change must preserve these invariants:
|
||
|
||
1. **Motors NEVER spin on power-on.** Requires deliberate arming: deliberate ARM command.
|
||
2. **RC kill switch** — dedicated ELRS/Crossfire channel, checked every loop iteration. Always overrides.
|
||
3. **CAN watchdog** — if no Orin heartbeat for 500 ms, drop to RC-only mode.
|
||
4. **ESTOP CAN frame** — 0x303 with magic byte 0xE5 cuts all motors instantly.
|
||
5. **Inter-board heartbeat** — if IO board misses BALANCE heartbeat for 200 ms, IO disables all BTS7960 enables.
|
||
6. **Speed hard cap** — firmware limit, start at 10%. Increase only after proven stable.
|
||
7. **Never test without RC transmitter in hand.**
|
||
|
||
**If you break any of these, you are removed from the project.**
|
||
|
||
## Repository Layout
|
||
|
||
```
|
||
esp32/
|
||
├── balance/ — ESP32-S3 BALANCE firmware (PlatformIO)
|
||
│ ├── src/
|
||
│ │ ├── main.cpp
|
||
│ │ ├── config.h ← GPIO assignments — update here first
|
||
│ │ ├── imu_qmi8658.cpp/.h
|
||
│ │ ├── can_vesc.cpp/.h
|
||
│ │ └── protocol.cpp/.h
|
||
│ └── platformio.ini
|
||
├── io/ — ESP32-S3 IO firmware (PlatformIO)
|
||
│ ├── src/
|
||
│ │ ├── main.cpp
|
||
│ │ ├── config.h ← GPIO assignments — update here first
|
||
│ │ ├── rc_crsf.cpp/.h
|
||
│ │ ├── motor_bts7960.cpp/.h
|
||
│ │ └── protocol.cpp/.h
|
||
│ └── platformio.ini
|
||
└── shared/
|
||
└── protocol.h ← inter-board frame types — authoritative
|
||
|
||
src/ — LEGACY STM32 code (ARCHIVED — do not touch)
|
||
include/ — LEGACY STM32 headers (ARCHIVED — do not touch)
|
||
|
||
chassis/ — OpenSCAD mechanical parts
|
||
├── ASSEMBLY.md — assembly instructions
|
||
├── BOM.md — bill of materials
|
||
└── *.scad — parametric parts
|
||
|
||
docs/
|
||
├── SAUL-TEE-SYSTEM-REFERENCE.md ← MASTER REFERENCE — read this
|
||
├── AGENTS.md — this file
|
||
├── wiring-diagram.md — wiring reference (see SAUL-TEE-SYSTEM-REFERENCE.md)
|
||
└── SALTYLAB.md — legacy design doc (historical)
|
||
```
|
||
|
||
## Hardware Quick Reference
|
||
|
||
### ESP32-S3 BALANCE (Waveshare Touch LCD 1.28)
|
||
|
||
| Spec | Value |
|
||
|------|-------|
|
||
| MCU | ESP32-S3, dual-core 240 MHz, 8MB flash, 8MB PSRAM |
|
||
| USB | CH343G USB-UART bridge (UART0 / GPIO43 TX, GPIO44 RX) |
|
||
| Display | 1.28" round GC9A01 240×240 (SPI, onboard) |
|
||
| IMU | QMI8658 6-axis (I2C-0 SDA=GPIO6, SCL=GPIO7, INT=GPIO3) |
|
||
| CAN | SN65HVD230 external transceiver (GPIO TBD — see `esp32/balance/src/config.h`) |
|
||
| Inter-board UART | UART1 (GPIO TBD) ↔ ESP32-IO @ 460800 baud |
|
||
|
||
### ESP32-S3 IO (bare board)
|
||
|
||
| Peripheral | Interface | GPIO |
|
||
|------------|-----------|------|
|
||
| TBS Crossfire RX | UART0 CRSF @ 420000 | GPIO43 TX / GPIO44 RX |
|
||
| ELRS failover RX | UART2 CRSF @ 420000 | TBD |
|
||
| BTS7960 FL/FR/RL/RR | PWM + GPIO | TBD — see config.h |
|
||
| I2C bus (NFC/baro/ToF) | I2C | TBD |
|
||
| WS2812B LEDs | RMT GPIO | TBD |
|
||
| Horn / headlight / fan / buzzer | GPIO/PWM | TBD |
|
||
| Inter-board UART | UART1 @ 460800 | TBD |
|
||
|
||
> All TBD GPIO assignments are confirmed in `esp32/io/src/config.h`.
|
||
|
||
### CAN Bus
|
||
|
||
| Node | CAN ID | Notes |
|
||
|------|--------|-------|
|
||
| VESC left motor | 68 (0x44) | FSESC 6.7 Pro Mini Dual |
|
||
| VESC right motor | 56 (0x38) | FSESC 6.7 Pro Mini Dual |
|
||
| Orin → robot cmds | 0x300–0x303 | drive / arm / PID / ESTOP |
|
||
| BALANCE → Orin telemetry | 0x400–0x401 | attitude + battery + faults |
|
||
|
||
### Physical Dimensions
|
||
|
||
| Parameter | Value |
|
||
|-----------|-------|
|
||
| Robot (SAUL-TEE) | 870 × 510 × 550 mm, 23 kg |
|
||
| Hub motor axle base OD | Ø16.11 mm (caliper-verified) |
|
||
| Hub motor axle D-cut OD | Ø15.95 mm, 13.00 mm flat chord |
|
||
| Bearing seat collar | Ø37.8 mm |
|
||
| Tire | 10 × 2.125" pneumatic (Ø254 mm) |
|
||
| ESP32-S3 BALANCE PCB | ~40×40 mm (TBD — caliper before machining) |
|
||
| Orin carrier hole pattern | 58 × 49 mm M3 |
|
||
|
||
## Inter-Board Protocol
|
||
|
||
**UART @ 460800 baud, 8N1.** Frame: `[0xAA][LEN][TYPE][PAYLOAD…][CRC8]`
|
||
|
||
CRC polynomial: CRC-8/MAXIM (poly 0x31, init 0x00, RefIn/RefOut true).
|
||
|
||
Authoritative message type definitions: `esp32/shared/protocol.h`
|
||
|
||
## Build & Flash
|
||
|
||
```bash
|
||
# ESP32-S3 BALANCE
|
||
cd esp32/balance
|
||
pio run -t upload # Upload via USB (CH343 serial)
|
||
|
||
# ESP32-S3 IO
|
||
cd esp32/io
|
||
pio run -t upload # Upload via USB (JTAG/CDC)
|
||
```
|
||
|
||
## Critical Lessons Learned
|
||
|
||
1. **`-(int)0 == 0`** — checking `if (-result)` doesn't detect a zero error result. Use explicit error codes.
|
||
2. **NEVER auto-run untested firmware on boot** — we bricked hardware doing this. Test manually first.
|
||
3. **One variable at a time** — never change PID gains and speed limit in the same test session.
|
||
4. **QMI8658 data ready** — poll INT pin (GPIO3) or use interrupt; don't poll status register in a tight loop.
|
||
5. **CAN bus termination** — 120 Ω at each physical end of the bus. Missing termination = unreliable comms.
|
||
|
||
## LED States (WS2812B on ESP32-IO)
|
||
|
||
| State | Pattern | Color |
|
||
|-------|---------|-------|
|
||
| Disarmed | Slow breathe | White |
|
||
| Arming | Fast blink | Yellow |
|
||
| Armed | Solid | Green |
|
||
| Turning | Sweep direction | Orange |
|
||
| Braking | Flash rear | Red |
|
||
| Fault / ESTOP | Triple flash | Red |
|
||
| RC lost | Alternating flash | Red/Blue |
|
||
|
||
## Printing (Bambu Lab)
|
||
|
||
- **X1C** (192.168.87.190) — structural PETG/ASA parts
|
||
- **A1** (192.168.86.161) — TPU bumpers, prototypes
|
||
- STL export from OpenSCAD, slice in Bambu Studio
|
||
|
||
## Rules for Agents
|
||
|
||
1. **Read `docs/SAUL-TEE-SYSTEM-REFERENCE.md`** fully before any design or firmware decision
|
||
2. **Never remove safety checks** — add more if needed
|
||
3. **All mechanical measurements go in `cad/dimensions.scad`** — single source of truth
|
||
4. **Test firmware on bench first** — VESCs/BTS7960 disconnected, verify outputs on serial
|
||
5. **GPIO assignments live in `config.h`** — change there, not scattered in source
|
||
6. **Document hardware quirks here** — if you find a gotcha, add a "Critical Lesson Learned"
|
||
7. **Ask before wiring changes** — wrong connections can fry ESP32-S3 boards
|