我将完整的代码放在下面,因为我实际上不确定问题出在哪里,但我可以将您的注意力转移到 def read_analog() ,因为根据出现的问题,这是最有可能的位置。
目标是使用 ardunio 模拟引脚读取 0-5 v DC 电压,使用 read_analog() 每 2 秒读取串行端口并打印该值。 .after 方法应用了 2000 毫秒的等待,以便“释放”代码以执行函数之外的任何其他操作,因为我还向操作硬件发送数据。由于某种原因, read_analog() 函数仅在第一次迭代时从串行读取值。此后,它只是每两秒重复一次相同的值(可能会变化 1),并且不会响应输入电压的变化。我确实确认了 PC 通过串行正确接收了这些位,所以这是一个 python 代码问题。奇怪的是,如果我在 .after 方法中使用“read_analog()”而不是“read_analog”,它将不停循环但是它确实报告了正确的更新值。
有什么想法吗?
谢谢!
import serial
import time
import tkinter
import customtkinter
from PIL import ImageTk, Image
from tkinter import ttk
from pynput import keyboard
import tk_tools
step = 0
def quit_button():
global tkTop
ser.write(bytes('K', 'UTF-8'))
tkTop.destroy()
def on_button():
varLabel.set("LED ON ")
ser.write(bytes('H', 'UTF-8'))
def off_button():
varLabel.set("LED OFF")
ser.write(bytes('K', 'UTF-8'))
def l_button():
varLabel.set("Rotate Left")
ser.write(bytes('L', 'UTF-8'))
global step
step = step - 1
progressbar.step(step)
p.set_value(step)
print("Step",step)
#varLabel.set("LED OFF")
ser.write(bytes('K', 'UTF-8'))
def r_button():
varLabel.set("Rotate Right")
ser.write(bytes('R', 'UTF-8'))
global step
step = step + 1
progressbar.step(step)
p.set_value(step)
print("Step",step)
#varLabel.set("LED OFF")
ser.write(bytes('K', 'UTF-8'))
def on_press(key):
if key == keyboard.Key.right:
r_button()
if key == keyboard.Key.left:
l_button()
def read_analog():
value = ser.readline().decode()
value = value.rstrip('\r\n') # Remove carriage return
#valueint = int(float((value)))
print('Voltage', value, ' volts')
tkTop.after( 2000, read_analog) # period depends on how frequent the arduino writes data to its serial port
listener = keyboard.Listener(
on_press=on_press)
listener.start()
#change the COM port below
ser = serial.Serial('COM10', 9600, timeout=0.1)
print("Reset Arduino")
time.sleep(2)
ser.write(bytes('K', 'UTF-8'))
tkTop = tkinter.Tk()
tkTop.geometry('400x400') #500 x 500 window
tkTop.title("LED control") #name in title bar
# Create a parent frame
parent_frame = tkinter.Frame(tkTop)
parent_frame.pack()
tkTop.after( 2000, read_analog()) # period depends on how frequent the arduino writes data to its serial port
#define button images
upimage = ImageTk.PhotoImage(Image.open('voltup.png').resize((60,60)))
downimage = ImageTk.PhotoImage(Image.open('voltdown.png').resize((60,60)))
#label to display the status
varLabel = tkinter.IntVar()
tkLabel = tkinter.Label(textvariable=varLabel, )
varLabel.set("LED STATUS")
tkLabel.pack()
#label for HV controls
HVlabel = tkinter.Label(text= "HV Control")
HVlabel.place(x=300, y=40),
#button1 - ON
button1 = tkinter.IntVar()
button1state = tkinter.Button(tkTop,
text="ON",
command=on_button,
height = 4,
width = 8,
bg = 'green'
)
button1state.pack(side='top', ipadx=10, padx=10, pady=15)
#button2 - OFF
button2 = tkinter.IntVar()
button2state = tkinter.Button(tkTop,
text="OFF",
command=off_button,
height = 4,
width = 8,
)
button2state.pack(side='top', ipadx=10, padx=10, pady=15)
#button3 - Rotate Right
button3 = tkinter.IntVar()
button3state = tkinter.Button(tkTop,
text="Rotate Right",
command=r_button,
height = 60,
width = 60,
image = upimage
)
button3state.place(x=300, y=60)
#button4 - Rotate Left
button4 = tkinter.IntVar()
button4state = tkinter.Button(tkTop,
text="Rotate Left",
command=l_button,
height = 60,
width = 60,
image = downimage
)
button4state.place(x=300, y=180)
#Quit button
tkButtonQuit = tkinter.Button(
tkTop,
text="Quit",
command=quit_button,
height = 4,
width = 8,
)
p = tk_tools.RotaryScale(tkTop, max_value = 60, unit = "step")
p.place(x=300, y =300)
#print("step",step)
tkTop.title("Progress Bar in Tk")
progressbar = ttk.Progressbar(maximum=1500)
progressbar.place(x=400, y=60, width=160)
tkButtonQuit.pack(side='top', ipadx=10, padx=10, pady=15)
tkinter.mainloop()
建议创建
Serial
实例而不设置timeout
选项。 然后使用ser.in_waiting检查是否有数据可供读取。
...
ser = serial.Serial('COM10', 9600) # don't set timeout option
...
def read_analog():
if ser.in_waiting > 5: # size of (value + newline), change it to suit your case
value = ser.readline().decode().rstrip()
print(f'Voltage: {value} volts')
tkTop.after(1000, read_analog) # period depends on how frequent the arduino writes data to its serial port
read_analog() # start the after loop
...