Jetson Nano / Xavier NX の GPIO (Digital I/O、PWM、I2C、I2S、SPI) 動作確認

# はじめに
Jetson Xavier NX 開発ボードの拡張コネクタピンレイアウトを確認できたので、実際に動作確認してみました。
https://qiita.com/kitazaki/items/961c80c7e497f6a2f4d9

### 環境
- Jetson Xavier NX  
 - NVMe SSD 128GB
 - JetPack4.4 DP(Developer Preview) (r32.4.2)

- Jetson Nano
 - JetPack4.3 (r32.3.1)

## Jetson-IO
JetPack 4.3 (r32.3.1) で追加された Jetson-IO tool を使用して I2S (aud_mclk、i2s5)、PWM (pwm1、pwm8)、SPI (spi1) を有効にします。
https://qiita.com/kitazaki/items/a445994f1f46a1b15f78
最初の実行でエラーになる問題は JetPack4.4 DP (r32.4.2) では解消されていました。(ワークアラウンドは不要)
https://qiita.com/kitazaki/items/34505828019c102b8701

(変更前)
<img width="50%" alt="変更前.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c3f15891-42ab-e068-8677-235d637186d0.png">

(設定追加)
<img width="50%" alt="設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/a70b9162-8072-d154-a1d3-08577e4e30ce.png">

(変更後)
<img width="50%" alt="変更後.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/cb10963b-134a-b36c-df87-015e2d3061c8.png">


## Jetson-GPIO
NVIDIA が公開している <a href="https://github.com/NVIDIA/jetson-gpio">Jetson.GPIO Python library</a> について動作確認します。
書籍「<a href="https://www.amazon.co.jp/Jetson-Nano%E8%B6%85%E5%85%A5%E9%96%80-Japan-User-Group/dp/4800712513">Jetson Nano 超入門</a>」の Part 8-2、8-3 と同様です。

### デジタル入出力と LED 制御
すべての動作確認 OK でした。

- simple_input.py  
- simple_out.py  
- button_led.py  
- button_event.py  
- button_interrupt.py

### PWM
- simple_pwm.py  

PWM はピン設定 (ピン番: 32 と 33) とサーボモーターの仕様に合わせて Duty 比を変更する必要があります。  
https://qiita.com/kitazaki/items/9db6b0679eee5f768b3e

## I2C
書籍「<a href="https://www.amazon.co.jp/Jetson-Nano%E8%B6%85%E5%85%A5%E9%96%80-Japan-User-Group/dp/4800712513">Jetson Nano 超入門</a>」の Part 8-4 と同様です。
I2C Bus 番号、ソースコードを修正して動作確認 OK でした。
差分情報を記載します。

### I2C Bus 番号の変更

```bash
$ sudo i2cdetect -r -y 1
↓
$ sudo i2cdetect -r -y 8
```

### Python ライブラリのインストール
OLED、BME280 の動作確認に Python ライブラリをインストールする必要があります。

```bash
$ git clone https://github.com/Seeed-Studio/grove.py
$ cd grove.py
$ sudo apt install python-pip
$ sudo pip install .
$ sudo pip install smbus
```

### ソースコードの修正
I2C Bus 番号の変更に伴ってソースコードの修正が必要です。

```python:grove_oled_display_128x64.py
    def __init__(self, bus=None, address=0x3C):
↓
    def __init__(self, bus=8, address=0x3C):
```

```python:bme280.py
bus = smbus.SMBus(1) # Rev 2 Pi, Pi 2 & Pi 3 uses bus 1
↓
bus = smbus.SMBus(8) # Rev 2 Pi, Pi 2 & Pi 3 uses bus 1
```

```python:bme280_oled.py
    def __init__(self, bus=None, address=0x3C):
↓
    def __init__(self, bus=8, address=0x3C):
```

```python:~/.local/lib/python3.6/site-packages/Adafruit_GPIO/I2C.py
   return Device(address, 1, i2c_interface, **kwargs)
↓
   return Device(address, 8, i2c_interface, **kwargs)
```

