sl-jetson 3755e235aa feat: Orin Nano Super platform update + 4x IMX219 CSI cameras
Task A — Orin Nano Super platform update:
- docker-compose.yml: update header/comments, switch all service image tags
  to jetson-orin, update devices to udev symlinks (/dev/rplidar,
  /dev/stm32-bridge, i2c-7), add NVMe volume mounts (/mnt/nvme/saltybot),
  update stm32-bridge to saltybot_bridge launch, add csi-cameras service
- docs/pinout.md: full rewrite for Orin Nano Super — i2c-7, ttyTHS0,
  CSI-A/B connectors, M.2 NVMe slot, IMX219 15-pin FFC pinout, V4L2 nodes,
  GStreamer test commands, updated udev rules
- docs/power-budget.md: full rewrite — 25W TDP, 8GB LPDDR5, 67 TOPS,
  4-camera CSI bandwidth analysis, nvpmodel modes, Nano vs Orin comparison,
  5V 6A PSU recommendation, 4S LiPo architecture
- scripts/setup-jetson.sh: full rewrite — JetPack 6 / Ubuntu 22.04,
  nvidia-container-toolkit new keyring method, NVMe partition/format/fstab,
  CSI driver check (imx219 modprobe), video group, jtop install, 8GB swap

Task B — saltybot_cameras ROS2 package:
- launch/csi_cameras.launch.py: 4x v4l2_camera nodes, namespace per camera
  (front/left/rear/right), 640x480x30fps, includes TF launch automatically
- launch/camera_tf.launch.py: static TF for 4 cameras at 90deg intervals
  on sensor_head_link (r=5cm offset), yaw 0/90/180/-90 deg
- package.xml, setup.py, setup.cfg, __init__.py, resource marker
- config/cameras_params.yaml: per-camera device/frame/offset configuration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 22:59:13 -05:00

317 lines
9.4 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: STM32F722 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. STM32F722 Bridge (USB CDC — Primary)
The STM32 acts as a real-time motor + IMU controller. Communication is via **USB CDC serial**.
### USB CDC Connection
| Connection | Detail |
|-----------|--------|
| Interface | USB Micro-B on STM32 dev board → USB-A on Jetson |
| Device node | `/dev/ttyACM0` → symlink `/dev/stm32-bridge` (via udev) |
| Baud rate | 921600 (configured in STM32 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 | STM32 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 STM32F722 are 3.3V GPIO
```bash
# Verify UART
ls /dev/ttyTHS0
sudo usermod -aG dialout $USER
# Quick test
picocom -b 921600 /dev/ttyTHS0
```
**ROS2 topics (STM32 bridge node):**
| ROS2 Topic | Direction | Content |
|-----------|-----------|---------
| `/saltybot/imu` | STM32→Jetson | IMU data (accel, gyro) at 50Hz |
| `/saltybot/balance_state` | STM32→Jetson | Motor cmd, pitch, state |
| `/cmd_vel` | Jetson→STM32 | Velocity commands → `C<spd>,<str>\n` |
| `/saltybot/estop` | Jetson→STM32 | 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) | STM32 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 → STM32 (fallback) |
| 10 | RXD0 | 3.3V | UART RX ← STM32 (fallback) |
| USB-A ×2 | — | 5V | D435i, RPLIDAR |
| USB-C | — | 5V | STM32 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"
# STM32 USB CDC (STMicroelectronics)
KERNEL=="ttyACM*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \
SYMLINK+="stm32-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
```