saltylab-firmware/docs/wiring-diagram.md
sl-webui 308be74330 feat(arch): implement SAUL-TEE ESP32 protocol specs from hal reference doc
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>
2026-04-04 08:59:28 -04:00

14 KiB

SaltyLab Wiring Diagram

System Overview

┌─────────────────────────────────────────────────────────────────────┐
│                        ORIN NANO SUPER                              │
│                     (Top Plate — 25W)                               │
│                                                                     │
│  USB-A ──── CANable2 USB-CAN adapter (slcan0, 500 kbps)           │
│  USB-A ──── ESP32-S3 IO (/dev/esp32-io, 460800 baud)              │
│  USB-A1 ─── RealSense D435i (USB 3.1)                             │
│  USB-A2 ─── RPLIDAR A1M8 (via CP2102 adapter, 115200)             │
│  USB-C* ─── SIM7600A 4G/LTE modem (ttyUSB0-2, AT cmds + PPP)     │
│  USB ─────── Leap Motion Controller (hand/gesture tracking)        │
│  CSI-A ──── ArduCam adapter → 2x IMX219 (front + left)            │
│  CSI-B ──── ArduCam adapter → 2x IMX219 (rear + right)            │
│  M.2 ───── 1TB NVMe SSD                                            │
│  40-pin ─── ReSpeaker 2-Mic HAT (I2S + I2C, WM8960 codec)         │
│  Pin 8 ──┐                                                         │
│  Pin 10 ─┤ UART fallback to ESP32-S3 BALANCE (ttyTHS0, 460800)    │
│  Pin 6 ──┘ GND                                                     │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
         │ USB-A (CANable2)               │ UART fallback (3 wires)
         │ SocketCAN slcan0               │ 460800 baud, 3.3V
         │ 500 kbps                       │
         ▼                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                  ESP32-S3 BALANCE                                    │
│          (Waveshare Touch LCD 1.28, Middle Plate)                   │
│                                                                     │
│  CAN bus ──── CANable2 → Orin (primary link, ISO 11898)            │
│  UART0 ──── Orin UART fallback (460800 baud, 3.3V)                │
│  UART1 ──── VESC Left  (CAN ID 56) via UART/CAN bridge            │
│  UART2 ──── VESC Right (CAN ID 68) via UART/CAN bridge            │
│  I2C   ──── QMI8658 IMU (onboard, 6-DOF accel+gyro)               │
│  SPI   ──── GC9A01 LCD (onboard, 240x240 round display)           │
│  GPIO  ──── WS2812B LED strip                                      │
│  GPIO  ──── Buzzer                                                  │
│  ADC   ──── Battery voltage divider                                │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
         │ CAN bus (ISO 11898)            │ UART (460800 baud)
         │ 500 kbps                       │
         ▼                                ▼
┌────────────────────────┐    ┌──────────────────────────┐
│   VESC Left (ID 56)    │    │   VESC Right (ID 68)     │
│   (Bottom Plate)       │    │   (Bottom Plate)          │
│                        │    │                            │
│  BLDC hub motor        │    │  BLDC hub motor            │
│  CAN 500 kbps          │    │  CAN 500 kbps             │
│  FOC current control   │    │  FOC current control      │
│  VESC Status 1 (0x900) │    │  VESC Status 1 (0x910)   │
│                        │    │                            │
└────────────────────────┘    └──────────────────────────┘
         │                              │
    LEFT MOTOR                    RIGHT MOTOR

Wire-by-Wire Connections

1. Orin <-> ESP32-S3 BALANCE (Primary: CAN Bus via CANable2)

From To Wire Notes
Orin USB-A CANable2 USB USB cable SocketCAN slcan0 @ 500 kbps
CANable2 CAN-H ESP32-S3 BALANCE CAN-H twisted pair ISO 11898 differential
CANable2 CAN-L ESP32-S3 BALANCE CAN-L twisted pair ISO 11898 differential
  • Interface: SocketCAN slcan0, 500 kbps
  • Device node: /dev/canable2 (via udev, symlink to ttyUSBx)
  • Protocol: CAN frames --- ORIN_CMD_DRIVE (0x300), ORIN_CMD_MODE (0x301), ORIN_CMD_ESTOP (0x302)
  • Telemetry: BALANCE_STATUS (0x400), BALANCE_VESC (0x401), BALANCE_IMU (0x402), BALANCE_BATTERY (0x403)

2. Orin <-> ESP32-S3 BALANCE (Fallback: Hardware UART)

Orin Pin Signal ESP32-S3 Pin Notes
Pin 8 TXD0 GPIO17 (UART0 RX) Orin TX -> BALANCE RX
Pin 10 RXD0 GPIO18 (UART0 TX) Orin RX <- BALANCE TX
Pin 6 GND GND Common ground
  • Jetson device: /dev/ttyTHS0
  • Baud: 460800, 8N1
  • Voltage: 3.3V both sides (no level shifter needed)
  • Cross-connect: Orin TX -> BALANCE RX, Orin RX <- BALANCE TX

