# SaltyLab / SAUL-TEE Wiring Reference

> ⚠️ **ARCHITECTURE CHANGE (2026-04-03):** Mamba F722S / STM32 retired.
> New stack: **ESP32-S3 BALANCE** + **ESP32-S3 IO** + VESCs on 500 kbps CAN.
> **Authoritative reference:** [`docs/SAUL-TEE-SYSTEM-REFERENCE.md`](SAUL-TEE-SYSTEM-REFERENCE.md)
> Historical STM32/Mamba wiring below is **obsolete** — retained for reference only.

---

## ~~System Overview~~ (OBSOLETE — see SAUL-TEE-SYSTEM-REFERENCE.md)

```
┌─────────────────────────────────────────────────────────────────────┐
│                        ORIN NANO SUPER                              │
│                     (Top Plate — 25W)                               │
│                                                                     │
<<<<<<< HEAD
│  USB-A ──── CANable2 USB-CAN adapter (slcan0, 500 kbps)           │
│  USB-A ──── ESP32-S3 IO (/dev/esp32-io, 460800 baud)              │
=======
│  USB-C ──── ESP32-S3 CDC (/dev/esp32-bridge, 921600 baud)            │
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)
│  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                       │
         ▼                                ▼
┌─────────────────────────────────────────────────────────────────────┐
<<<<<<< HEAD
│                  ESP32-S3 BALANCE                                    │
│          (Waveshare Touch LCD 1.28, Middle Plate)                   │
=======
│                     ESP32-S3 BALANCE (FC)                                 │
│                  (Middle Plate — foam mounted)                       │
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)
│                                                                     │
│  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

<<<<<<< HEAD
### 1. Orin <-> ESP32-S3 BALANCE (Primary: CAN Bus via CANable2)
=======
### 1. Orin ↔ FC (Primary: USB Serial (CH343))
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)

| 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 |

<<<<<<< HEAD
- 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)
=======
- Device: `/dev/ttyACM0` → symlink `/dev/esp32-bridge`
- Baud: 921600, 8N1
- Protocol: JSON telemetry (FC→Orin), ASCII commands (Orin→FC)
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)

### 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` |


<<<<<<< HEAD
## FC UART Summary (MAMBA F722S — OBSOLETE)

| 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).
=======
## FC UART Summary (ESP32-S3 BALANCE)

| UART | Pins | Baud | Assignment | Notes |
|------|------|------|------------|-------|
| USART1 | PB6=TX, PB7=RX | — | SmartAudio/VTX | Unused in SaltyLab |
| USART2 | PA2=TX, PA3=RX | 26400 | Hoverboard ESC | Binary motor commands |
| USART3 | PB10=TX, PB11=RX | — | Available | Was SBUS default |
| UART4 | PA0=TX, PA1=RX | 420000 | ELRS RX (CRSF) | RC control |
| UART5 | PC12=TX, PD2=RX | 115200 | Debug serial | Optional |
| USART6 | PC6=TX, PC7=RX | 921600 | Jetson UART | Fallback link |
| USB Serial (CH343) | USB-C | 921600 | Jetson primary | `/dev/esp32-bridge` |
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)


### 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 |
|--------|-----------|------------|
<<<<<<< HEAD
| CANable2 USB-CAN | USB-A | ~0.5W |
| ESP32-S3 BALANCE | USB-C | ~0.8W (WiFi off) |
| ESP32-S3 IO | USB-C | ~0.5W |
=======
| ESP32-S3 FC (CDC) | USB-C | ~0.5W (data only, FC on 5V bus) |
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)
| 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
              ┌────────────▼────────────┐
<<<<<<< HEAD
              │   ESP32-S3 BALANCE      │
              │  (Waveshare LCD 1.28)   │
=======
              │      ESP32-S3 BALANCE        │
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)
              │                         │
              │  QMI8658 -> Balance PID │
              │  RC -> Mode Manager     │
              │  Safety Monitor         │
              │                         │
              └──┬──────────┬───────────┘
<<<<<<< HEAD
    CAN 500kbps─┘          └───── CAN bus / UART fallback
=======
    USART2 ─────┘          └───── USB Serial (CH343) / USART6
    26400 baud                    921600 baud
>>>>>>> 291dd68 (feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only)
         │                              │
    ┌────┴────────────┐                 ▼
    │ 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 │
                       └────────────┘   └───────────────┘
```
