ダイオードI-V特性測定器作成:3-1. PC側ソフト設計 – pySerialでUSBシリアル通信

2025年8月31日

Google Ad

本記事の主旨

ダイオードI-V特性測定器(カーブトレーサ)作成のPC側ソフト上におけるpySerialでのUSBシリアル通信について記す。

本記事の目的

本記事の目的を以下に記す。

  • pySerialで作成したUSBシリアル通信のソースについての解説を記すこと

本記事の背景

ダイオードI-V特性測定器(カーブトレーサ)作成の中でPC側ソフトを作成したため、本記事でその部分的な解説をする。

本記事の位置づけ

以下の流れで作業説明と解説を行った。

記事に対応したリンクを添付した。

概要説明:ダイオードI-V特性測定器作成:0. 概要 | 工事中.com

  1. 取扱説明
  2. 回路設計
    1. ダイオードのI-V特性を手作業で確認
    2. 回路の実装
      1. 回路の実装(PWM平滑化)
      2. 回路の実装(PWM平滑化以外)
  3. PC側ソフト設計
    1. pySerialでUSBシリアル通信★現在のページ
    2. Matplotlibでのグラフ表示
    3. Pythonで最小二乗法の指数関数近似
    4. openpyxlでグラフ描画と最小二乗法の指数関数近似
  4. マイコン側ソフト設計
    1. Arduino Uno Rev3 / R4 Minima
    2. Raspberry Pi Pico / Pico 2
  5. 実験
    1. 1N4148の測定でマイコンとソースの組み合わせを比較
    2. 種々のダイオードを測定
    3. 種々の高精度ゲルマニウムダイオードを測定
  6. まとめと補足

コードの全体

今回解説するコードの全体は、以下にアップロードした。

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変換ケーブル。

広告