Pythonを使用してシリアル通信を行うためのサンプルプログラム(hdlSerial)とGUIとの連携例
シリアル通信を行う場合、TeraTermなどの汎用ターミナルソフトや一部弊社製品に付属している専用のアプリケーションを用いて行うことも可能ですが、ここではPythonを用いてヒューマンデータ製品と接続・通信するプログラムをGUIで表示する簡単なサンプルをご紹介します。
以下のPythonプログラムは、GUIを用いてシリアル通信の送受信を確認するサンプルプログラムです。
本プログラムを含め、3つのPythonプログラムで構成されています。1つ目は、iniファイルの設定を基づき接続可能なCOMポートを検索するプログラム、2つ目は、シリアル通信の接続・送受信・切断を行うプログラム(これについては別記事「Pythonによるシリアル通信サンプルプログラム(hdlSerial)」でご紹介しています)、3つ目はそれらの通信をGUIで表示するための本プログラムです。
GUIの実装はPython標準ライブラリのtkinterを使用しています。シリアル通信にはシリアルポートを介した送受信の実装に便利なオープンソースライブラリであるPySerialを利用しています。PySerialは標準ライブラリには含まれないため、別途Pythonへのインストールが必要です。
# HuMANDATA LTD. hdlSerial_GUI_v10.py
import tkinter as tk
from tkinter import scrolledtext
from tkinter import font
from hdlSerial_Config_v10 import hdlCfgMgr
from hdlSerial_v21 import hdlSerialComm
from datetime import datetime
import os
class hdlSerialGUI:
def __init__(self, root, entry_TXT, area_RX, area_LOG):
self.root = root
self.entry = entry_TXT
self.textarea = area_RX
self.log = area_LOG
try:
hdlCfg = hdlCfgMgr.load_config(ini_path="hdlSerial.ini", ini_callback=self.on_log)
hdlPort = hdlCfgMgr.search_port(
com_num=hdlCfg["com"],
com_desc=hdlCfg["description"],
port_callback=self.on_log # 受信データを受信表示に渡す
)
self.serial = hdlSerialComm(
port=hdlPort,
baudrate=hdlCfg["baudrate"],
eol_tx=hdlCfg["eol_tx"],
eol_rx=hdlCfg["eol_rx"],
encoding=hdlCfg["encode_charset"],
callback=self.on_receive, # 受信データを受信表示に渡す
log_callback=self.on_log # ログデータをログ表示に渡す
)
if not self.serial.open():
self.on_log("Error: Open Serial Port")
self.serial = None
except Exception as e:
self.on_log(f"Error: Initial Configuration, {e}")
self.serial = None
def on_receive(self, data):
self.root.after(0, self.update_text, data)
def on_log(self, data):
self.root.after(0, self.write_log, data)
def write_log(self, data):
now = datetime.now()
timestamp = f"[{now:%Y/%m/%d %H:%M:%S}.{now.microsecond // 1000:03d}] "
self.log.insert(tk.END, timestamp+data+"\n")
def send_text(self, data):
self.serial.sendData(data)
self.on_log("TX: "+data)
def update_text(self, data):
self.textarea.insert(tk.END, data+"\n")
self.on_log("RX: "+data)
def main():
root = tk.Tk()
root.title("HuMANDATA HdlSerial_GUI v1.0")
icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "hdlpyicon.gif")
icon = tk.PhotoImage(file=icon_path)
root.iconphoto(True, icon)
root.geometry("500x500")
text_font = font.Font(size=11)
frame1 = tk.Frame(root)
frame1.pack(fill=tk.X, padx=5, pady=5)
tk.Label(frame1, text="送信データ :").pack(side=tk.LEFT)
entry_TXT = tk.Entry(frame1, font=text_font)
entry_TXT.pack(side=tk.LEFT, padx=10, fill=tk.X, expand=True)
tk.Label(root, text="受信データ :").pack(anchor="w", padx=5)
area_RX = scrolledtext.ScrolledText(root, width=50, height=12, font=text_font)
area_RX.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
area_LOG = scrolledtext.ScrolledText(root, width=50, height=9, font=text_font)
area_LOG.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
serial_Mgr = hdlSerialGUI(root, entry_TXT, area_RX, area_LOG)
if serial_Mgr.serial is None:
print("End: Valid COM Port not found")
root.destroy() # GUIを閉じる
return # main()終了
serial_Mgr.serial.start()
tk.Button(
frame1, text="送信", width=10, command=lambda: serial_Mgr.send_text(entry_TXT.get())
).pack(side=tk.RIGHT)
def on_close():
if serial_Mgr.serial:
serial_Mgr.serial.close()
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_close)
root.mainloop()
if __name__ == "__main__":
main()
# HuMANDATA LTD. hdlSerial_Config_v10.py
import os
import sys
import configparser
import serial
import serial.tools.list_ports
class hdlCfgMgr:
@staticmethod
def _notify(callback, message):
if callback:
callback(message)
else:
print(message)
@staticmethod
def load_config(ini_path="hdlSerial.ini", ini_callback=None): # デフォルト値設定とiniファイルから設定読込
config_values = {
"baudrate": 9600,
"eol_tx": "CR",
"eol_rx": "CR",
"encode_charset": "utf-8",
}
ini_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), ini_path)
if os.path.isfile(ini_file):
config = configparser.ConfigParser()
config.read(ini_file, encoding="utf-8-sig")
config_values.update(config["DEFAULT"])
hdlCfgMgr._notify(ini_callback, "Set Configuration from ini file")
else:
hdlCfgMgr._notify(ini_callback, "ini file not Found")
return config_values
@staticmethod
def search_port(com_num="", com_desc="", port_callback=None): # COMポートの検索
ports = serial.tools.list_ports.comports()
for p in ports:
if com_num and p.device == com_num: # COM番号一致
hdlCfgMgr._notify(port_callback, "Port Detected by COM Name, "+p.device)
return p.device
if com_desc and p.description and com_desc in p.description: # description一致
hdlCfgMgr._notify(port_callback, "Port Detected by Description, "+p.description)
return p.device
if p.manufacturer and 'HuMANDATA' in p.manufacturer: # HuMANDATA製品
hdlCfgMgr._notify(port_callback, "Port Detected by Manufacturer, "+p.manufacturer)
return p.device
hdlCfgMgr._notify(port_callback, "Error: Valid port not found")
return None
- Pythonプログラムの実行には、あらかじめPython実行環境のインストールが必要です。
- 本プログラムは、Pythonバージョン3.11.9で作成・確認しております。バージョンが異なる場合の動作については未確認です。
ターミナルなどから「hdlSerial_GUI_v10.py」を実行すると以下のGUIが開きます。
接続先は例としてUSB-045A(2CH 独立絶縁型 USB 4-20mA 電流モニタ)を使用しております。
- 初めにiniファイルの設定情報を基にCOMポートを検索・接続します。iniファイルがない場合はhdlSerial_Config_v10.py内で指定されたデフォルト値を使用します。検索は設定されたCOM番号、description、manufacturerの順で行い、いずれかに一致したCOMポートに接続を試みます。
- 上記の実行例では、シリアル通信開始後に送信データに「CST,1」を入力し、送信ボタンを押してデータを送信しています。(「CST」はUSB-045Aの接続確認コマンド)
- データを受信すると受信データの欄にデータに表示されます。
- 有効なCOMポートが見つからず、オープンできない場合はGUIは表示されず「End: Valid COM Port not found」が返ります。
- 接続などのステータスや送受信データなどのログは、受信データの下の欄に時刻付きで表示されます。
この他、一例として、USB-003、USB-010、USB-045VなどのCOMポート使用してシリアル通信を行う製品とも同様に接続、通信の確認が可能です。接続・通信時にはそれぞれの製品、環境に応じてCOM番号やシリアル通信の設定の変更が必要になる場合があります。
詳しくは各製品ページやマニュアルをご参照ください。
本プログラムをご利用いただくにあたり、以下の点についてあらかじめご確認ください。
- 掲載するプログラムは、あくまで弊社製品をご活用いただくための例としてご紹介するものであり、推奨するプログラムということではありません。
- 十分注意して作成しておりますが、意図せずバグやエラーなどを含む可能性があります。
- プログラムの使用に起因するトラブルにつきましては補償対象外となります。
- ご使用前に必ず使用者の責任にて、十分検証の上ご利用ください。
- 使用されているモジュールなどのライセンスについては、使用範囲に応じてご自身でお確かめください。
ご不明な点や間違い、バグなどありましたらご連絡ください。ご自身の環境に合わせて改良するなど、自由に改変してご活用くださると幸いです。
開発環境の使い方やプログラムの具体的な内容などについては、サポート外となりますのであらかじめご了承ください。
[kw] 2026-02-24 USB シリアル通信 Python GUI プログラム ターミナル TEC-FA
[ ]



