# 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** (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. 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,\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 ```