如何为pyserial读取运行线程

Posted

技术标签:

【中文标题】如何为pyserial读取运行线程【英文标题】:how to run thread for pyserial read 【发布时间】:2021-01-31 13:35:13 【问题描述】:

我正在尝试创建一个 python 接口来向 arduino 发送帧并从 arduino 接收 can 帧并显示它。对于发送数据它工作正常,但对于接收我有点困惑如何处理它。 我试图创建一个在串行 com 建立后将启动的线程。 我有 2 个问题: 1 /它是创建线程的正确方法吗? 2/ 断开串行连接后如何停止线程运行 here's my GUI with an example of receiving random value from arduino

from tkinter import* 
from tkinter import  filedialog, Label, Entry, LabelFrame, Button, Tk
from tkinter import ttk
from db_class import up
import serial_tx_rx
from tkinter import messagebox
from diagservices import diag_services
import threading
import serial
import tkinter.scrolledtext as tkscrolledtext

class MainWindow():
    def __init__(self, master):
        self.master = master
        self.title = self.master.title("CanSim")
        self.size = self.master.geometry('950x200')
        self.baudrate = 9600
        self.com_port = ['COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'COM10']
        self.isopen = False
        self.receivedMessage = None
        self.stop_thread = False
        self.bConnect = ttk.Button(self.master, text="Connect", command = self.connectSerial)
        self.bConnect.place(x=750, y=7)
        self.bDisconnect = ttk.Button(self.master, text="Disconnect", command= self.disconnectSerial)
        self.bDisconnect.place(x=750, y=30)
        self.com_portCmb = ttk.Combobox(self.master, width=8, values =self.com_port )
        self.com_portCmb.place(x=830, y=7)
        self.Frame = Frame(self.master, bg= 'cyan')
        self.Frame.place(x=10, y=30)
        self.comStatusLabel = Label(master, text= "Disconnected ", font=("Helvetica", 8, "normal", "italic"))
        self.comStatusLabel.place(x=830, y=33)
        self.textbox = tkscrolledtext.ScrolledText(self.Frame, wrap='word',font=2, width=55, height=8) 
        self.textbox.pack(side='bottom', fill='y', expand=True, padx=0, pady=0)
        self.textbox.config(font="bold")
        self.textbox.yview_pickplace("end")

    def connectSerial(self):
        try:
            self.ser = serial.Serial(self.com_portCmb.get(), self.baudrate)
            self.comStatusLabel["text"] = "Connected"
            self.isopen =True
            self.t1 = threading.Thread(target=self.readSerial)
            self.t1.start()
        except:
            messagebox.showerror("Error : Invalid COM ", "Fail to establish connection with the selected COM Port" )

    def disconnectSerial(self):
        self.t1.daemon()
        self.ser.close()
        self.comStatusLabel["text"] = "Disconnected"

    def readSerial(self):
        if self.isopen:
            self.received_data = self.ser.read(2)
            self.textbox.insert(END, str(self.received_data)+"\n")
            print(self.received_data)
            self.textbox.after(100, self.readSerial)

if __name__ == "__main__":
    root = Tk()
    ex = MainWindow(root)
    root.mainloop()

【问题讨论】:

【参考方案1】:

您不应在线程任务 (readSerial()) 中使用 .after(),而应使用 while 循环:

class MainWindow():
    def __init__(self, master):
        self.master = master
        self.title = self.master.title("CanSim")
        self.size = self.master.geometry('950x200')
        self.ser = None
        ...

    def disconnectSerial(self):
        if self.ser and self.ser.is_open:
            #self.t1.daemon()  # daemon is an attribute, not function
            self.ser.close()
            self.comStatusLabel["text"] = "Disconnected"

    def readSerial(self):
        while self.ser.is_open:
            self.received_data = self.ser.read(2)
            self.textbox.insert(END, str(self.received_data)+"\n")
            print(self.received_data)

【讨论】:

以上是关于如何为pyserial读取运行线程的主要内容,如果未能解决你的问题,请参考以下文章

在另一个线程中中断 pySerial readline

Pyserial readline() 永远挂起程序而不读取串行数据

PySerial 丢失数据

PySerial 读取问题

pyqt4 和 pyserial

pySerial:端口只工作第一个命令