sl-jetson c47ac41573 feat: Jetson Nano platform setup and Docker env (bd-1hcg)
- Dockerfile: L4T R32.6.1 (JetPack 4.6) base + ROS2 Humble + SLAM stack
  (slam_toolbox, Nav2, rplidar_ros, realsense2_camera, robot_localization)
- docker-compose.yml: multi-service stack (ROS2, RPLIDAR A1M8, D435i, STM32 bridge)
  with device passthrough, host networking for DDS, persistent map volume
- docs/pinout.md: full GPIO/I2C/UART pinout for STM32F722 bridge (USB CDC +
  UART fallback), RealSense D435i (USB3), RPLIDAR A1M8, udev rules
- docs/power-budget.md: 10W envelope analysis with per-component breakdown,
  mitigation strategies (RPLIDAR gating, D435i 640p, nvpmodel modes)
- scripts/setup-jetson.sh: host one-shot setup (Docker, nvidia-container-runtime,
  udev rules, MAXN power mode, swap)
- scripts/build-and-run.sh: build/up/down/shell/slam/status helper

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 12:46:14 -05:00

214 lines
6.3 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 Nano — GPIO / I2C / UART Pinout Reference
## Self-Balancing Robot: STM32F722 Bridge + RealSense D435i + RPLIDAR A1M8
Last updated: 2026-02-28
JetPack version: 4.6 (L4T R32.6.1)
---
## 40-Pin Header Overview
The Jetson Nano 40-pin header is physically compatible with Raspberry Pi HATs.
Pin numbering below follows **physical board pin** (140) and the Jetson GPIO BCM-equivalent name.
```
3.3V [ 1] [ 2] 5V
SDA1 [ 3] [ 4] 5V ← I2C SDA (i2c-1)
SCL1 [ 5] [ 6] GND ← I2C SCL (i2c-1)
GPIO [ 7] [ 8] TXD0 ← UART TX (ttyTHS1)
GND [ 9] [10] RXD0 ← UART RX (ttyTHS1)
GPIO [11] [12] GPIO
GPIO [13] [14] GND
GPIO [15] [16] GPIO
3.3V [17] [18] GPIO
MOSI [19] [20] GND ← SPI0 MOSI
MISO [21] [22] GPIO ← SPI0 MISO
SCLK [23] [24] CE0 ← SPI0 CLK / CS0
GND [25] [26] CE1 ← SPI0 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
```
---
## 1. STM32F722 Bridge (UART)
The STM32 acts as a real-time motor + IMU controller. Communication to Jetson is via **USB CDC serial** (primary) with hardware UART as fallback.
### USB CDC (Primary — Recommended)
| Connection | Detail |
|-----------|--------|
| Interface | USB Micro-B on STM32 dev board → USB-A on Jetson |
| Device node | `/dev/ttyACM0` or `/dev/ttyUSB1` |
| Baud rate | 921600 (configured in STM32 firmware) |
| Protocol | Custom binary framing (see `src/comm/`) |
| Power | Powered via Jetson USB 5V (500mA max from host) |
### Hardware UART (Fallback)
| 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/ttyTHS1`
**Baud rate:** 921600, 8N1
**Voltage level:** 3.3V — STM32F722 is 3.3V tolerant; Jetson GPIO is 3.3V
**Do NOT use 5V** — Jetson GPIO max is 3.3V
```bash
# Verify UART on Jetson
ls /dev/ttyTHS1
# Check permissions (add user to dialout group)
sudo usermod -aG dialout $USER
# Quick loopback test (connect TX→RX)
picocom -b 921600 /dev/ttyTHS1
```
**ROS2 topic mapping (STM32 bridge node):**
| ROS2 Topic | Direction | Content |
|-----------|-----------|---------|
| `/stm32/imu_raw` | STM32→Jetson | IMU data (accel, gyro) at 500Hz |
| `/stm32/motor_state` | STM32→Jetson | Motor RPM, current, temperature |
| `/cmd_vel` | Jetson→STM32 | Velocity commands (m/s, rad/s) |
| `/stm32/estop` | Jetson→STM32 | Emergency stop signal |
---
## 2. RealSense D435i (USB3)
The D435i provides RGB-D (depth + color) and IMU (accelerometer + gyroscope).
### Connection
| Parameter | Value |
|-----------|-------|
| Interface | USB 3.1 Gen 1 (USB-A on Jetson) |
| 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:** The Jetson Nano has **4× USB-A ports** — use a USB3 port (blue) for D435i.
```bash
# Verify detection
lsusb | grep Intel
# Expected: Bus 002 Device 003: ID 8086:0b3a Intel Corp. Intel RealSense D435i
# Install udev rules (required for non-root access)
sudo cp /etc/udev/rules.d/99-realsense-libusb.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger
# Test with realsense-viewer (if installed)
realsense-viewer
```
**ROS2 topics published:**
| 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 |
| `/camera/color/camera_info` | `sensor_msgs/CameraInfo` | 30Hz |
---
## 3. RPLIDAR A1M8 (UART via USB adapter)
The A1M8 uses a CP2102/CH340 USB-UART adapter (included in kit).
### Connection
| Parameter | Value |
|-----------|-------|
| Interface | USB Micro-B (via included USB-UART adapter) |
| Device node | `/dev/ttyUSB0` (first USB-UART device) |
| Baud rate | 115200 |
| Power draw | ~2.6W motor on, 0.4W idle |
| Motor control | DTR line (handled by rplidar_ros driver) |
```bash
# Verify detection
ls /dev/ttyUSB*
# Expected: /dev/ttyUSB0
# Set permissions
sudo usermod -aG dialout $USER
# Test — should output scan data
ros2 launch rplidar_ros rplidar_a1_launch.py serial_port:=/dev/ttyUSB0
```
**ROS2 topics published:**
| Topic | Type | Rate |
|-------|------|------|
| `/scan` | `sensor_msgs/LaserScan` | 10Hz |
**udev rule (set consistent device name):**
```bash
# /etc/udev/rules.d/99-rplidar.rules
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
SYMLINK+="rplidar", MODE="0666"
```
---
## 4. I2C Bus (i2c-1) — Pin 3 / Pin 5
Available for future peripherals (IMU breakout, OLED display, etc.).
| Parameter | Value |
|-----------|-------|
| Jetson I2C bus | i2c-1 (pins 3 = SDA, 5 = SCL) |
| Voltage | 3.3V pull-up |
| Max clock | 400kHz (Fast Mode) |
| Current source | Jetson 3.3V rail (max ~500mA shared) |
```bash
# Scan i2c-1 bus
i2cdetect -y -r 1
```
**Note:** i2c-0 (pins 27/28) is reserved for EEPROM ID — do not use.
---
## 5. GPIO Summary Table
| Physical Pin | Jetson GPIO | Voltage | Current Used For |
|-------------|-------------|---------|-----------------|
| 3 | SDA1 | 3.3V | I2C data (i2c-1) |
| 5 | SCL1 | 3.3V | I2C clock (i2c-1) |
| 8 | TXD0 | 3.3V | UART TX → STM32 (fallback) |
| 10 | RXD0 | 3.3V | UART RX ← STM32 (fallback) |
| USB-A (×4) | — | 5V | D435i, RPLIDAR adapter, STM32 USB |
---
## 6. Device Enumeration Notes
USB devices may enumerate differently across reboots. Use udev rules for stable 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"
```
Apply rules:
```bash
sudo cp docs/99-saltybot.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger
```