# 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** (1–40) 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 ```