【问题标题】:Reading serial input and printing to Tkinter GUI读取串行输入并打印到 Tkinter GUI
【发布时间】:2019-01-31 06:57:00
【问题描述】:

我正在尝试为 Arduino 打印传感器值制作基于 Tkinter 的 GUI,并响应用户输入。

我试图用来消除 while 循环的代码是这样的,它不打印任何传感器信息,唯一的输出是“正在尝试.../dev/ttyACM0”,然后是 tkinter 窗口打开。 导入序列号 进口时间 从 Tkinter 导入 *

connected = False
write_to_file_path = "output.txt"
output_file = open(write_to_file_path, "w+")

locations=['/dev/ttyACM0','/dev/ttyACM1','/dev/ttyACM2','/dev/ttyACM3']

for device in locations:
    try:
        print "Trying...",device
        ser = serial.Serial(device, 9600)
        break
    except:
        print "Failed to connect on",device

## loop until the arduino tells us it is ready
while not connected:
    serin = ser.read()
    connected = True

time.sleep(0.1)
ser.flushInput()
time.sleep(1)

def serialRead():
    if ser.inWaiting():
        line = ser.readline()
        data = line.decode("utf-8").split('\t')
        print(data)
        output_file.write(line)
        root.after(1000, serialRead)



root = Tk()
root.title("Temperature Control")
serialRead()
root.mainloop()

另一方面,除了没有 tkinter 窗口之外,它可以完美运行。但它会从缓冲区中删除旧输入并读入新输入。

import serial
import time

connected = False
write_to_file_path = "output.txt"
output_file = open(write_to_file_path, "w+")

serial_port = '/dev/ttyACM0'
baud_rate = 9600
ser = serial.Serial(serial_port, baud_rate, timeout=5)
time.sleep(0.1)
ser.flushInput()
time.sleep(1)

while True:
    if ser.inWaiting():
        line = ser.readline()
        data = line.decode("utf-8").split('\t') #ser.readline returns a binary, convert to string
        print data[0] + '\t' + data[1]
        output_file.write(line)

这是受到不久前另一篇 stackoverflow 帖子的启发:Run an infinite loop in the backgroung in Tkinter

我见过一些使用线程的例子,但我对 python 和线程都不太了解,所以如果可能的话,我真的很想让它与 root.after() 一起工作。我还尝试了使用 root.after 的示例,所有这些都与我链接的那个非常相似,但我无法让它们中的任何一个工作。我是否在做任何明显错误的事情,或者以一种比需要的方式更困难的方式?如果有人能指出我正确的方向,我将不胜感激。

【问题讨论】:

  • ser = serial.Serial(device, 9600, timeout=5) 可能会解决你的问题......我的猜测是树莓派正在打开 AMA0 端口(它的 GPIO 端口),因为没有什么可读的......read() 只是永远挂起等待不会到来的字节......顺便说一句,你会想要使用线程......当然
  • Arduino 每隔 100 毫秒就会发送一次数据,所以肯定有一些东西可以阅读。刚刚尝试了修改,并没有什么不同。为什么需要线程?这个 gui 只需要读取数据并偶尔发送一个字节,所以我认为最大化计算效率不是超级关键?
  • 因为如果你在主线程中,当你做查询时它会阻塞......而且感觉不对......
  • 好的,我会尝试看看我是否可以通过线程来解决这个问题。谢谢
  • 它可能很好的概念证明来开玩笑让它工作......但你会希望尽快将连续的东西放在自己的线程中

标签: python python-2.7 tkinter


【解决方案1】:

我在 TK 中创建了一个 UI,用于从 GPS 接收器读取数据,但我很难让 root.mainloop() 运行,因此我在 TK 应用程序中放置了一个回调,最终调用 root.update() 而不是主循环。

代码如下所示:

class App:

def __init__(self, master):
    self.sats = tk.StringVar()
    self.satsnum = tk.Label(self.frame, textvariable=self.sats, bg="blue")
    self.satsnum.pack()

def update_display(self, master):

    while source:

        self.sats.set(n_sats)

        if n_sats < 10:
            satsbgcolor = 'red'
        else:
            satsbgcolor = 'green'
        self.satsnum.configure(bg = satsbgcolor)

        master.update()
        time.sleep(1)


with serial_link.get_base_args_driver(args) as driver:
    with Handler(Framer(driver.read, driver.write, verbose=True)) as source:
        root = tk.Tk()
        app = App(root)
        app.update_display(root)

注意,在 MacOS 上 time.sleep(1) 是必需的,因为如果更新调用太快, tk.update() 会泄漏内存。

【讨论】:

    猜你喜欢
    • 2021-08-27
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多