Raspberry Pi Pico を使ったマルチ USB UART Bridge に機能追加してみた

# 0.はじめに
Arduino や Raspberry Pi, ESP32 等、手元にバラバラとマイコン関係が増えてきて、開発に使っている windows に大量の USB ケーブルをつないでいる状態です。調べると同じような事情をなんとかしようと USBシリアル変換器 を作って USBケーブル１本で複数マイコンのシリアルUARTをたばねる試みをされている方がいらっしゃいます。
* [Raspberry pi picoで作るマルチUSB-TTLシリアルコンバータ](https://qiita.com/kazueda/items/596258b2931c8d01697d "Raspberry pi picoで作るマルチUSB-TTLシリアルコンバータ")
* [Raspberry Pi Pico USB-UART Bridge](https://github.com/Noltari/pico-uart-bridge/releases/tag/v3.0 "Raspberry Pi Pico USB-UART Bridge")

ただ自分の欲しい機能がなかったり、たばねることができる UART 数が少なかったりしたので、自分でコーディングしてみました。その内容を共有します。誰かの参考になれば幸いです。

***
# 1.出来ること
* 6つの UART(Tx/Rx) をそれぞれ USB COMポートにブリッジし、PC のシリアルコンソールでデータ送受信できる
* Pico コンソール用の COMポートもあり、6つのブリッジの送受信バイト数確認やデータキャプチャができる

# 2.使い方
使ってみたほうが分かりやすいので、まずは使い方から。
## 2.1.UF2 を書き込んだ Pico を用意して PCにつなぐ
* Github に UF2 ファイルを置いてますので、使うだけならこれを Pico に書き込めば使えます。
[[https://github.com/zbn10/USB-UART-Bridge](https://github.com/zbn10/USB-UART-Bridge)]
* ご自身でビルドされる場合は、以下[[3.使ったもの](#3-使ったもの)][[4.注意点](#4-注意点)]を参照の上実施ください。
ソースは同じく Github に置いてあります。

## 2.2.windows の COMポートと USB-UART Bridge ポートの対応を把握する
この Pico を PC につなぐと、Picoコンソール用USB 1つ、USB<->UARTブリッジの USB 6つの計 7つの COMポートが追加されますが、このままではどの COMポートがどれなのか区別がつきません。デバイスマネージャの情報から特定していきます。
複数の Pico をつないでいると区別がつかない可能性があるため、Pico は一つだけつないだ状態で調べることをお勧めします。
* デバイスマネージャから各COMポートのプロパティを開き、詳細タブ->デバイスインスタンスパス が
USB&yen;<B>VID_2E8A</B>&<B>PID_000A</B>&MI_00&yen;...
になっているものを探す。
VendorID 2E8A = Raspberry Pi
ProductID 000A = Raspberry Pi Pico SDK CDC UART
[[https://github.com/raspberrypi/usb-pid](https://github.com/raspberrypi/usb-pid)]

* COMポート デバイスインスタンスパスの MI_xx が以下の通り対応するので、該当の COMポート番号をメモる。
USB&yen;VID_2E8A&PID_000A&<B>MI_00</B>&yen;...
MI_00 = Pico コンソール
MI_02 = USB-UART Bridge 0
MI_04 = USB-UART Bridge 1
MI_06 = USB-UART Bridge 2
MI_08 = USB-UART Bridge 3
MI_0a = USB-UART Bridge 4
MI_0c = USB-UART Bridge 5

* 私は以下の記事を参考にレジストリの FriendlyName を変更することでデバイスマネージャの表示を変更しました。レジストリを直接いじるため不具合発生のリスクは各自で判断して実施ください。
[https://vertys.net/usb-device-name-change-on-windows10/](https://vertys.net/usb-device-name-change-on-windows10/)
![Customize FriendlyName](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567640/616bff10-4d31-6554-53d5-c272ced9add9.png)

## 2.3.Pico UART ピンに何か通信相手をつなぐ
動作確認できるものなら何でもよいです。
|ブリッジ|Pico ピン(Tx/Rx)|
|:----|:----|
|USB-UART Bridge 0|GPIO 0/1|
|USB-UART Bridge 1|GPIO 4/5|
|USB-UART Bridge 2|GPIO 8/9|
|USB-UART Bridge 3|GPIO 12/13|
|USB-UART Bridge 4|GPIO 16/17|
|USB-UART Bridge 5|GPIO 20/21|

## 2.4.PCのターミナルソフトで UART につないだ装置に USB経由でアクセスしてみる

## 2.5.PCのターミナルソフトで Pico用コンソールUSBシリアルにアクセスしてみる
Picoコンソール用のCOMポートに接続してコマンドを打ってみてください。
```:実行例: help
Usage: 
  show              : show current parameters
  cap num           : enable capture for bridge<n>
  uncap num         : disable capture for bridge<num>
  capmode num mode  : capture mode for bridge<num> to <mode>
                    : mode: 1=TXT, 2=BIN, 3=TXT&BIN
  clear {num | all} : clear bytes count
  help              : print this help
```
```:実行例: show
Show:
  bridge        |  baudrt | capture | capmode |  usb->uart |  uart->usb
  B0 (GP0/1)    |  115200 | off     |     BIN |          0 |          1
  B1 (GP4/5)    |  115200 | off     |     BIN |          0 |          0
  B2 (GP8/9)    |  115200 | off     |     BIN |          0 |          1
  B3 (GP12/13)  |  115200 | off     |     BIN |          0 |          0
  B4 (GP16/17)  |  115200 | off     |     BIN |          0 |          0
  B5 (GP20/21)  |  115200 | off     |     BIN |          0 |          0
```
以下は 2.4 で例示した UART 接続機器との通信を Pico コンソールでキャプチャした例です。
```:実行例: Capture
(送信) capmode 0 1  <- set capture mode of bridge 0 to text mode
(送信) cap 0        <- enable capture on bridge 0
aaa
aaa
(送信) show         <- confirm setting
(送信) uncap 0      <- disable capture on bridge 0
```

# 3.使ったもの
ここは中身に興味のある方向けです。
<UL>
<LI>Raspberry Pi Pico
<LI>Arduino IDE ボードパッケージ Raspberry Pi Pico/RP2040, バージョン 2.5.2<BR>
[<A href="https://github.com/earlephilhower/arduino-pico">Github で公開されているこちら</A>]ですね。<BR>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567640/c5258ca0-96d6-daea-218d-eb3223c41d08.png" width=60%>
<BR>
純正の Pico SDK ではなく Arduino 開発環境でビルドしようと思った理由が一つあり、この Arduino Pico ボードパッケージには Pico の Programmable IO を使った UART 機能(SerialPIO)がライブラリとして組み込まれており、これを使うと非常に簡単に CPU負荷に影響されない独立した UART 機能が用意できます。
<LI>TinyUSB ライブラリ<BR>
ボードパッケージ Raspberry Pi Pico/RP2040 に Adafruit版 TinyUSB が含まれているのでそれを使います。<BR>
Pico SDK 標準 USBスタックでは Row Level API で細々 USBデバイスを設定する必要があり、その点 TinyUSB は使い勝手が良いです。
<LI>TinyUSB ソースコード、ヘッダファイルの修正<BR>
7つの USB CDC インターフェースを作るのに、TinyUSB デフォルトの CDC上限数やUSBデバイス情報格納用固定バッファサイズが足りないため、一部ソースコードを変更する必要があります。詳細は Github に書いておいたのでそちらを参照ください。
パッケージは別のプロジェクトにも使うので、USB-UART Bridge をビルドした後で元に戻しておいたほうがよいかもしれません。
</UL>

***
# 4.注意点
<UL>
<LI>UART 通信速度(BaudRate)は全て 115200 bps です。変更する場合はソースコードを修正してビルドしなおす必要があります。
<LI>Bridge 通信のキャプチャ機能は基本的にデバッグ用途です。多数の Bridge ポートを同時にキャプチャしたりすると一時的にバッファがあふれて通信を取りこぼす可能性があり、万能ではありません。
<LI>ソースからビルドする際は、ボードパラメータの USB Stack で Adafruit TinyUSB を選択してください。<BR>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567640/1e4f92a9-cf7c-19e6-bc2a-1a4b615a9e6a.png" width=50%>
<LI>ターミナルソフトから Pico用コンソール USBシリアルにコマンドを送る際の改行コードは、LF もしくは CRLF にしてください。CR だけだと正しく動きません。
<LI>UART の先につながっているマイコンへのプログラム書込みには使えません。書込み時のマイコンリセット等の方法を別途用意するなど追加の工夫が必要です。
</UL>

# 5.おわりに
各デバイスを USB-UART Bridge にぶらさげようとすると、すでに動いてるデバイスのプログラムの USBシリアル入出力を UART 入出力に書き換える必要があるとか、結局給電にUSBつなぐよね、、とかそのままでは使いずらい点もあるのですが、選択肢の一つになればいいかなと思っています。
おわり。