Python 函数在后台连续运行,以无阻塞地收集实例变量的数据

Python 函数在后台连续运行,以无阻塞地收集实例变量的数据,python,tkinter,subprocess,multiprocessing,pyserial,Python,Tkinter,Subprocess,Multiprocessing,Pyserial,问题: 如何从串行端口读取数据而不阻塞GUI其余部分中发生的操作 当前问题: 我有一个GUI,它不能在我需要的时间内执行所有任务。我需要读取数据->存储传入数据(在文件、列表中,无所谓)->显示一些最新的数据点~50个不同变量->检查GUI中的任何更改,所有这些都在0.05秒内完成 我尝试过的方法:(我可能做得不正确,也许这就是它不起作用的原因) 为不同的功能使用计时器:仍然太慢 读取数据块:仍然太慢 每隔一点都会发出咕噜声:还是太慢了 线程到读取缓冲区:读取不完整(不确定我是否正确执行了此操作

问题: 如何从串行端口读取数据而不阻塞GUI其余部分中发生的操作

当前问题: 我有一个GUI,它不能在我需要的时间内执行所有任务。我需要读取数据->存储传入数据(在文件、列表中,无所谓)->显示一些最新的数据点~50个不同变量->检查GUI中的任何更改,所有这些都在0.05秒内完成

我尝试过的方法:(我可能做得不正确,也许这就是它不起作用的原因)

为不同的功能使用计时器:仍然太慢

读取数据块:仍然太慢

每隔一点都会发出咕噜声:还是太慢了

线程到读取缓冲区:读取不完整(不确定我是否正确执行了此操作,但似乎是一个好方法,希望看到如何对读取行执行此操作的示例)

多处理:无法开始工作,但似乎是最好的方法

当前正在尝试读入压缩二进制数据以减少读取时间

我收到的内容一行,包含12个变量长的整数值

int1.int2.int3 | int1,int2,int3 | int1,int2,int3 | int1,int2,int3

我在“|”处拆分这个字符串,并从每个拆分中绘制一个整数变量,并将所有变量存储在单独的列表中

我通过usb接收来自arduino的数据,arduino每50毫秒或20赫兹输出一个字符串

我遇到的主要问题是读取串行端口花费的时间太长,当它备份时会导致明显的延迟,我需要它是实时的

以下是我正在使用的GUI:

import Tkinter
import serial
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from collections import deque
import random
import time

class App:
    def __init__(self, master):
        self.arduinoData = serial.Serial('com5', 250000, timeout=None)

        frame = Tkinter.Frame(master)

        self.running = False
        self.ani = None

        self.run = Tkinter.LabelFrame(frame, text="Testing", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
        self.run.grid(row=0, column=0, padx=20, pady=20)

        self.run_respiration = Tkinter.Button(self.run, text="RUN",bd=10, height=5, width=10, command=self.getData)
        self.run_respiration.grid(row=0, column=0, padx=5, pady=5)

        self.test_options = Tkinter.LabelFrame(frame, text="Test Options", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
        self.test_options.grid(row=0, column=1, padx=20, pady=20)

        self.stop = Tkinter.Button(self.test_options, text="STOP", bd=10, height=5, width=10, command=self.stopTest)
        self.stop.grid(row=0, column=0, padx=5, pady=5)


        self.fig = plt.Figure()
        self.ax1 = self.fig.add_subplot(111)
        self.line0, = self.ax1.plot([], [], lw=2)
        self.line1, = self.ax1.plot([], [], lw=2)
        self.line2, = self.ax1.plot([], [], lw=2)
        self.line3, = self.ax1.plot([], [], lw=2)
        self.canvas = FigureCanvasTkAgg(self.fig,master=master)
        self.canvas.show()
        self.canvas.get_tk_widget().grid(row=0, column=4, padx=20, pady=20)
        frame.grid(row=0, column=0, padx=20, pady=20)

    def getData(self):
        if self.ani is None:
            self.k = 0
            self.arduinoData.flushInput()
            self.arduinoData.write("<L>")
            return self.start()
        else:
            self.arduinoData.write("<L>")
            self.arduinoData.flushInput()
            self.ani.event_source.start()
        self.running = not self.running

    def stopTest(self):
        self.arduinoData.write("<H>")
        if self.running:
            self.ani.event_source.stop()
        self.running = not self.running

    def start(self):
        self.xdata = []
        self.pressure1 = []
        self.displacement1 = []
        self.cycle1 = []
        self.pressure2 = []
        self.displacement2 = []
        self.cycle2 = []
        self.pressure3 = []
        self.displacement3 = []
        self.cycle3 = []
        self.pressure4 = []
        self.displacement4 = []
        self.cycle4 = []
        self.k = 0
        self.limit = 300
        self.arduinoData.flushInput()
        self.timer()
        self.ani = animation.FuncAnimation(
            self.fig,
            self.setData,
            interval=10,
            repeat=True)
        self.arduinoData.write("<L>")
        self.running = True
        self.ani._start()


    def readData(self):
        if (self.arduinoData.inWaiting()>0):
            self.xdata.append(self.k)
            x = self.arduinoData.readline()
            strip_data = x.strip()
            split_data = x.split("|")
            actuator1 = split_data[0].split(".")
            actuator2 = split_data[1].split(".")
            actuator3 = split_data[2].split(".")
            actuator4 = split_data[3].split(".")
            self.pressure1.append(int(actuator1[0]))
            self.displacement1.append(int(actuator1[1]))
            self.cycle1 = int(actuator1[2])
            self.pressure2.append(int(actuator2[0]))
            self.displacement2.append(int(actuator2[1]))
            self.cycle2 = int(actuator2[2])
            self.pressure3.append(int(actuator3[0]))
            self.displacement3.append(int(actuator3[1]))
            self.cycle3 = int(actuator3[2])
            self.pressure4.append(int(actuator4[0]))
            self.displacement4.append(int(actuator4[1]))
            self.cycle4 = int(actuator4[2])
            if self.k > 0:
                self.line0.set_data(self.xdata, self.pressure1)
                self.line1.set_data(self.xdata, self.pressure2)
                self.line2.set_data(self.xdata, self.pressure3)
                self.line3.set_data(self.xdata, self.pressure4)
                if self.k < 49:
                    self.ax1.set_ylim(min(self.pressure1)-1, max(self.pressure4) + 1)
                    self.ax1.set_xlim(0, self.k+1)
                elif self.k >= 49:
                    self.ax1.set_ylim(min(self.pressure1[self.k-49:self.k])-1, max(self.pressure4[self.k-49:self.k]) + 1)
                    self.ax1.set_xlim(self.xdata[self.k-49], self.xdata[self.k-1])
                if self.cycle1 >= self.limit:
                    self.running = False
                    self.ani = None
                    self.ani.event_source.stop()
                    self.running = not self.running
            self.k += 1


    def setData(self, i):
            return self.line0, self.line1, self.line2, self.line3,



    def timer(self):
        self.readData()
        root.after(1, self.timer)

root = Tkinter.Tk()
app = App(root)
root.mainloop()
导入Tkinter
导入序列号
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG
从matplotlib.figure导入图形
从matplotlib导入pyplot作为plt
将matplotlib.animation导入为动画
从集合导入deque
随机输入
导入时间
类应用程序:
定义初始(自我,主):
self.arduinoData=serial.serial('com5',250000,超时=None)
帧=Tkinter.frame(主帧)
self.running=False
self.ani=无
self.run=Tkinter.LabelFrame(frame,text=“Testing”,borderwidth=10,relief=Tkinter.GROOVE,padx=10,pady=10)
self.run.grid(行=0,列=0,padx=20,pady=20)
self.run\u呼吸=Tkinter.Button(self.run,text=“run”,bd=10,高度=5,宽度=10,命令=self.getData)
self.run\u.grid(行=0,列=0,padx=5,pady=5)
self.test_options=Tkinter.LabelFrame(frame,text=“test options”,borderwidth=10,relief=Tkinter.GROOVE,padx=10,pady=10)
self.test\u options.grid(行=0,列=1,padx=20,pady=20)
self.stop=Tkinter.Button(self.test_选项,text=“stop”,bd=10,高度=5,宽度=10,命令=self.stopTest)
self.stop.grid(行=0,列=0,padx=5,pady=5)
self.fig=plt.Figure()
self.ax1=self.fig.add_子批次(111)
self.line0,=self.ax1.plot([],[],lw=2)
self.line1,=self.ax1.plot([],[],lw=2)
self.line2,=self.ax1.plot([],[],lw=2)
self.line3,=self.ax1.plot([],[],lw=2)
self.canvas=FigureCanvasTkAgg(self.fig,master=master)
self.canvas.show()
self.canvas.get_tk_widget().grid(行=0,列=4,padx=20,pady=20)
frame.grid(行=0,列=0,padx=20,pady=20)
def getData(自):
如果self.ani为无:
self.k=0
self.arduinoData.flushInput()
self.arduinoData.write(“”)
返回self.start()
其他:
self.arduinoData.write(“”)
self.arduinoData.flushInput()
self.ani.event_source.start()
自运行=不自运行
def停止测试(自):
self.arduinoData.write(“”)
如果自动运行:
self.ani.event_source.stop()
自运行=不自运行
def启动(自):
self.xdata=[]
自压力1=[]
自位移1=[]
self.cycle1=[]
自压力2=[]
自位移2=[]
self.cycle2=[]
自压力3=[]
自位移3=[]
self.cycle3=[]
自压力4=[]
自位移4=[]
self.cycle4=[]
self.k=0
自限=300
self.arduinoData.flushInput()
self.timer()
self.ani=animation.FuncAnimation(
赛尔夫,
self.setData,
间隔=10,
重复=真)
self.arduinoData.write(“”)
self.running=True
self.ani.\u start()
def读取数据(自身):
如果(self.arduinoData.inWaiting()>0):
self.xdata.append(self.k)
x=self.arduinoData.readline()
条带数据=x.条带()
split_data=x.split(“|”)
actuator1=拆分数据[0]。拆分(“.”)
actuator2=拆分数据[1]。拆分(“.”)
actuator3=拆分数据[2]。拆分(“.”)
actuator4=拆分数据[3]。拆分(“.”)
自压力1.append(int(促动器1[0]))
self.displacement1.append(int(actuator1[1]))
self.cycle1=int(执行器1[2])
self.pressure2.append(int(促动器2[0]))
self.displacement2.append(int(actuator2[1]))
self.cycle2=int(执行器2[2])
自压力3.附加(int(促动器3[0]))
self.displacement3.append(int(actuator3[1]))
self.cycle3=int(执行器3[2])
自压力4.append(int(促动器4[0]))
self.displacement4.append(int(actuator4[1]))
self.cycle4=int(执行器4[2])
如果self.k>0:
self.line0.set_数据(self.xdata、self.pressure1)
self.line1.set_数据(self.xdata、self.pressure2)