## I2S
認識されるデバイス名が異なるだけで動作確認 OK でした。
https://qiita.com/kitazaki/items/9c976bd7aa13ec204a0e

```bash
$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: tegrahdagalent1 [tegra-hda-galen-t194], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: tegrahdagalent1 [tegra-hda-galen-t194], device 7: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: tegrahdagalent1 [tegra-hda-galen-t194], device 8: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: tegrahdagalent1 [tegra-hda-galen-t194], device 9: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 0: ADMAIF1 CIF ADMAIF1-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 1: ADMAIF2 CIF ADMAIF2-1 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 2: ADMAIF3 CIF ADMAIF3-2 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 3: ADMAIF4 CIF ADMAIF4-3 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 4: ADMAIF5 CIF ADMAIF5-4 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 5: ADMAIF6 CIF ADMAIF6-5 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 6: ADMAIF7 CIF ADMAIF7-6 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 7: ADMAIF8 CIF ADMAIF8-7 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 8: ADMAIF9 CIF ADMAIF9-8 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 9: ADMAIF10 CIF ADMAIF10-9 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 10: ADMAIF11 CIF ADMAIF11-10 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 11: ADMAIF12 CIF ADMAIF12-11 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 12: ADMAIF13 CIF ADMAIF13-12 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 13: ADMAIF14 CIF ADMAIF14-13 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 14: ADMAIF15 CIF ADMAIF15-14 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 15: ADMAIF16 CIF ADMAIF16-15 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 16: ADMAIF17 CIF ADMAIF17-16 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 17: ADMAIF18 CIF ADMAIF18-17 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 18: ADMAIF19 CIF ADMAIF19-18 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: jetsonxaviernxa [jetson-xaviernx-ape], device 19: ADMAIF20 CIF ADMAIF20-19 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
```

認識されたデバイス名 jetsonxaviernxa を指定する。

```
$ aplay -D plughw:CARD=jetsonxaviernxa,DEV=0 fanfare.wav
```

## SPI
動作確認に使用したデバイスは以下のとおりです。

- OLED 128x 64 SSD1306 (SPI 接続用)
- 1.8' SPI 128x160 ST7735
- 1.3' 240*240 IPS ST7789 (CS ピン無し)

OLED 128x 64 SSD1306
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/180549ff-8b05-b688-b880-b9caf849f6d4.png" width="30%">

1.8' SPI 128x160 ST7735 (表 / 裏)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/69079d04-bc6f-de25-1040-cc277bc2c55b.png" width="40%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/e35c3751-99ba-528f-380c-6f847856a0ee.png" width="40%">

1.3' 240*240 IPS ST7789
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/82d74b58-e99f-183f-2f02-139eeb1a1e50.png" width="30%">


Raspberry Pi 3B+ では全て問題なく動作しましたが、Jetson Nano、Xavier NX では動作しないデバイスもありました。(使用したライブラリでは動作しませんでした)

| | OLED 128x 64 SSD1306 | 1.8' SPI 128x160 ST7735 | 1.3' 240*240 IPS ST7789 |
| --- | --- | --- | --- |
| Raspberry Pi 3B+ | OK | OK | OK |
| Jetson Nano | NG | OK | OK |
| Xavier NX | NG | OK | NG |

### 接続方法
OLED 128x 64 SSD1306

| OLED 128x 64 SSD1306 | Nano / Xavier NX ピン番号 |
| --- | --- |
| GND | 6 (GND) |
| VCC | 1 (3.3V) |
| D0 (SCK) | 23 (SCK) |
| D1 (SDI) | 19 (MOSI) |
| RES | 18 (GPIO 24) |
| DC | 22 (GPIO 25) |
| CS | 24 (CS0) |

1.8' SPI 128x160 ST7735