3. Orin <-> ESP32-S3 IO (USB Serial)

From To Notes
Orin USB-A ESP32-S3 IO USB-C USB cable, /dev/esp32-io
  • Device node: /dev/esp32-io (udev symlink)
  • Baud: 460800, 8N1
  • Protocol: Binary frames [0xAA][LEN][TYPE][PAYLOAD][CRC8]
  • Use: IO expansion, GPIO control, sensor polling

4. ESP32-S3 BALANCE <-> VESC Motors (CAN Bus)

BALANCE Pin Signal VESC Pin Notes
GPIO21 CAN-H CAN-H ISO 11898 differential pair
GPIO22 CAN-L CAN-L ISO 11898 differential pair
GND GND GND Common ground
  • Baud: 500 kbps CAN
  • VESC Left: CAN ID 56, VESC Right: CAN ID 68
  • Commands: COMM_SET_RPM, COMM_SET_CURRENT, COMM_SET_DUTY
  • Telemetry: VESC Status 1 at 50 Hz (RPM, current, duty)

5. Power Distribution

BATTERY (36V) ──┬── VESC Left  (36V direct -> BLDC left motor)
                ├── VESC Right (36V direct -> BLDC right motor)
                │
                ├── 5V BEC/regulator ──┬── Orin (USB-C PD or barrel jack)
                │                      ├── ESP32-S3 BALANCE (5V via USB-C)
                │                      ├── ESP32-S3 IO (5V via USB-C)
                │                      ├── WS2812B LEDs (5V)
                │                      └── RPLIDAR (5V via USB)
                │
                └── Battery monitor ──── ESP32-S3 BALANCE ADC (voltage divider)

6. Sensors on Orin (USB/CSI)

Device Interface Orin Port Device Node
RealSense D435i USB 3.1 USB-A (blue) /dev/bus/usb/...
RPLIDAR A1M8 USB-UART USB-A /dev/rplidar
IMX219 front+left MIPI CSI-2 CSI-A (J5) /dev/video0,2
IMX219 rear+right MIPI CSI-2 CSI-B (J8) /dev/video4,6
1TB NVMe PCIe Gen3 x4 M.2 Key M /dev/nvme0n1
CANable2 USB-CAN USB-A /dev/canable2 -> slcan0

ESP32-S3 BALANCE UART/CAN Summary

Interface Pins Baud/Rate Assignment Notes
UART0 GPIO17=RX, GPIO18=TX 460800 Orin UART fallback 3.3V, cross-connect
UART1 GPIO19=RX, GPIO20=TX 115200 Debug serial Optional
CAN (TWAI) GPIO21=H, GPIO22=L 500 kbps CAN bus (VESCs + Orin) SN65HVD230 transceiver
I2C GPIO4=SDA, GPIO5=SCL 400 kHz QMI8658 IMU (addr 0x6B) Onboard
SPI GPIO36=MOSI, GPIO37=SCLK, GPIO35=CS 40 MHz GC9A01 LCD (onboard) 240x240 round
USB CDC USB-C 460800 Orin USB fallback /dev/esp32-balance

CAN Frame ID Map

CAN ID Direction Name Contents
0x300 Orin -> BALANCE ORIN_CMD_DRIVE left_rpm_f32, right_rpm_f32 (8 bytes LE)
0x301 Orin -> BALANCE ORIN_CMD_MODE mode byte (0=IDLE, 1=DRIVE, 2=ESTOP)
0x302 Orin -> BALANCE ORIN_CMD_ESTOP flags byte (bit0=stop, bit1=clear)
0x400 BALANCE -> Orin BALANCE_STATUS pitch x10:i16, motor_cmd:u16, vbat_mv:u16, state:u8, flags:u8
0x401 BALANCE -> Orin BALANCE_VESC l_rpm x10:i16, r_rpm x10:i16, l_cur x10:i16, r_cur x10:i16
0x402 BALANCE -> Orin BALANCE_IMU pitch x100:i16, roll x100:i16, yaw x100:i16, ax x100:i16, ay x100:i16, az x100:i16
0x403 BALANCE -> Orin BALANCE_BATTERY vbat_mv:u16, current_ma:i16, soc_pct:u8
0x900+ID VESC Left -> VESC_STATUS_1 erpm:i32, current x10:i16, duty x1000:i16
0x910+ID VESC Right -> VESC_STATUS_1 erpm:i32, current x10:i16, duty x1000:i16

VESC Left CAN ID = 56 (0x38), VESC Right CAN ID = 68 (0x44).

7. ReSpeaker 2-Mic HAT (on Orin 40-pin header)

