docs: Add SAUL-TEE system reference — ESP32-S3 architecture (Issue #695+)

This commit is contained in:
sl-jetson 2026-04-04 08:19:14 -04:00 committed by sl-webui
parent 7db6158ada
commit ea71cefff5

View File

@ -0,0 +1,216 @@
# SAUL-TEE System Reference — SaltyLab ESP32 Architecture
*Source of truth for all hardware, pin, protocol, and CAN assignments.*
*Generated 2026-04-04 from hal@Orin spec.*
---
## Overview
| Board | Role | MCU | USB |
|-------|------|-----|-----|
| **ESP32-S3 BALANCE** | PID balance loop, CAN to VESCs, LCD UI | ESP32-S3 | CH343 USB-serial |
| **ESP32-S3 IO** | RC input, motor drivers, sensors, LEDs, peripherals | ESP32-S3 | JTAG USB |
**Robot form factor:** 4-wheel wagon — 870 × 510 × 550 mm, ~23 kg
**Power:** 36 V battery, DC-DC to 5 V / 12 V
**Orin connection:** CANable2 USB → CAN bus (same bus as VESCs)
---
## ESP32-S3 BALANCE
### Board
Waveshare ESP32-S3 Touch LCD 1.28 (GC9A01 round 240×240 LCD, CST816 touch, QMI8658 IMU)
### Pin Assignments
| Function | GPIO | Notes |
|----------|------|-------|
| **QMI8658 IMU** | | |
| SPI SCK | IO39 | |
| SPI MOSI | IO38 | |
| SPI MISO | IO40 | |
| IMU CS | IO41 | |
| IMU INT1 | IO42 | data-ready interrupt |
| **GC9A01 LCD** | | |
| SPI (shared) | IO39/38 | same SPI bus |
| LCD CS | IO12 | |
| LCD DC | IO11 | |
| LCD RST | IO10 | |
| LCD BL | IO9 | PWM backlight |
| **CST816 Touch** | | |
| I2C SDA | IO4 | |
| I2C SCL | IO5 | |
| Touch INT | IO6 | |
| Touch RST | IO7 | |
| **CAN (SN65HVD230)** | | 500 kbps |
| CAN TX | IO43 | to SN65HVD230 TXD |
| CAN RX | IO44 | from SN65HVD230 RXD |
| **Inter-board UART** | | 460800 baud |
| UART TX → IO | IO17 | |
| UART RX ← IO | IO18 | |
### Software Responsibilities
- Read QMI8658 @ 1 kHz (SPI)
- Run PID balance loop (configurable Kp/Ki/Kd, target pitch)
- Send VESC speed commands via CAN (IDs 68 left, 56 right)
- Receive Orin velocity commands via CAN (0x3000x303)
- Receive IO board status (arming, RC, faults) via UART
- Drive LCD status display (pitch, speed, battery, state)
- Enforce tilt cutoff at ±25°, hardware watchdog 50 ms
- Send telemetry CAN frames 0x4000x401 at 10 Hz
---
## ESP32-S3 IO
### Board
Bare ESP32-S3 devkit (JTAG USB)
### Pin Assignments
| Function | GPIO | Notes |
|----------|------|-------|
| **TBS Crossfire RC** | | UART0, primary RC |
| CRSF RX | IO44 | UART0 RX |
| CRSF TX | IO43 | UART0 TX |
| **ELRS RC failover** | | UART2 |
| ELRS RX | IO16 | UART2 RX |
| ELRS TX | IO17 | UART2 TX |
| **BTS7960 Motor Drivers** | | 2× drivers (left/right) |
| Left RPWM | IO1 | forward PWM |
| Left LPWM | IO2 | reverse PWM |
| Left R_EN | IO3 | enable |
| Left L_EN | IO4 | enable |
| Right RPWM | IO5 | forward PWM |
| Right LPWM | IO6 | reverse PWM |
| Right R_EN | IO7 | enable |
| Right L_EN | IO8 | enable |
| **I2C bus** | | sensors |
| SDA | IO11 | |
| SCL | IO12 | |
| NFC reader | I2C | PN532 or similar |
| Barometer | I2C | BMP280 / BMP388 |
| ToF sensor | I2C | VL53L0X / VL53L1X |
| **WS2812B LEDs** | | |
| LED data | IO13 | |
| **Outputs** | | |
| Horn / buzzer | IO14 | PWM |
| Headlight | IO15 | PWM or digital |
| Fan | IO16 | (shared if ELRS not fitted) |
| Arming button | IO9 | active-low, hold 3 s |
| Kill switch in | IO10 | hardware estop sense |
| **Inter-board UART** | | 460800 baud |
| UART TX → BAL | IO18 | |
| UART RX ← BAL | IO21 | |
### Software Responsibilities
- Parse CRSF frames (TBS Crossfire primary)
- Parse ELRS frames (failover if CRSF absent)
- Drive BTS7960 motor drivers (PWM + enable)
- Read NFC, barometer, ToF via I2C
- Drive WS2812B LEDs (status patterns)
- Control horn, headlight, fan, buzzer
- Manage arming sequence (hold button 3 s while upright)
- Monitor hardware kill switch
- Forward RC + sensor data to BALANCE board via UART
- Report faults, RC loss, sensor health upstream
---
## Inter-Board Protocol (UART 460800 baud)
```
Frame: [0xAA][LEN][TYPE][PAYLOAD...][CRC8]
0xAA — start byte
LEN — payload length (1 byte)
TYPE — message type (1 byte)
PAYLOAD — LEN bytes
CRC8 — CRC-8/MAXIM over TYPE+PAYLOAD
```
### Message Types (IO → BALANCE)
| TYPE | Name | Payload |
|------|------|---------|
| 0x01 | RC_CMD | int16 throttle, int16 steer, uint8 flags (armed, kill) |
| 0x02 | SENSOR | uint16 tof_mm, int16 baro_pa_delta, uint8 nfc_present |
| 0x03 | FAULT | uint8 fault_flags (rc_loss, motor_fault, estop) |
### Message Types (BALANCE → IO)
| TYPE | Name | Payload |
|------|------|---------|
| 0x10 | STATE | int16 pitch_x100, int16 pid_out, uint8 error_state |
| 0x11 | LED_CMD | uint8 pattern, uint8 r, uint8 g, uint8 b |
| 0x12 | BUZZER | uint8 tone_hz, uint16 duration_ms |
---
## CAN Bus — 500 kbps
### Node IDs
| Node | CAN ID | Description |
|------|--------|-------------|
| VESC Left motor | 68 | Speed/duty commands via VESC protocol |
| VESC Right motor | 56 | Speed/duty commands via VESC protocol |
| ESP32 BALANCE | — | Initiates VESC commands; sends telemetry |
| Jetson Orin | — | Via CANable2 USB adapter |
### CAN Frame Assignments
| ID | Direction | Description | Rate |
|----|-----------|-------------|------|
| 0x300 | Orin → BALANCE | Velocity cmd: int16 speed_mmps, int16 steer_mrad | 20 Hz |
| 0x301 | Orin → BALANCE | PID override: float Kp, Ki, Kd (IEEE 754, 4B each) | on demand |
| 0x302 | Orin → BALANCE | Mode: uint8 (0=off,1=balance,2=manual,3=estop) | on demand |
| 0x303 | Orin → BALANCE | Config: uint16 tilt_limit_x100, uint16 max_speed | on demand |
| 0x400 | BALANCE → Orin | Telemetry A: int16 pitch_x100, int16 pid_out, int16 speed_mmps, uint8 state | 10 Hz |
| 0x401 | BALANCE → Orin | Telemetry B: int16 vesc_l_rpm, int16 vesc_r_rpm, uint16 battery_mv, uint8 faults | 10 Hz |
---
## RC Channel Mapping (CRSF / ELRS)
| Channel | Function | Range | Notes |
|---------|----------|-------|-------|
| CH1 | Roll (steer) | 9882012 µs | ±100% = ±max steer |
| CH2 | Pitch (throttle) | 9882012 µs | forward/back speed |
| CH3 | Throttle | 9882012 µs | unused / spare |
| CH4 | Yaw | 9882012 µs | unused |
| CH5 | ARM switch | <1500=disarm, >1500=arm | SB on TX |
| CH6 | ESTOP | <1500=normal, >1500=kill | SC on TX, always checked |
| CH7 | Speed limit | 9882012 µs | 10100% speed cap |
| CH8 | Spare | | |
RC loss (CRSF failsafe or no frame >100 ms): immediate motor cutoff, fault 0x03.
---
## Safety Invariants (unchanged from STM32 era)
1. Motors NEVER spin on power-on — 3 s arm hold required
2. Tilt cutoff ±25° — immediate motor zero, manual re-arm
3. Hardware watchdog 50 ms — firmware hang → motors cut
4. RC ESTOP channel checked every loop iteration
5. Orin CAN timeout 500 ms — revert to RC-only mode
6. Speed hard cap in firmware — start at 10%, increase in 10% steps
7. Never test untethered until stable for 5+ min tethered
---
## Serial Commands (USB debug, both boards)
```
help — list commands
status — print state, pitch, PID, CAN stats
pid <Kp> <Ki> <Kd> — set PID gains
arm — arm (if upright)
disarm — disarm immediately
estop — emergency stop
tilt_limit <deg> — set tilt cutoff (default 25)
speed_limit <pct> — set speed cap (default 10)
can_stats — CAN bus stats (tx/rx/errors)
reboot — soft reboot
```