【问题标题】:Setting up the serial object from a function (called from tkinter interaction)从函数设置串行对象(从 tkinter 交互调用)
【发布时间】:2021-03-06 21:37:32
【问题描述】:

我设法让我的 tkinter 应用程序在文本字段上显示文本。

我通过硬编码 COM 端口和波特率来做到这一点,然后在我的程序开始时设置一个串行对象。

baudRate = 9600
ser = serial.Serial('COM16', baudRate)

然后我的所有代码都会运行。

但问题在于所有内容都是硬编码的。 我希望用户能够从下拉列表中选择 COM 端口。 当他选择一个端口时,串行通信应该开始了。

所以我就是这样做的。这是我的相关代码。

#hardcoded baud rate
baudRate = 9600

# this is the global variable that will hold the serial object value
ser = 0 #initial  value. will change at 'on_select()'

#this function populates the dropdown on frame1, with all the serial ports of the system
def serial_ports():    
    return serial.tools.list_ports.comports()

#when the user selects one serial port from the dropdown, this function will execute
def on_select(event=None):
    global ser
    COMPort = cb.get()
    string_separator = "-"
    COMPort = COMPort.split(string_separator, 1)[0] #remove everything after '-' character
    COMPort = COMPort[:-1] #remove last character of the string (which is a space)
    ser = serial.Serial(port = COMPort, baudrate=9600)
    return ser
    readSerial() #start reading

#this function reads the incoming data and inserts them into a text frame
def readSerial():
    ser_bytes = ser.readline()
    ser_bytes = ser_bytes.decode("utf-8")
    text.insert("end", ser_bytes)
    if vsb.get()[1]==1.0:
       text.see("end")
    root.after(100, readSerial)

当我从下拉列表中选择一个 COM 端口时会发生什么,我在设备的 LED 按钮上看到了传输。

但是,文本框架上没有显示任何内容。之前,当我对所有内容进行硬编码并在程序开始时设置串行对象,并在程序结束时声明readSerial() 函数时,一切正常。

【问题讨论】:

    标签: python-3.x tkinter serial-port pyserial


    【解决方案1】:

    在您的on_select 函数中,您在调用readSerial() 函数之前调用了returnreturn 语句终止函数的执行,它后面的任何语句都不会被执行。删除它会使程序正常工作。

    另外,由于on_select 是下拉列表的回调,return 语句是多余的,因为它没有任何地方可以返回。 global ser 负责将新值全局分配给 ser 变量。

    您无需在每次选择新选项时调用readSerial() 函数(否则,每次都会增加预定调用次数)。您可以拥有一个在初始配置后调用它的按钮,然后从on_select 中删除对readSerial() 的调用,或者创建一个标志以确保它只被调用一次。


    根据您的评论,我创建了以下示例,您可以尝试这样的操作

    from tkinter import *
    
    def on_select(event):
        global value
        value=option.get()
        if stop_:
            start_button['state']='normal'
    
    def start():
        global stop_
        stop_=False
        readSerial()
        start_button['state']='disabled'
        stop_button['state']='normal'
    
    def stop():
        global stop_
        stop_=True
        root.after_cancel(after_id)
        start_button['state']='normal'
        stop_button['state']='disabled'
    
    def readSerial():
        global after_id
        text.insert(END,value)
        after_id=root.after(100,readSerial)
    
    root=Tk()
    
    text=Text(root)
    text.pack(side='bottom')
    
    options=['1','2']
    option=StringVar()
    om=OptionMenu(root,option,*options,command=on_select)
    om.pack(side='left')
    
    start_button=Button(root,text='start',command=start,state='disabled')
    start_button.pack(side='left')
    stop_button=Button(root,text='stop',command=stop,state='disabled')
    stop_button.pack(side='left')
    
    stop_=True
    
    root.mainloop()
    

    【讨论】:

    • 很好的解释
    • 我正试图弄清楚。 1.完全删除return语句。关于你的第三段......我不太明白......在我的代码中,我还必须能够停止 readSerial() 函数。因为我的 arduino 程序只会在触发时发送数据。因此,当我从 tkinter 发送 STOP TRANSMIT 命令时,我还必须停止 readSerial()。哇什么是最好的方法。也许是一个通过设置串行对象来启动串行通信的按钮。另一个按钮将启动 readSerial() 并设置一个标志,另一个按钮将发送
    • StopTransmit 命令到 arduino,但它也必须停止 readSerial(),有可能吗?
    • @user1584421 我已经用一个例子更新了答案,我相信你正在寻找类似的东西,如果有帮助,请告诉我。
    • 此代码有效吗?在 readSerial() 中,当标志 (stop_) 设置为 True 时,这两行将不会执行。所以它不会打印到文本字段。但是如果 root.after(100,readSerial) 已经启动,那么你的 readSerial() 函数将不会停止它的执行。如果已经启动,您的 readSerial() 是否还应该包含主动停止定期执行的代码?我看到 _cancel 是这样做的。所以也许readSerial()会把一个flag转成True,停止按钮会检查是否设置了True,如果是,就会调用id上的_cancel函数。
    猜你喜欢
    • 1970-01-01
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 2019-10-13
    相关资源
    最近更新 更多