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>
317 lines
9.4 KiB
Markdown
317 lines
9.4 KiB
Markdown
# 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** (1–40).
|
||
|
||
```
|
||
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
|
||
```
|