The task is as follows: it is necessary to write a program that will read the values ​​from the com-port and build on them a graph in real time. Somehow implemented, BUT it turns out a delay of at least 3-4 seconds.

I came to the conclusion that I do not have time to take values ​​from the buffer. You can draw a graph in several streams, but since I'm not strong in python. Addressed to you.

Please provide examples of multi-threaded drawing graphics with a detailed description.

import matplotlib.pyplot as plt plt.ion() class SerialRead(): com = 0 def __call__(self): import serial self.com = serial.Serial('/dev/ttyACM0', 1200) def readValue(self): #import time #time.sleep(0.2) #self.com.flushInput() ERR = False try: line = self.com.readline() except: ERR = True print("ERR::Ресурс временно недоступен!") if ERR != True: try: value = float(line) except: print("ERR::Wrong value at serial port!") ERR = True if ERR != True: return value c = SerialRead() c() class DynamicUpdate(): #Suppose we know the x range min_y = 0 max_y = 5.1 def on_launch(self): import numpy as np #Set up plot plt.rcParams['toolbar'] = 'None' self.figure, self.ax = plt.subplots() self.lines, = self.ax.plot([],[], 'r') #Autoscale on unknown axis and known lims on the other #self.ax.set_autoscaley_on(True) #self.ax.set_xlim(self.min_x, self.max_x) self.ax.set_autoscaley_on(True) self.ax.set_ylim(self.min_y, self.max_y) #Other stuff self.ax.grid() ... def on_running(self, xdata, ydata): import numpy as np #Update data (with the new _and_ the old points) self.lines.set_xdata(xdata) self.lines.set_ydata(ydata) #Need both of these in order to rescale self.ax.relim() self.ax.autoscale_view() #We need to draw *and* flush self.figure.canvas.draw() self.figure.canvas.flush_events() ######################################### x = max(xdata) if x > 10000: self.ax.set_xlim(x, x - 10000) else: self.ax.set_xlim(0, x) ######################################### #Example def __call__(self): import numpy as np import time import matplotlib.ticker as ticker import random self.on_launch() xdata = [] ydata = [] while True: OLD_VALUE = c.readValue() xdata.append(int(round(time.time() * 1000))) ydata.append(OLD_VALUE) self.on_running(xdata, ydata) #time.sleep(1) return xdata, ydata d = DynamicUpdate() d() 
  • I, of course, not much in the know, but: do not you just rest against the performance of Python itself? --- Try to profile. If bottleneck is drawing, maybe it is worth not to cause on_running on each on_running piece of data? (Operations like autoscale_view or flush_events do not look very cheap from the name.) - VladD
  • @palyla: I'm not sure that multithreading will help if the bottleneck is the speed of calculations. In Python (at least the old versions), a global blocking was used, which essentially blocked the simultaneous operation of several threads. Perhaps @jfs can better clarify the situation. - VladD
  • @palyla: Oh well. Then try to update the picture not every time, but only every, say, 10 values. You don’t supplement the data anyway, and redraw it from scratch, right? - VladD
  • one
    @palyla, use Xlib directly is, of course, a joke (the program will be too voluminous). This library is something like an assembler (if we draw analogies between programming languages) for window graphics in * nix. The bottom level of interaction with the server graphics. It lies somewhere in the depths of almost all the libraries that everyone usually uses (and double buffering can be there in some of the widgets and implicitly be present). - avp pm
  • 2
    Try graphite to draw graphs. Why reinvent the wheel, especially if you are sitting under linux. For the same ubunt it is a few calls apt-get install. And then you definitely will not waste time on the process of drawing. If there is only one core - graphite can be deployed on another machine. - Arkady

0