Orin Pin Signal Function
Pin 12 (GPIO 18) I2S BCLK Audio bit clock
Pin 35 (GPIO 19) I2S LRCLK Audio left/right clock
Pin 38 (GPIO 20) I2S DIN Audio data in (from mics)
Pin 40 (GPIO 21) I2S DOUT Audio data out (to speaker)
Pin 3 (GPIO 2) I2C SDA WM8960 codec control (i2c-7)
Pin 5 (GPIO 3) I2C SCL WM8960 codec control (i2c-7)
Pin 32 (GPIO 12) GPIO Button input
Pin 11 (GPIO 17) GPIO RGB LED (APA102 data)
Pin 2, 4 5V Power
Pin 6, 9 GND Ground
  • Codec: Wolfson WM8960 (I2C addr 0x1A)
  • Mics: 2x MEMS (left + right) --- basic stereo / sound localization
  • Speaker: 3W class-D amp output (JST connector)
  • Headset: 3.5mm TRRS jack
  • Requires: WM8960 device tree overlay for Jetson (community port)
  • Use: Voice commands (faster-whisper), wake word (openWakeWord), audio feedback, status announcements

8. SIM7600A 4G/LTE HAT (via USB)

Connection Detail
Interface USB (micro-B on HAT -> USB-A/C on Orin)
Device nodes /dev/ttyUSB0 (AT), /dev/ttyUSB1 (PPP/data), /dev/ttyUSB2 (GPS NMEA)
Power 5V from USB or separate 5V supply (peak 2A during TX)
SIM Nano-SIM slot on HAT
Antenna 4G LTE + GPS/GNSS (external SMA antennas --- mount high on chassis)
  • Data: PPP or QMI for internet connectivity
  • GPS/GNSS: Built-in receiver, NMEA sentences on ttyUSB2 --- outdoor positioning
  • AT commands: AT+CGPS=1 (enable GPS), AT+CGPSINFO (get fix)
  • Connected via USB (not 40-pin) --- avoids UART conflict with BALANCE fallback, flexible antenna placement
  • Use: Remote telemetry, 4G connectivity outdoors, GPS positioning, remote SSH/control

9. Leap Motion Controller (USB)

Connection Detail
Interface USB 3.0 (micro-B on controller -> USB-A on Orin)
Power ~0.5W
Range ~80cm, 150 deg FOV
SDK Ultraleap Gemini V5+ (Linux ARM64 support)
ROS2 leap_motion_ros2 wrapper available
  • 2x IR cameras + 3x IR LEDs --- tracks all 10 fingers in 3D, sub-mm precision
  • Mount: Forward-facing on sensor tower or upward on Orin plate
  • Use: Gesture control (palm=stop, point=go, fist=arm), hand-following mode, demos
  • Combined with ReSpeaker: Voice + gesture control with zero hardware in hand

10. Power Budget (USB)

Device Interface Power Draw
CANable2 USB-CAN USB-A ~0.5W
ESP32-S3 BALANCE USB-C ~0.8W (WiFi off)
ESP32-S3 IO USB-C ~0.5W
RealSense D435i USB-A ~1.5W (3.5W peak)
RPLIDAR A1M8 USB-A ~2.6W (motor on)
SIM7600A USB ~1W idle, 3W TX peak
Leap Motion USB-A ~0.5W
ReSpeaker HAT 40-pin ~0.5W
Total USB ~7.9W typical, ~11W peak

Orin Nano Super delivers up to 25W --- USB peripherals are well within budget.


Data Flow

                    ┌──────────────┐
                    │  RC TX       │ (in your hand)
                    │  (2.4GHz)    │
                    └──────┬───────┘
                           │ radio
                    ┌──────▼───────┐
                    │  RC RX       │ CRSF 420kbaud (future)
                    └──────┬───────┘
                           │ UART
              ┌────────────▼────────────┐
              │   ESP32-S3 BALANCE      │
              │  (Waveshare LCD 1.28)   │
              │                         │
              │  QMI8658 -> Balance PID │
              │  RC -> Mode Manager     │
              │  Safety Monitor         │
              │                         │
              └──┬──────────┬───────────┘
    CAN 500kbps─┘          └───── CAN bus / UART fallback
         │                              │
    ┌────┴────────────┐                 ▼
    │ CAN bus (500k)  │        ┌───────────────────┐
    ├─ VESC Left  56  │        │   Orin Nano Super  │
    └─ VESC Right 68  │        │                     │
         │    │                │  SLAM / Nav2 / AI  │
         ▼    ▼                │  Person following   │
       LEFT  RIGHT             │  Voice commands     │
       MOTOR MOTOR             │  4G telemetry       │
                               └──┬──────────┬───────┘
                                  │          │
                       ┌──────────▼─┐   ┌────▼──────────┐
                       │ ReSpeaker  │   │  SIM7600A     │
                       │ 2-Mic HAT  │   │  4G/LTE + GPS │
                       └────────────┘   └───────────────┘