serail.readline() 在使用 arduino/pc 测量电压时不使用 .after() 方法更新值

问题描述 投票:0回答:1

我将完整的代码放在下面,因为我实际上不确定问题出在哪里,但我可以将您的注意力转移到 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()
python tkinter arduino
1个回答
0
投票

建议创建

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

...
© www.soinside.com 2019 - 2024. All rights reserved.