1

J'ai besoin de gérer les données de graphe à un débit élevé. J'ai besoin d'interroger en permanence le port série pour récupérer les données quand elles sont disponibles. Les données modifient ensuite les variables d'instance que je représente. Je représente graphiquement 4 lignes différentes sur deux sous-tracés, donc 8 lignes au total. Je reçois 12 variables différentes, mais seulement le graphique 8. J'ai besoin que le processus ne s'éteigne pas après l'exécution de la fonction une fois de cette façon, je peux continuer à recevoir de nouvelles données. Je veux que le tracé soit fait dans un autre processus afin qu'il ne bloque pas la lecture du port série. J'ai trouvé des exemples et j'ai obtenu de l'aide pour y parvenir si toutes les données sont déjà disponibles mais pas si je reçois continuellement de nouvelles données et si je suis novice en multiprocessing/threading, il est difficile de comprendre comment les lire en continu. à partir du port série. Je peux accomplir ce que j'ai besoin à un taux de 10Hz mais j'ai besoin d'échantillonner à 20Hz et il semble que le seul moyen serait le multiprocessing/threading à moins que je manque quelque chose qui optimiserait le temps de lecture ou graphique. Voici une fenêtre Tkinter qui interrogera le port série lorsque le bouton de validation est pressé et graphique:Utilisation de multiprocessing/threading pour lire le port série et les données de graphe en temps réel avec 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() 

Si quelqu'un peut aider avec ma compréhension de multitraitement ou de fournir un exemple qui serait génial. Merci

+0

Vous pouvez simplement définir une minuterie pour répéter la fonction après tant de ticks. Si vous voulez simplement exécuter cette fonction en permanence, vous pouvez le faire avec '.after()'. 'self.function_to_get_data.after (100, lambda: self.function_to_get_data())' –

+0

La fonction get data que j'utilise est appelée par la fonction d'animation comment serais-je capable d'utiliser après pour qu'ils soient à la fois appelés et gagnés? t bloquer l'exécution des autres – emg184

+0

est la fonction d'animation appelée plus d'une fois? –

Répondre

2

Si vous fournissez une minuterie, vous pouvez avoir une fonction qui gérera vos événements pour vous.

Par exemple:

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() 

ce appellera chaque fonction pour toujours 1 sec et imprimer:

getData 
update_graph 

C'était juste un exemple simple pour illustrer comment vous pourriez gérer vos données de traitement sur une minuterie.

Mise à jour:

Voici une autre option avec votre code posible. Dans votre méthode start(self):, ajoutez une instruction if à la fin pour répéter la méthode if self.x == True:. Ensuite, tout ce que vous devez faire est de créer un bouton qui permute la variable self.x afin que vous puissiez arrêter la boucle quand vous le souhaitez.

self.x == True 

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

Désolé j'avais parlé trop tôt après avoir essayé de l'exécuter à 20Hz c'était encore trop lent ça fonctionnait bien au-dessus de ce que j'avais avant qui était de 10 Hz – emg184

+0

Ah. Eh bien, j'imaginais qu'il y a une solution pour vous avec un peu plus de recherche.Quand je rentre du travail aujourd'hui je jetterai un coup d'oeil si personne ne vous a présenté une meilleure option :) –

+0

Semble grand merci pour sortir de votre manière d'aider j'ai été coincé sur ceci depuis un certain temps maintenant – emg184