不具合:シリアル通信で受信データの前半部分が欠落する。
例:
”abcdefghijklmn” + 終了文字 というデータを受信したいが
"klmn" + 終了文字 しか受信できない。
なお、送受信の基本処理はpySimpleGUIで作った画面のボタンを押すことで制御し、受信処理はスレッドで回している。
serial.py
import PySimpleGUI as sg
import serial
import time
import threading
Ser = None #シリアルポート
def open_port(s_port):
ser = serial.Serial()
ser.baudrate = 9600
ser.timeout = 0 # 読み取りタイムアウトの時間 0:即座にタイムアウト
ser.parity = serial.PARITY_NONE
ser.bytesize = serial.EIGHTBITS
ser.stopbits = serial.STOPBITS_ONE
ser.xonxoff = False
ser.port = 'COM' + s_port
# 開いてみる
try:
ser.open()
return ser
except:
messagebox.showerror('エラー', 'エラー:ポートが開けませんでした。')
return None
tm_wait_rx = 0 #受信待ちタイマー
#送信処理
def Tx(ser):
global tm_wait_rx
Tx_Data = 送りたい文字列データ
if ser.isOpen() == True:
ser.write(Tx_Data.encode('ascii'))
ser.flush() #送信するまで待機
tm_wait_rx = 1000 #受信待ちタイマー1000ミリ秒
#受信処理
def Rx_Proc(ser):
global tm_wait_rx
global End_Mark #'通信の終了文字
if ser == None:
return
elif ser.isOpen() == True:
line = ''
while ser.isOpen() == True:
try:
r = ser.read(1) #1バイトずつ読む
if r == b'':
return
line += r.decode('ascii')
if r.decode('ascii') == End_Mark:
このへんで受信データ line を処理
break
except:
messagebox.showerror('エラー', 'エラー:受信処理に異常')
break
tm_wait_rx = 0 #受信待ちタイマーをクリア
else:
return
#受信処理をスレッドでまわす
def Rx_Proc_th():
global Ser
global tm_wait_rx
while True:
Rx_Proc(Ser)
time.sleep(0.001)
if tm_wait_rx > 0:
tm_wait_rx -= 1 #受信待ちタイマーを0.001秒ごとに減算
layout = ここで画面パーツを定義する
window = sg.Window('シリアル通信テスト', layout, return_keyboard_events=True, enable_close_attempted_event=False)
thread2 = threading.Thread(target=Rx_Proc_th, )
thread2.start()
#ループで送信ボタンが押されるのを待つ
while True:
event, values = window.read(timeout=50) #画面イベントを待つ
if tm_wait_rx > 0: #受信待ち中は何もしない
continue
elif event == 'com_open':
Ser = open_port(1)
elif event == '送信':
Tx(Ser) #データ送信
解決?方法
1.画面イベント待ちのタイムアウトを短くした。←これは関係ないっぽい
serial.py
#ループで送信ボタンが押されるのを待つ
while True:
event, values = window.read(timeout=1) #画面イベントを待つ タイムアウト1ms
2.念のためシリアルポートの受信タイムアウトを長くした。←多分これが正解
serial.py
def open_port(s_port):
ser = serial.Serial()
ser.baudrate = 9600
ser.timeout = 0.1 # 読み取りタイムアウトの時間 100ms
ser.parity = serial.PARITY_NONE
ser.bytesize = serial.EIGHTBITS
ser.stopbits = serial.STOPBITS_ONE
ser.xonxoff = False
ser.port = 'COM' + s_port
受信タイムアウトが短すぎるのが原因のようです。
ただ、なぜ受信データの先頭部分だけが欠落するのか謎・・・