1

我需要高速生存图形数据。我需要不断查询串行端口以在数据可用时检索数据。数据然后修改我正在绘制的实例变量。我在两个子图上绘制了4条不同的线,因此总共有8条线。我正在接收12个不同的变量,但只能绘制图形8.我需要这个过程在运行一次函数后不会消失,这样我可以继续接收新数据。我想绘制在另一个过程中完成,以防止读取串行端口。我已经找到了一些例子,并且在如何完成这项任务时得到了帮助,如果我拥有所有可用的数据,但是如果它不断接收新数据,并且我不熟悉多处理/线程,那么很难理解如何修改它以连续读取来自串口。我可以以10Hz的速率完成我需要的工作,但我需要以20Hz的频率进行采样,似乎唯一的方法就是通过多处理/线程,除非我错过了优化绘图或读取时间的东西。这里是按Go按钮时会查询串行端口和一个图形窗口Tkinter的:使用多处理/线程读取Tkinter的串行端口和实时图形数据

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.t = 0 
     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(211) 
     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.ax2 = self.fig.add_subplot(212) 
     self.line4, = self.ax2.plot([], [], lw=2) 
     self.line5, = self.ax2.plot([], [], lw=2) 
     self.line6, = self.ax2.plot([], [], lw=2) 
     self.line7, = self.ax2.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.ani = animation.FuncAnimation(
      self.fig, 
      self.update_graph, 
      interval=1, 
      repeat=True) 
     self.arduinoData.write("<L>") 
     self.running = True 
     self.ani._start() 

    def update_graph(self, i): 
     if (self.arduinoData.inWaiting()>0): 
      self.xdata.append(self.k) 
      x = self.arduinoData.readline() 
      self.setData(x) 
      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]) 
      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) 
      self.line4.set_data(self.xdata, self.displacement1) 
      self.line5.set_data(self.xdata, self.displacement2) 
      self.line6.set_data(self.xdata, self.displacement3) 
      self.line7.set_data(self.xdata, self.displacement4) 
      if self.k < 49: 
       self.ax1.set_ylim(min(self.pressure1)-1, max(self.pressure4) + 1) 
       self.ax1.set_xlim(0, self.k+1) 
       self.ax2.set_ylim(min(self.displacement1)-1, max(self.displacement4) + 1) 
       self.ax2.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]) 
       self.ax2.set_ylim(min(self.displacement1[self.k-49:self.k])-1, max(self.displacement4[self.k-49:self.k]) + 1) 
       self.ax2.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 



root = Tkinter.Tk() 
app = App(root) 
root.mainloop() 

如果任何人都可以跟我多的了解帮助或提供,将是巨大的例子。谢谢

+0

您可以设置一个计时器,在如此多的滴答声之后重复该功能。如果你只是想经常运行这个功能,你可以用'.after()'来完成。 'self.function_to_get_data.after(100,lambda:self.function_to_get_data())' –

+0

我正在使用的get数据函数被动画函数调用,我将如何使用它们,以便它们都被调用并赢得' t阻止彼此执行 – emg184

+0

是不止一次调用的动画函数? –

回答

2

如果你提供一个计时器,你可以有一个功能来管理你的事件给你。

例如:

import time 
import tkinter as tk 

root = tk.Tk() 

def getData(): 
    print("getData") 

def update_graph(): 
    print("update_graph") 

def timed_events(): 
    getData() 
    update_graph() 
    root.after(1000, timed_events) # you can change the number to anything you need 

timed_events() 

root.mainloop() 

这将调用为了曾经1秒的每个功能和打印:

getData 
update_graph 

这只是一个简单的例子来说明,你可以如何处理您的数据处理上一个计时器。

更新:

这是您的代码的另一个可选选项。 在您的start(self):方法中,在结尾处添加if语句以重复方法if self.x == True:。然后,您只需创建一个按钮来切换变量self.x,以便您可以在需要时停止循环。

self.x == True 

    def start(self): 
     # all your code so far 
     if self.x == True: 
      self.start 
+0

对不起,我试图以20Hz运行它之后说得太快了,它仍然太慢,它运行得很好,略高于我以前的水平这是10Hz – emg184

+0

啊。那么我会成像有一个解决方案为你多一点研究。当我今天下班回家时,我会看看是否没有人给你提供更好的选择:) –

+0

听起来非常感谢你的帮助,我一直坚持这一段时间 – emg184