| 1.8' SPI 128x160 ST7735 | Nano / Xavier NX ピン番号 |
| --- | --- |
| 1-RES | 18 (GPIO 24) |
| 2-CS | 24 (CS0) |
| 3-D/C | 22 (GPIO 25) |
| 4-DIN | 19 (MOSI) |
| 5-CLK | 23 (SCK) |
| 6-VCC | 2 (5V) |
| 7-BL | 2 (5V) |
| 8-GND | 6 (GND) |

1.3' 240*240 IPS ST7789

| 1.3' 240*240 IPS ST7789 | Nano / Xavier NX ピン番号 |
| --- | --- |
| GND | 6 (GND) |
| VCC | 1 (3.3V) |
| SCL (SPI clock line) | 23 (SCK) |
| SDA (SPI data line) | 19 (MOSI) |
| RES | 18 (GPIO 24)
| DC | 22 (GPIO 25)
| BLK (Backlight LED Kathode) | 13 (GPIO 27) |

## Python ライブラリとソースコード
### Raspberry Pi 3B+
raspi-config コマンドで SPI を有効化 (有効にして再起動) します。

```bash
$ sudo raspi-config
```

SSD1306 (Adafruit_Python_SSD1306) ライブラリをインストールします。

```bash
$ git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
$ cd Adafruit_Python_SSD1306
$ sudo python3 setup.py install
```

サンプルプログラムを修正して実行します。
(shapes.py を例に説明しますが、他の animate.py、image.py、stats.py も同様です。)

```bash
$ cd examples
$ vi shapes.py
$ sudo python3 shapes.py
```

```python:shapes.py
DC = 23
↓
DC = 25

disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST)
↓
#disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST)

# disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))
↓
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))
```

他のプログラム (Luma.OLED) も正常に動作しました。

```bash
$ git clone https://github.com/rm-hull/luma.examples.git
$ cd luma.examples
$ sudo python3 3d_box.py -i spi --gpio-data-command 25 --gpio-reset 24
```

### Jetson Nano
ST7735 (adafruit-circuitpython-rgb-display) ライブラリをインストールします。

```bash
$ sudo apt-get install python3-pip python3-pil
$ pip3 install adafruit-blinka
$ pip3 install adafruit-circuitpython-busdevice
$ pip3 install adafruit-circuitpython-rgb-display
```

サンプルプログラムを修正して実行します。

```
$ git clone https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display
$ cd Adafruit_CircuitPython_RGB_Display/examples
$ vi rgb_display_pillow_stats.py
$ python3 rgb_display_pillow_stats.py
```

```python:rgb_display_pillow_stats.py
# disp = st7735.ST7735R(spi, rotation=90,     # 1.8" ST7735R
↓
disp = st7735.ST7735R(spi, rotation=90,         # 1.8" ST7735R

disp = ili9341.ILI9341(
    spi,
    rotation=90,  # 2.2", 2.4", 2.8", 3.2" ILI9341
↓
#disp = ili9341.ILI9341(
#    spi,
#    rotation=90,  # 2.2", 2.4", 2.8", 3.2" ILI9341

font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 24)
↓
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 10)
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d3b61b79-9ac0-7ab5-75e4-9940d5d9e4f5.png" width="50%">

ST7789 (Python_ST7789) ライブラリをインストールします。
(CS ピンが無い 1.3' 240*240 IPS ST7789 を使用したため、adafruit-circuitpython-rgb-display ライブラリは動作しませんでした。)

```bash
$ git clone https://github.com/solinnovay/Python_ST7789
$ cd Python_ST7789
$ sudo python3 setup.py install
```

サンプルプログラムを修正して実行します。

```
$ cd examples
$ vi clock_EN.py
$ python3 clock_EN.py
```

```python:clock_EN.py
RST = 27
↓
RST = 24

LED = 24
↓
LED = 27
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/84f7182c-e362-4130-4beb-71185ab8d6b5.png" width="50%">

### Jetson NX
Jetson Nano と同様に ST7735 (adafruit-circuitpython-rgb-display) ライブラリをインストールし、サンプルプログラムを修正して実行します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/66aa874e-9fcc-9dd5-8eb6-7b634171d2af.png" width="75%">