ダイオードI-V特性測定器作成:3-1. PC側ソフト設計 – pySerialでUSBシリアル通信
本記事の主旨
ダイオードI-V特性測定器(カーブトレーサ)作成のPC側ソフト上におけるpySerialでのUSBシリアル通信について記す。
本記事の目的
本記事の目的を以下に記す。
- pySerialで作成したUSBシリアル通信のソースについての解説を記すこと
本記事の背景
ダイオードI-V特性測定器(カーブトレーサ)作成の中でPC側ソフトを作成したため、本記事でその部分的な解説をする。
本記事の位置づけ
以下の流れで作業説明と解説を行った。
記事に対応したリンクを添付した。
概要説明:ダイオードI-V特性測定器作成:0. 概要 | 工事中.com
- 取扱説明
- 回路設計
- ダイオードのI-V特性を手作業で確認
- 回路の実装
- 回路の実装(PWM平滑化)
- 回路の実装(PWM平滑化以外)
- PC側ソフト設計
- pySerialでUSBシリアル通信★現在のページ
- Matplotlibでのグラフ表示
- Pythonで最小二乗法の指数関数近似
- openpyxlでグラフ描画と最小二乗法の指数関数近似
- マイコン側ソフト設計
- Arduino Uno Rev3 / R4 Minima
- Raspberry Pi Pico / Pico 2
- 実験
- 1N4148の測定でマイコンとソースの組み合わせを比較
- 種々のダイオードを測定
- 種々の高精度ゲルマニウムダイオードを測定
- まとめと補足
コードの全体
今回解説するコードの全体は、以下にアップロードした。
usbserial.py
USBシリアル通信用ソースファイル。
コードの解説
シリアルポートの取得とオープン
以下のUSBSerialクラス内で実装した。
シリアルポートの取得
pySerialのserial.tools.list_ports.comports()関数で、利用可能なシリアルポートのリストが取得できる。
USBSerialクラス内では、わかりやすく自作のlistUpCom()関数でラッピングしている。
def listUpCom():
return serial.tools.list_ports.comports()
シリアルポートのオープン
pySerialのserial.Serialオブジェクトを作成するときに、自動的にオープンする。
USBSerialクラス内では、わかりやすく自作のopenCom()関数でラッピングしている。
def openCom(com, speed):
return serial.Serial(com, speed)
シリアル送受信
以下のUSBSerialDataクラス内で実装した。
シリアルポートの前処理
自作のUSBSerial.listUpCom()関数で取得した利用可能なシリアルポートのうち、先頭のシリアルポートを使用した。
自作のUSBSerial.openCom()関数で、115200bpsのボーレートにしてシリアルポートを開いた。
# シリアルポート前処理
measure_com = (USBSerial.listUpCom())[0].device # シリアルポート取得
ser = USBSerial.openCom(measure_com, 115200) # シリアルポートを開く
シリアルポートの接続待ち
time.sleep(3)関数で、3秒待った。
Arduino Uno Rev3とのシリアル接続後にマイコン側でリセットがかかるため、リセットにかかる時間分は待つようにした。
Arduino Uno Rev3ではArduino IDEでのシリアル通信接続時も、特に対策されることなく同様に起こる。
Arduino Uno Rev3では、基板上のLED「L」を見るとリセット時と同じ挙動をすることを確認できる。
DTSを操作する方法もあるようだが、これでもリセットがかかる。
# シリアル接続後にリセットがかかるため、リセットを待つ。
# これは、Arduino IDEでシリアル通信接続時も同様に起こる。
# 基板上のLED「L」がリセット時と同じ挙動をすることを確認できる。
# リンクのようにDTSを操作する方法もあるようだが、これでもリセットがかかる。https://erias00.blogspot.com/2016/05/pyserialrts.html
time.sleep(3)
シリアルポートのデータ送信
PC側ソフトが"SerialStart\r\n"を送信するところから、マイコン側との通信が始まる。
encode()関数で文字列からバイト列に変更したのち、pySerialのserial.Serial.write()関数で送信する。
pySerialのserial.Serial.flush()関数で、書き込みの終了を待つ。
# データ送信
data = "SerialStart\r\n"
ser.write(data.encode())
ser.flush() # 書き込み終わり待ち
シリアルポートのデータ受信
pySerialのserial.Serial.readline()関数で1行分を読んだものを、decode()関数でバイト列からUTF-8に変換する。
# データ受信
strbuf = ""
while True:
if ser != "":
strbuf += ser.readline().decode("utf8") # read()であると1バイトずつしか読みださない。readlineで改行まで読む。
if len(strbuf) >= 14 and "SerialFinish" in strbuf:
break
シリアルポートのクローズ
"SerialFinish"という文字列が受信した文字列に含まれている場合、シリアルポートを閉じる。
pySerialのserial.Serial.close()関数で、シリアルポートをクローズする。
ser.close()
補足
USBをPCにつなげてソースを実行するとエラーが出るが、一度今回解説したソースで実行した後だと正常に実行できるpyWin32版のソースは以下にアップロードした。
エラーは以下のものが出る。
pywintypes.error: (121, 'WriteFile', 'セマフォがタイムアウトしました。')
前回(2-2-2. 回路設計 - 回路の実装(PWM平滑化以外))
次回(3-2. PC側ソフト設計 - Matplotlibでのグラフ表示)
他の回
「ダイオードI-V特性測定器作成 連載記事」でタグ付けを行っている。
広告
今回は関係がないが、相対的にRS232Cの通信で問題が起こりにくい印象のあるUSB変換ケーブル。














ディスカッション
コメント一覧
まだ、コメントがありません