LoginSignup
0
2

pySerial :シリアル通信で受信データの前半部分が欠落するのでやってみたこと

Last updated at Posted at 2024-05-24

不具合:シリアル通信で受信データの前半部分が欠落する。

例:
”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

受信タイムアウトが短すぎるのが原因のようです。
ただ、なぜ受信データの先頭部分だけが欠落するのか謎・・・

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2