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
所以我正在读取一个每隔几秒发送一次数据的串行设备,我的计时器 运行 在屏幕上,目标是每次它更新串行读取时都会将计时器重新启动为零。 . 这让我可以直观地看到我是否与设备失去联系。我花了很多时间搜索无济于事。 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