sl-mechanical a2c554c232 cleanup: remove all Mamba/F722S/STM32F722 refs — replace with ESP32-S3 BALANCE/IO
- 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>
2026-04-04 09:06:09 -04:00

309 lines
9.1 KiB
Markdown
Raw Permalink 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-S3 BALANCE (CAN bus) + 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-S3 BALANCE Bridge (CAN bus — Primary)
The ESP32-S3 BALANCE acts as a real-time motor + IMU controller. Communication is via **CAN bus** through a CANable 2.0 USB-CAN adapter.
### CAN Bus Connection
| Connection | Detail |
|-----------|--------|
| Interface | CANable 2.0 USB-CAN adapter → USB-A on Jetson |
| Device node | `/dev/can0` (via CANable 2.0, SocketCAN) |
| Bitrate | 500 kbps |
| Protocol | Binary CAN frames (see balance_protocol.py) |
| Power | ESP32-S3 BALANCE powered from robot 5V DC-DC |
### Bring Up CAN Interface
```bash
# Bring up can0 at 500 kbps
sudo ip link set can0 up type can bitrate 500000
ip link show can0
# Quick test — dump CAN frames
candump can0
```
**ROS2 topics (CAN bridge node):**
| ROS2 Topic | Direction | Content |
|-----------|-----------|---------
| `/saltybot/imu` | ESP32-S3→Jetson | IMU data (accel, gyro) at 50Hz |
| `/saltybot/balance_state` | ESP32-S3→Jetson | Motor cmd, pitch, state |
| `/cmd_vel` | Jetson→CAN 0x300 | Velocity commands via CAN |
| `/saltybot/estop` | Jetson→CAN 0x302 | 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) | CANable 2.0 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-S3 IO (inter-board, fallback) |
| 10 | RXD0 | 3.3V | UART RX ← ESP32-S3 IO (inter-board, fallback) |
| USB-A ×2 | — | 5V | D435i, RPLIDAR |
| USB-C | — | 5V | CANable 2.0 (CAN bus) |
| 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"
# CANable 2.0 USB-CAN adapter
# (bring up with: sudo ip link set can0 up type can bitrate 500000)
KERNEL=="ttyACM*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \
SYMLINK+="balance", 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
```