Python 串行读定时器

Python Serial Read Timer

所以我正在读取一个每隔几秒发送一次数据的串行设备,我的计时器 运行 在屏幕上,目标是每次它更新串行读取时都会将计时器重新启动为零。 . 这让我可以直观地看到我是否与设备失去联系。我花了很多时间搜索无济于事。 python 不太好,所以任何帮助将不胜感激。

from tkinter import *
from serial import Serial
import time
from serial.threaded import ReaderThread, Protocol
import threading
import tkinter as tk

 
#Input ED Number
ed_num = 0
def tkinter_input(prompt=""):
    global ed_num
    root = tk.Tk()
    root.wm_attributes('-fullscreen',1)  
    root.configure(background='black')
    tk.Label(root, font=('Ariel', 100), foreground='Green',
                    background='Black', text=prompt).pack()
    entry = tk.Entry(root, font=('Ariel', 100),justify='center', foreground='Black',
                    background='white')
    entry.focus()
    entry.pack()
    result = None
    def callback(event):
        nonlocal result
        result = entry.get()
        root.destroy()
    entry.bind("<Return>", callback)
    root.mainloop()
    return result
result = tkinter_input("Scan Dosimeter")
ed_num = result
print(ed_num)


#Start Loop
root = Tk()

#Sets Main Window
root.wm_attributes('-fullscreen',1)  
root.configure(background='black')

'''Shuts Down App will need to remove'''
button_quit = Button(root, text = 'QUIT', command = root.destroy).pack(anchor=NE)

#Container Frame
mainframe= Frame(root, bd=4, bg='Black') 
mainframe.pack(anchor=CENTER, expand=True, fill=BOTH, padx=(20,20), pady=(20,20))
mainframe.grid_columnconfigure(0, weight=1)
mainframe.grid_rowconfigure(0, weight=1)
mainframe.grid_rowconfigure(1, weight=1)
mainframe.grid_rowconfigure(2, weight=1)

#ID Label
ed_id_label = Label(mainframe, 
                    font=('Ariel', 50), foreground='Green',
                    background='Black', anchor='w')
ed_id_label.grid(row=0, column=0, sticky='ew', padx=(100,100), pady=(100,100))

#Dose Label
doselabel = Label(mainframe,  
                  font=('Ariel', 130), foreground='Green',
                  background='Black', anchor='w')
doselabel.grid(row=1, column=0, sticky='ew', padx=(100,100), pady=(100,100))

# Rate Label
ratelabel = Label(mainframe,  
                  font=('Ariel', 130), foreground='Green',
                  background='Black', anchor='w')
ratelabel.grid(row=2, column=0, sticky='ew', padx=(100,100), pady=(100,100))

#Timer Label
timelabel = Label(mainframe,
                  font=('Ariel', 20), foreground='Green',
                  background='Black', anchor='w')
timelabel.grid(row=3, column=0, sticky='se')

#Data Timer
seconds = 0
def countup(seconds):
    seconds += 1
    timelabel['text'] = str(seconds)+"s"
    root.after(1000, countup, seconds)

#Serial Reader Thread
class SerialReaderProtocolRaw(Protocol):
    
    def data_received(self, data):
        """Called with snippets received from the serial port"""
        updateLabelData(data)

def updateLabelData(data):
    data = data.decode("utf-8")
    if data[0:6] == ed_num:
        ed_id_label['text']='Ed id:   ' +data[0:6]
        doselabel['text']='Dose:   ' + data[11:14]+'.'+data[14:15]
        if data[21:22] == '0':
            ratelabel['text']='Rate:    ' + data[18:19]
        if data[21:22] == '1':
            ratelabel['text']='Rate:    ' + data[18:20]
        if data[21:22] == '2':
            ratelabel['text']='Rate:    ' + data[18:21]
        if data[21:22] == '3':
            ratelabel['text']='Rate:    ' + data[18:22]
        if data[6:7] =='1':
            doselabel.config(bg= "red")
        if data[6:7] =='2':
            ratelabel.config(bg= "red")
        root.update_idletasks()
   
# Initiate serial port
serial_port = Serial('COM3', baudrate = 57600)

# Initiate ReaderThread
reader = ReaderThread(serial_port, SerialReaderProtocolRaw)
# Initiate Counter Thread
countupthread = threading.Thread(target=countup, args = (seconds,))

# Start reader/counter
countupthread.start()
reader.start()
# Join Threads
countupthread.join()

root.after(1, countup, seconds)
root.mainloop()

我脑海中至少能想到两种解决方案:取消并重新启动计数器,或者使 seconds 全局化。

停止并重新启动计数器

当您使用 after 安排某事时,它 returns 是一个标识符。您可以将此标识符传递给 after_cancel 以防止该函数来自 运行。由于您没有使用 类,您可以使用全局变量来跟踪此标识符。

示例:

def countup(seconds):
    global after_id
    seconds += 1
    timelabel['text'] = str(seconds)+"s"
    after_id = root.after(1000, countup, seconds)

然后,每当您需要重置计时器时,您可以使用以下两行来取消并重新启动 countup:

root.after_cancel(after_id)
countup(0)

使seconds成为全球

与其将 seconds 传递给 countup 函数,不如让它使用全局变量。然后,您可以随时重置此变量。

seconds = 0
def countup():
    global seconds
    seconds += 1
    timelabel['text'] = str(seconds)+"s"
    after_id = root.after(1000, countup, seconds)

有了这个,只要你想重置计数器,你只需要重置 seconds:

global seconds
seconds = 0