sl-webui f71dad5344 feat(arch): migrate all STM32/Mamba/BlackPill refs to ESP32 BALANCE/IO + fix roslib@1.4.0
Architecture change (2026-04-03): Mamba F722S (STM32F722) and BlackPill
replaced by ESP32 BALANCE (PID loop) and ESP32 IO (motors/sensors/comms).

- Update CLAUDE.md, docs, chassis BOM/ASSEMBLY, pinout, power-budget,
  wiring-diagram, TEAM.md, AUTONOMOUS_ARMING.md, docker-compose
- Update all ROS2 package comments, config labels, launch args
  (stm32_port→esp32_port, /dev/stm32-bridge→/dev/esp32-bridge)
- Update WebUI: stm32Mode→esp32Mode, stm32Version→esp32Version,
  "STM32 State/Mode" labels → "ESP32 State/Mode" (ControlMode, SettingsPanel)
- Add TODO(esp32-migration) markers on stm32_protocol.py and mamba_protocol.py
  binary frame layouts — pending ESP32 protocol spec from max
- Fix roslib CDN 1.3.0→1.4.0 in all 11 HTML panels (fixes ROS2 Humble
  rosbridge "Received a message without an op" incompatibility)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:25:24 -04:00

317 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Jetson Orin Nano Super — GPIO / I2C / UART / CSI Pinout Reference
## Self-Balancing Robot: ESP32 Bridge + RealSense D435i + RPLIDAR A1M8 + 4× IMX219
Last updated: 2026-02-28
JetPack version: 6.x (L4T R36.x / Ubuntu 22.04)
---
## 40-Pin Header Overview
The Jetson Orin Nano Super 40-pin header is physically compatible with Raspberry Pi HATs.
Pin numbering follows **physical board pin** (140).
```
3.3V [ 1] [ 2] 5V
SDA1 [ 3] [ 4] 5V ← I2C SDA (i2c-7 on Orin Nano)
SCL1 [ 5] [ 6] GND ← I2C SCL (i2c-7 on Orin Nano)
GPIO [ 7] [ 8] TXD0 ← UART TX (ttyTHS0)
GND [ 9] [10] RXD0 ← UART RX (ttyTHS0)
GPIO [11] [12] GPIO
GPIO [13] [14] GND
GPIO [15] [16] GPIO
3.3V [17] [18] GPIO
MOSI [19] [20] GND ← SPI1 MOSI
MISO [21] [22] GPIO ← SPI1 MISO
SCLK [23] [24] CE0 ← SPI1 CLK / CS0
GND [25] [26] CE1 ← SPI1 CS1
ID_SD[27] [28] ID_SC ← I2C ID EEPROM (reserved)
GPIO [29] [30] GND
GPIO [31] [32] GPIO
GPIO [33] [34] GND
GPIO [35] [36] GPIO
GPIO [37] [38] GPIO
GND [39] [40] GPIO
```
**Note on Orin Nano I2C bus numbering:** The 40-pin header I2C pins (3/5) map to
`/dev/i2c-7` on Orin Nano (not i2c-1 as on the older Nano). Verify with:
```bash
ls /dev/i2c-*
i2cdetect -l
```
---
## 1. ESP32 Bridge (USB CDC — Primary)
The ESP32 BALANCE acts as a real-time motor + IMU controller. Communication is via **USB CDC serial**.
### USB CDC Connection
| Connection | Detail |
|-----------|--------|
| Interface | USB on ESP32 BALANCE board → USB-A on Jetson |
| Device node | `/dev/ttyACM0` → symlink `/dev/esp32-bridge` (via udev) |
| Baud rate | 921600 (configured in ESP32 BALANCE firmware) |
| Protocol | JSON telemetry RX + ASCII command TX (see bridge docs) |
| Power | Powered via robot 5V bus (data-only via USB) |
### Hardware UART (Fallback — 40-pin header)
| Jetson Pin | Signal | ESP32 Pin | Notes |
|-----------|--------|-----------|-------|
| Pin 8 (TXD0) | TX → | PA10 (UART1 RX) | Cross-connect TX→RX |
| Pin 10 (RXD0) | RX ← | PA9 (UART1 TX) | Cross-connect RX→TX |
| Pin 6 (GND) | GND | GND | Common ground **required** |
**Jetson device node:** `/dev/ttyTHS0`
**Baud rate:** 921600, 8N1
**Voltage level:** 3.3V — both Jetson Orin and ESP32 are 3.3V GPIO
```bash
# Verify UART
ls /dev/ttyTHS0
sudo usermod -aG dialout $USER
# Quick test
picocom -b 921600 /dev/ttyTHS0
```
**ROS2 topics (ESP32 bridge node):**
| ROS2 Topic | Direction | Content |
|-----------|-----------|---------
| `/saltybot/imu` | ESP32 BALANCE→Jetson | IMU data (accel, gyro) at 50Hz |
| `/saltybot/balance_state` | ESP32 BALANCE→Jetson | Motor cmd, pitch, state |
| `/cmd_vel` | Jetson→ESP32 BALANCE | Velocity commands → `C<spd>,<str>\n` |
| `/saltybot/estop` | Jetson→ESP32 BALANCE | Emergency stop |
---
## 2. RealSense D435i (USB 3.1)
### Connection
| Parameter | Value |
|-----------|-------|
| Interface | USB 3.1 Gen 1 (USB-A on Jetson — use blue port) |
| Device node | `/dev/bus/usb/...` (udev-managed) |
| USB PID:VID | `0x8086:0x0b3a` (D435i) |
| Power draw | ~1.5W active, 3.5W peak during init |
| Cable | USB 3.1 — use **short cable ≤1m** for stability |
**Note:** Orin Nano Developer Kit has **2× USB-A + 1× USB-C**. Use USB-A (blue = USB 3.1) for D435i.
```bash
lsusb | grep Intel
# Expected: Bus 002 Device 003: ID 8086:0b3a Intel Corp. Intel RealSense D435i
```
**ROS2 topics:**
| Topic | Type | Rate |
|-------|------|------|
| `/camera/color/image_raw` | `sensor_msgs/Image` | 30Hz |
| `/camera/depth/image_rect_raw` | `sensor_msgs/Image` | 30Hz |
| `/camera/aligned_depth_to_color/image_raw` | `sensor_msgs/Image` | 30Hz |
| `/camera/imu` | `sensor_msgs/Imu` | 400Hz |
---
## 3. RPLIDAR A1M8 (UART via USB adapter)
### Connection
| Parameter | Value |
|-----------|-------|
| Interface | USB Micro-B (via included CP2102 USB-UART adapter) |
| Device node | `/dev/ttyUSB0` → symlink `/dev/rplidar` (via udev) |
| Baud rate | 115200 |
| Power draw | ~2.6W motor on, 0.4W idle |
| Motor control | DTR line (handled by rplidar_ros driver) |
```bash
ls /dev/rplidar # should exist after udev rule applied
ros2 launch rplidar_ros rplidar_a1_launch.py serial_port:=/dev/rplidar
```
**ROS2 topics:**
| Topic | Type | Rate |
|-------|------|------|
| `/scan` | `sensor_msgs/LaserScan` | 10Hz |
---
## 4. 4× IMX219 CSI Cameras (MIPI CSI-2)
The IMX219 (Sony 8MP) cameras connect via MIPI CSI-2 FFC cables to the Jetson Orin Nano.
### CSI Connector Layout (Orin Nano Developer Kit)
The Orin Nano Developer Kit has two MIPI CSI-2 connectors:
- **CSI-A (J5):** 15-pin FFC — connects to ArduCam adapter A
- **CSI-B (J8):** 15-pin FFC — connects to ArduCam adapter B
Each ArduCam multi-camera adapter multiplexes 2× IMX219 cameras onto one CSI lane.
### ArduCam Multi-Camera Adapter Wiring
| Adapter | Cameras | CSI Connector | V4L2 Devices |
|---------|---------|---------------|--------------|
| Adapter A (CSI-A) | front + left | J5 | `/dev/video0`, `/dev/video2` |
| Adapter B (CSI-B) | rear + right | J8 | `/dev/video4`, `/dev/video6` |
### IMX219 15-pin FFC Pinout (each camera module)
| Pin | Signal | Notes |
|-----|--------|-------|
| 1 | GND | |
| 2 | CSI D0- | MIPI data lane 0 negative |
| 3 | CSI D0+ | MIPI data lane 0 positive |
| 4 | GND | |
| 5 | CSI D1- | MIPI data lane 1 negative |
| 6 | CSI D1+ | MIPI data lane 1 positive |
| 7 | GND | |
| 8 | CSI CLK- | MIPI clock negative |
| 9 | CSI CLK+ | MIPI clock positive |
| 10 | GND | |
| 11 | CAM_GPIO | Camera enable (active high) |
| 12 | CAM_CLK | I2C / control clock |
| 13 | CAM_SDA | I2C data |
| 14 | GND | |
| 15 | 3.3V | Power |
### V4L2 Device Nodes
```bash
# List all video devices
v4l2-ctl --list-devices
# Expected output:
# vi-output, imx219 2-0010 (platform:tegra-capture-vi:0):
# /dev/video0
# vi-output, imx219 2-0010 (platform:tegra-capture-vi:1):
# /dev/video2
# vi-output, imx219 4-0010 (platform:tegra-capture-vi:2):
# /dev/video4
# vi-output, imx219 4-0010 (platform:tegra-capture-vi:3):
# /dev/video6
# Capture test (GStreamer)
gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
'video/x-raw(memory:NVMM),width=640,height=480,framerate=30/1' ! \
nvvidconv ! xvimagesink
# Capture via V4L2
v4l2-ctl --device=/dev/video0 --stream-mmap --stream-count=1 \
--set-fmt-video=width=640,height=480,pixelformat=RG10
```
### ROS2 Topics (saltybot_cameras package)
| Topic | Camera | Type | Rate |
|-------|--------|------|------|
| `/camera/front/image_raw` | front (video0) | `sensor_msgs/Image` | 30Hz |
| `/camera/left/image_raw` | left (video2) | `sensor_msgs/Image` | 30Hz |
| `/camera/rear/image_raw` | rear (video4) | `sensor_msgs/Image` | 30Hz |
| `/camera/right/image_raw` | right (video6) | `sensor_msgs/Image` | 30Hz |
### TF Frames
| Camera | Frame ID | Offset from sensor_head_link |
|--------|----------|------------------------------|
| front | `camera_front_link` | x=+0.05m, yaw=0° |
| left | `camera_left_link` | y=+0.05m, yaw=+90° |
| rear | `camera_rear_link` | x=-0.05m, yaw=180° |
| right | `camera_right_link` | y=-0.05m, yaw=-90° |
---
## 5. I2C Bus (i2c-7) — Pin 3 / Pin 5
Available for future peripherals (IMU breakout, OLED display, etc.).
| Parameter | Value |
|-----------|-------|
| Jetson I2C bus | i2c-7 (pins 3 = SDA, 5 = SCL) on Orin Nano |
| Voltage | 3.3V pull-up |
| Max clock | 400kHz (Fast Mode) |
```bash
# Scan i2c-7 bus
i2cdetect -y -r 7
```
**Note:** i2c-0 (pins 27/28) is reserved for EEPROM ID — do not use.
---
## 6. M.2 NVMe Storage
The Orin Nano Developer Kit includes an M.2 Key M slot.
| Parameter | Value |
|-----------|-------|
| Interface | PCIe Gen 3 ×4 |
| Form factor | M.2 2230 / 2242 / 2280 |
| Recommended | 256GB+ NVMe SSD (e.g., WD SN530, Samsung PM991) |
| Mount point | `/mnt/nvme` |
```bash
# Verify NVMe detected
lsblk | grep nvme
nvme list
# Partition + format (one-time setup — see setup-jetson.sh)
sudo parted /dev/nvme0n1 mklabel gpt
sudo parted /dev/nvme0n1 mkpart primary ext4 0% 100%
sudo mkfs.ext4 /dev/nvme0n1p1
sudo mkdir -p /mnt/nvme
```
---
## 7. USB Ports Summary
| Port | Type | Used For |
|------|------|----------|
| USB-A (top, blue) | USB 3.1 Gen 1 | RealSense D435i |
| USB-A (bottom) | USB 2.0 | RPLIDAR (via USB-UART adapter) |
| USB-C | USB 3.1 Gen 1 (+ DP) | ESP32 CDC or host flash |
| Micro-USB | Debug/flash | JetPack flash only |
---
## 8. GPIO Summary Table
| Physical Pin | Function | Voltage | Used For |
|-------------|----------|---------|----------|
| 3 | SDA1 | 3.3V | I2C data (i2c-7) |
| 5 | SCL1 | 3.3V | I2C clock (i2c-7) |
| 8 | TXD0 | 3.3V | UART TX → ESP32 BALANCE (fallback) |
| 10 | RXD0 | 3.3V | UART RX ← ESP32 BALANCE (fallback) |
| USB-A ×2 | — | 5V | D435i, RPLIDAR |
| USB-C | — | 5V | ESP32 CDC |
| CSI-A (J5) | MIPI CSI-2 | — | Cameras front + left |
| CSI-B (J8) | MIPI CSI-2 | — | Cameras rear + right |
| M.2 Key M | PCIe Gen3 ×4 | — | NVMe SSD |
---
## 9. udev Rules
Apply stable device names:
```bash
# /etc/udev/rules.d/99-saltybot.rules
# RPLIDAR A1M8 (SiliconLabs CP2102)
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
SYMLINK+="rplidar", MODE="0666"
# ESP32 USB CDC (STMicroelectronics)
KERNEL=="ttyACM*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \
SYMLINK+="esp32-bridge", MODE="0666"
# Intel RealSense D435i
SUBSYSTEM=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b3a", \
MODE="0666"
# IMX219 CSI cameras (V4L2)
KERNEL=="video[0246]", SUBSYSTEM=="video4linux", MODE="0666"
```
```bash
sudo cp docs/99-saltybot.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger
```