2023年8月20日日曜日

pythonでシリアルポートのvidとpidを指定してポートを開く


背景

COMポート名ではなくvid(ベンダーID)とpid(プロダクトID)を指定してシリアルポートを開きたい場面があったので、参照方法を調べて実現しました。
備忘録として記事を残します。

使ったもの

  • USBポートがあるPC
    今回はUbuntu 22.04をインストールしたノートPCを利用しました
  • python3
    Ubuntuの場合は下記コマンドでインストールできます
    sudo apt install -y python3-pip
  • USBシリアルポート対応機器
    この記事はESP32S3を接続対象として解説します。

ライブラリインストール: pyserial

pyserialを使ってvidとpidの参照とシリアルポートの接続を行います。
pipコマンドでインストールできます。
python -m pip install pyserial

lsusbでpid vidを確認

linuxならlsusbコマンドでpidとvidを確認できます。
lsusb
Bus 002 Device 041: ID 303a:1001 Espressif USB JTAG/serial debug unit

コロン「:」で繋がっている数字の左がvid、右がpidです。


書き方

serial.toolのlist_portsを使ってvidとpidでポートを絞り込めます。
コード全体を共有後に要所を解説します。
from serial.tools import list_ports
import serial

target_vid = 0x303a
target_pid = 0x1001
path_to_open = None
bps_to_open = 115200
opened_stream = None

for comport in list_ports.comports():
print(comport)
print(comport.hwid)
if comport.vid is not None and comport.vid == target_vid and comport.pid == target_pid:
path_to_open = comport.device

if path_to_open is not None:
try:
opened_stream = serial.Serial(path_to_open, bps_to_open)
print("opened stream")
except serial.serialUtil.SerialException as e:
print("failed to open serial port")
print(e)
else:
print("cannot find target serial port")

serial.toolsはimportしたserial経由では呼べないので、from serial.toolsで中身(list_ports)を呼びます。
from serial.tools import list_ports
import serial

lsusbで取得したvidとpidを持つポートを探します。
target_vid = 0x303a
target_pid = 0x1001

comports関数で認識しているポートの一覧が取得できるので、それのvidとpidを参照します。
hwidvid pid serial_numberなどを表示します。
serial_numberを参照してvidとpidが同じでも個体識別可能な装置が基本だと思いますが、serial_numberが同じで識別不能な装置もあるので、serial_numberを使う場合は確認が必要です。
comportのパスはdeviceで取得できます。
for comport in list_ports.comports():
print(comport)
print(comport.hwid)
if comport.vid is not None and comport.vid == target_vid and comport.pid == target_pid:
path_to_open = comport.device

comport.deviceで取得したパスがあれば開きます。
パスを取得したものの開けない場合は「serial.serialutil.SerialException」でエラーが発生するので、開けない場合もプログラムを終えずにループを繰り返したい場合はそれをexceptして処理を続けます。
if path_to_open is not None:
try:
opened_stream = serial.Serial(path_to_open, bps_to_open)
print("opened stream")
except serial.serialutil.SerialException as e:
print("failed to open serial port")
print(e)
else:
print("cannot find target serial port")

ESP32S3の内蔵jtagポートに対して上記のプログラムを実施した場合、下記のようなログが表示されます。
/dev/ttyACM0 - USB JTAG/serial debug unit
USB VID:PID=303A:1001 SER=F4:12:FA:84:14:24 LOCATION=2-1:1.0
opened stream

おわり

pythonでUSBのvidとpidを指定してシリアルポートを開けました。
他に良い方法や書き方があれば、コメントなどで教えていただけると嬉しいです。

参考

Is it possible to refer to a serial device by vendor and device ID in pySerial?
serial.tools.list_ports

0 件のコメント :