Real time plotting of serial data with python and tkinter - python

I have been working for some time to find a way to graph incoming data from an arduino with a Python GUI. I was able to accomplish this using the Matplotlib animation function to read in 6 different variables and plot 4 of them 2 on one subplot 2 on another subplot. This was able to be done fast enough that it was graphing real time (20 samples per second).
I now need to modify the system to read in 12 different variables at the same time of which 8 are graphed. 4 on one sub plot 4 on another at the same rate of 20 samples per second. I haven't been able to get this to work and have tried a few different things and done a lot of research but can't seem to figure out how to do it with my limited knowledge of python. Im not very familiar with multiprocessing or multithreading but they seem to be the way that people are able to speed up the graphing process. I know that the matplotlib animated function itself is threaded so I'm not sure how much the threading would help with that or if there's a way to read in one thread and update the graph in another. I'm operating at the highest baudrate that the arduino supports 250000. I also was able to find an example where someone was able to get a very high speed plot in this post but havent been able to modify to work for my use: What is the best real time plotting widget for wxPython?
the data is received from the arduino like this:
integer.integer.integer|integer.integer.integer|integer.integer.integer|integer.integer.integer
where the pipe represents a new actuator (what each variable im sending is coming from)
I'm fairly new to python so sorry if this isnt so pythonic but here are two examples I have:
This is a gui using the animation function:
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
class App:
def __init__(self, master):
self.arduinoData = serial.Serial('com5', 250000)#115200)
frame = Tkinter.Frame(master)
self.running = False
self.ani = None
self.start = Tkinter.LabelFrame(frame, text="Start", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
self.start.grid(row=0, column=0, padx=20, pady=20)
self.run = Tkinter.Button(self.start, text="RUN", bd=10, height=5, width=10, command=self.getData)
self.run.grid(row=0, column=0, padx=5, pady=5)
self.stop_frame = Tkinter.LabelFrame(frame, text="STOP", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
self.stop_frame.grid(row=0, column=1, padx=20, pady=20)
self.stop = Tkinter.Button(self.stop_frame, 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 resetTest(self):
self.k = 0
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.line1.set_data(self.xdata, self.ydata1)
self.line2.set_data(self.xdata, self.ydata2)
self.ax1.set_ylim(0,1)
self.ax1.set_xlim(0,1)
self.ax2.set_ylim(0,1)
self.ax2.set_xlim(0,1)
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.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):
self.xdata.append(self.k)
while (self.arduinoData.inWaiting()==0):
pass
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])
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.pressure3) + 1)
self.ax1.set_xlim(0, self.k+1)
self.ax2.set_ylim(min(self.displacement1)-1, max(self.displacement3) + 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.pressure3[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.displacement3[self.k-49:self.k]) + 1)
self.ax2.set_xlim(self.xdata[self.k-49], self.xdata[self.k-1])
self.k += 1
root = Tkinter.Tk()
app = App(root)
root.mainloop()
This is a gui that prints to the monitor:
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
import time
class App:
def __init__(self, master):
self.arduinoData = serial.Serial('com5', 250000, timeout=0)
frame = Tkinter.Frame(master)
self.go = 0
self.start = Tkinter.LabelFrame(frame, text="Start", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
self.start.grid(row=0, column=0, padx=20, pady=20)
self.run = Tkinter.Button(self.start, text="RUN", bd=10, height=5, width=10, command=self.getData)
self.run.grid(row=0, column=0, padx=5, pady=5)
self.stop_frame = Tkinter.LabelFrame(frame, text="STOP", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
self.stop_frame.grid(row=0, column=1, padx=20, pady=20)
self.stop = Tkinter.Button(self.stop_frame, 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):
self.k = 0
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.arduinoData.flushInput()
self.go = 1
self.readData()
def readData(self):
if self.go == 1:
self.xdata.append(self.k)
while (self.arduinoData.inWaiting()==0):
pass
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])
self.printData()
root.after(0, self.readData)
def printData(self):
print str(self.pressure1[self.k-1]) + " " +
str(self.displacement1[self.k-1]) + " " + str(self.cycle1) + " " +
str(self.pressure2[self.k-1]) + " " + str(self.displacement2[self.k-
1]) + " " + str(self.cycle2) + " " + str(self.pressure3[self.k-1]) +
" " + str(self.displacement3[self.k-1]) + " " + str(self.cycle3) + "
" + str(self.pressure4[self.k-1]) + " " +
str(self.displacement4[self.k-1]) + " " + str(self.cycle4)
def stopTest(self):
self.arduinoData.write("<H>")
self.go = 0
def resetTest(self):
self.k = 0
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.line1.set_data(self.xdata, self.ydata1)
self.line2.set_data(self.xdata, self.ydata2)
self.ax1.set_ylim(0,1)
self.ax1.set_xlim(0,1)
self.ax2.set_ylim(0,1)
self.ax2.set_xlim(0,1)
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.arduinoData.write("<L>")
root = Tkinter.Tk()
app = App(root)
root.mainloop()
and here is an example arduino code:
int analog0 = 0;
int analog1 = 1;
int analog2 = 2;
int sensor0;
int sensor1;
int sensor2;
String pot0;
String pot1;
String Force;
int pot0holder;
int pot1holder;
String Forceholder;
unsigned long i = 0;
String Is;
int val = 0;
boolean Sensordata = false;
int cycles;
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
unsigned long CurrentMillis = 0;
unsigned long PrintMillis = 0;
int PrintValMillis = 50;
unsigned long SensorMillis = 0;
int SensorValMillis = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(250000);
}
void loop()
{
CurrentMillis = millis();
recvWithStartEndMarkers();
commands();
sensordata();
}
void sensordata()
{
if (CurrentMillis - SensorMillis >= SensorValMillis)
{
sensor0 = analogRead(analog0);
pot0holder = sensor0;
sensor1 = analogRead(analog1);
pot1holder = sensor1;
i += 1;
String potcolumn = String(pot0holder) + "." + String(pot1holder) + "." + String(i) + "|" + String(int(pot0holder)+30) + "." + String(int(pot1holder)+30) + "." + String(i) + "|" + String(int(pot0holder)+60) + "." + String(int(pot1holder)+60) + "." + String(i) + "|" + String(int(pot0holder)+90) + "." + String(int(pot1holder)+90) + "." + String(i);
Serial.println(potcolumn);
SensorMillis += SensorValMillis;
}
}
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false; //creates variable visible to only one function with boolean
static byte ndx = 0;
char startMarker = '<'; //sets begin condition
char endMarker = '>'; //sets end condition
char rc; //sets variable type to char
while (Serial.available() > 0 && newData == false) {
rc = Serial.read(); //sets rc equal to serial value
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void commands()
{
if (newData == true)
{
if (receivedChars[0] == 'T')
{
PrintValMillis = atoi(&receivedChars[1]); //atoi -> Converting strings to integer
}
else if (receivedChars[0] == 'S')
{
cycles = atoi(&receivedChars[1]);
i = 0;
}
else if (receivedChars[0] == 'L')
{
val = atoi(&receivedChars[1]);
i = 0;
}
}
newData = false;
}
Thanks in advance for any help or advice any one has.

So your reading process takes most of the time. I would put the reading in a separate task and do the evaluation/splitting of the data in the main (drawing)-process. Unfortunately, I am not a tkinter user, so I have written this without any special gui-framework. But I think you can adapt this to your needs.
That would look like that:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import multiprocessing as mp
import time
# global variables
fig = plt.figure(1)
# first sub-plot
ax1 = fig.add_subplot(211)
line1, = ax1.plot([], [], lw=2)
ax1.grid()
xdata1, ydata1 = [], []
# second sub-plot
ax2 = fig.add_subplot(212)
line2, = ax2.plot([], [], lw=2)
ax2.grid()
xdata2, ydata2 = [], []
# the multiprocessing queue
q = mp.Queue()
# data generator in separate process
# here would be your arduino data reader
def dataGen(output):
for x in range(50):
output.put((x, np.sin(x)))
# update first subplot
def update1(data):
# update the data
t, y = data
xdata1.append(t)
ydata1.append(y)
xmin, xmax = ax1.get_xlim()
ymin, ymax = ax1.get_ylim()
if t >= xmax:
ax1.set_xlim(xmin, 2*xmax)
if y >= ymax:
ax1.set_ylim(ymin, 2*ymax)
if y <= ymin:
ax1.set_ylim(2*ymin, ymax)
line1.set_data(xdata1, ydata1)
return line1,
# update second subplot
def update2(data):
# update the data
t, y = data
xdata2.append(t)
ydata2.append(y)
xmin, xmax = ax2.get_xlim()
ymin, ymax = ax2.get_ylim()
if t >= xmax:
ax2.set_xlim(xmin, 2*xmax)
if y >= ymax:
ax2.set_ylim(ymin, 2*ymax)
if y <= ymin:
ax2.set_ylim(2*ymin, ymax)
line2.set_data(xdata2, ydata2)
return line2,
# called at each drawing frame
def run(data):
# get data from queue, which is filled in separate process, blocks until
# data is available
data = q.get(block=True, timeout=.5)
# put here your variable separation
data1 = (2*data[0], 3*data[1])
data2 = (data[0], data[1])
#provide the data to the plots
a = update1(data1)
b = update2(data2)
fig.canvas.draw()
return a+b
if __name__ == "__main__":
# count of reader processes
n_proc = 1
# setup workers
pool = [mp.Process(target=dataGen, args=(q,)) for x in range(n_proc)]
for p in pool:
p.daemon = True
p.start()
# wait a few sec for the process to become alive
time.sleep(3)
# start your drawing
ani = animation.FuncAnimation(fig, run, frames=60, blit=True, interval=10,
repeat=False)
plt.show()
print('done')

My question is very similar with yours.
I need to get data from a profi-bus network every 80ms, and I want the data to be plotted while sampling.
I used multiprocessing to solve the problem.The Pipe was used for communication between two processes.
When the Plotter gets data from Collector, and it is going to plot something, the Plotter will send a message to the Collector. and then the Collector will stop sending the data and put the data into a list.
when plotter done its job, it tells the collector that 'now you can send data', the collector then send the data and clear the list.
import time
import numpy as np
from matplotlib import pyplot as plt
import multiprocessing
from multiprocessing import Process, Pipe
from random import random
class DataGennerator(object):
"""docstring for DataGennerator"""
def __init__(self, data_pipe):
super(DataGennerator, self).__init__()
print('Data Gennerator Init...')
self.data_buffer = []
self.t = 0
self.start_time = 0
self.data_pipe = data_pipe
self.plot_inprogess = False
self.data_ready = False
def run(self):
self.start_time = time.time()
for i in range(0, 400):
self.loop_cycle()
print('Total Time:', time.time()-self.start_time)
print('Run completion......')
def loop_cycle(self):
self.t = time.time()-self.start_time
new_data = [time.time()-self.start_time, np.sin(self.t), np.cos(2*self.t), np.cos(self.t*4), random()]
self.send_data(new_data)
time.sleep(0.08)
def send_data(self, new_data):
if self.plot_inprogess or not self.data_ready:
self.data_buffer.append(new_data)
self.data_ready = True
# Wait 1ms to read plotter's msg
if self.data_pipe.poll(0.0001):
self.plot_inprogess = self.data_pipe.recv()
else:
self.data_pipe.send(self.data_buffer)
self.data_buffer = []
self.data_ready = False
# Function to collect data by using DataGennerator
def get_data(data_pipe):
dg = DataGennerator(data_pipe)
dg.run()
data_pipe.send('EXIT')
print('>>> Finished')
# use plotter_pipe to communicate with data collector
# and when get data from the collector, updata the figure
def updata_plot(plotter_pipe, plot_inprogess=True):
plot_inprogess = True
fig, ax = plt.subplots(nrows=4, ncols=1, figsize=(6,8), sharex=True)
fig.set_tight_layout(True)
styles = ['rs-', 'gs-', 'bs-', 'ro-', 'go-', 'bo-']*10
lines = []
for index, name in enumerate(['sin(t)', 'cos(t)', 'cos(2t)', 'random']):
line, = ax[index].plot([],[], styles[index],label=name, markersize=4, markerfacecolor='w')
ax[index].set_ylabel(name, color=styles[index][0], fontweight='bold')
lines.append(line)
ax[-1].set_xlabel('Time /s')
fig.align_ylabels(ax)
plt.ion()
plt.show(block=False)
plt.draw()
# Read the 1st data package and convert it to Numpy Array
data_array = np.array(plotter_pipe.recv())
while True:
try:
# Read data_buffer sent by Data Collector
data_buffer = plotter_pipe.recv() #[ [data1], [data2]...]
# If the DataCollector says EXIT, then break the while loop
if data_buffer == 'EXIT': break
# Raise a flag to indicate that Plot is in progress
plotter_pipe.send(True)
# Append data_buffer to Data Array
data_array = np.append(data_array, np.array(data_buffer), axis=0)
for i in range(0, 4):
lines[i].set_xdata(data_array[:,0])
lines[i].set_ydata(data_array[:,i+1])
ax[i].relim()
ax[i].autoscale_view()
fig.canvas.draw()
plt.pause(0.001)
# Tell data collector that Plot has been finished
plotter_pipe.send(False)
except Exception as e:
raise e
finally:
pass
print('>>> Stop receiving data')
data_content = '\n'.join([', '.join(map(str,data_line)) for data_line in data_array])
with open('data.txt', 'w', encoding='UTF-8') as f:
f.write('time, xx, yy, zz, bb\n')
f.writelines(data_content)
plt.show(block=True)
if __name__ == '__main__':
plot_inprogess = True
data_pipe, plotter_pipe = multiprocessing.Pipe(True)
P1 = Process(target=get_data , args=(data_pipe,))
P2 = Process(target=updata_plot, args=(plotter_pipe,))
P1.start()
P2.start()
P1.join()
P2.join()

Related

Windows serial port timing issue or bad code? [Python]

I am writing an application for a digital lab balance that connects over serial. To build the application I set up a COM port bridge and wrote a program to simulate the balance on my machine (the balance was in use). I will show you the most recent version of the balance simulation program:
import serial, random, time
s = serial.Serial('COM2')
#Initially we will just push a random float
#After the data the scale sends a carraige return + line feed
def pushData():
data = f'{round(random.uniform(10, 100), 2)}\r\n'.encode()
print(f'Sending Data: {data}')
s.write(data)
try:
while True:
pushData()
time.sleep(10)
except:
print('Something went wrong.')
This code along with my balance application works as expected on my machine. But when I try to use my balance program with the actual device it does not get all the serial data if it even works at all. I am wondering if I need some kind of multi-threading, if its a timing issue or something. I know the balance works because I can monitor the COM port.
I will post my most recent balance program here:
# !/usr/bin/python3
################ Imports
import serial, pyperclip
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from datetime import datetime, time
from tkinter import *
################ Declarations
GUI = Tk()
s = serial.Serial('COM5', timeout=1)
wgtList = [0,0,0,0,0]
wgtDict = {'Lab':[],
'Weight':[]}
newL = '\r\n'
tareWgt = 0
newWgt = 0 #Trying to get past program not working when no data is pushed
################ Functions
def thisAfter():
"""Updates scale feed and updates the scale feed."""
try:
global newWgt
newWgt = float(s.readline().decode().rstrip('\r\n')) - tareWgt
except ValueError:
#print('ValueError thisAfter(): NO DATA OR COULD NOT CONVERT SERIAL DATA TO FLOAT')
print('ValueError thisAfter(): '+ str(newWgt))
print('wgtList: '+ str(wgtList))
wgtList.append(newWgt)
if newWgt not in wgtList[0:5]:
text.insert(INSERT,str(newWgt)+newL)
if len(wgtList) > 5:
del wgtList[0]
GUI.after(50, thisAfter)
text.see(END)
def labCallback():
"""Saves data to file, iterates the entry field."""
num = labEntry.get()
csvStr = datetime.today().strftime("%Y/%m/%d") + ',' + datetime.now().strftime("%H:%M:%S") + ',' + num + ',' + str(wgtList[-1]) + ',' + var1.get() + ',' + str(tareWgt) + newL
with open('data.csv', 'a+', newline = '') as file:
if file.readline() == None:
file.write('Date, Time, Lab, Weight, Type' + newL)
file.write(csvStr)
#print(csvStr) #Just checking
labEntry.delete(0,END)
labEntry.insert(0, int(num) + 1)
csvArr = csvStr.split(',')
wgtDict['Lab'].append(int(csvArr[2]))
wgtDict['Weight'].append(float(csvArr[3]))
text2.insert(INSERT, ',\t'.join(csvArr))
text2.see(END)
#print(str(wgtDict)+'\n')
def tareCallback():
global tareWgt
tareWgt = wgtList[-1]
print(tareWgt)
text3.insert(INSERT,newL+str(tareWgt))
text3.see(END)
def copyData():
global newWgt
pyperclip.copy(newWgt)
def close():
s.close()
def start():
global s
try:
s = serial.Serial('COM5', timeout=1)
thisAfter()
except:
print('Serial port closed')
################ Frames/Panes
frame1 = LabelFrame(GUI, text = 'Lab Label + Entry Field')
frame1.pack(side = TOP)
frame6 = LabelFrame(frame1, text = 'Tare')
frame6.pack(side = BOTTOM)
frame2 = LabelFrame(GUI, text = 'Scale Feed')
frame2.pack(side = BOTTOM)
frame3 = LabelFrame(GUI, text = 'Saved Feed')
frame3.pack(side = BOTTOM)
frame4 = LabelFrame(GUI, text = 'Plot')
frame4.pack(side = TOP)
frame5 = LabelFrame(frame1, text = 'Type Select')
frame5.pack(side = BOTTOM)
################ Lab Label + Entry Field + Type Select
labLabel = Label(frame1, bd = 5, text = 'Lab#')
labLabel.pack(side = LEFT)
tareLabel = Label(frame6, bd = 5, text = 'Tare')
tareLabel.pack(side = LEFT)
text3 = Text(frame6, height = 1, width = 20)
text3.pack(side = RIGHT)
closeButton = Button(frame1, text = 'Close', command = close)
closeButton.pack(side = RIGHT)
startButton = Button(frame1, text = 'Start', command = start)
startButton.pack(side = RIGHT)
tareButton = Button(frame1, text = 'Tare', command = tareCallback)
tareButton.pack(side = RIGHT)
undoButton = Button(frame1, text = 'Undo')
undoButton.pack(side = RIGHT)
labButton = Button(frame1, text = 'Save', command = labCallback)
labButton.pack(side = RIGHT)
copyButton = Button(frame1, text = 'Copy', command = copyData)
copyButton.pack(side = RIGHT)
labEntry = Entry(frame1)
labEntry.pack(side = RIGHT)
var1 = StringVar()
r1 = Radiobutton(frame5, text = 'pH', variable= var1, value = 'pH')
r1.pack(anchor = 's')
r2 = Radiobutton(frame5, text = 'pH-Tray', variable= var1, value = 'pH-Tray')
r2.pack(anchor = 's')
r3 = Radiobutton(frame5, text = 'Mehlich', variable= var1, value = 'Mehlich')
r3.pack(anchor = 's')
r4 = Radiobutton(frame5, text = 'Nitrate', variable= var1, value = 'Nitrate')
r4.pack(anchor = 's')
r5 = Radiobutton(frame5, text = 'Excel', variable= var1, value = 'Excel')
r5.pack(anchor = 's')
r6 = Radiobutton(frame5, text = 'Excel-Tray', variable= var1, value = 'Excel-Tray', state=DISABLED)
r6.pack(anchor = 's')
r1.select()
r2.deselect()
r3.deselect()
r4.deselect()
r5.deselect()
r6.deselect()
################ Scale Feed
scrollbar = Scrollbar(frame2)
scrollbar.pack(side = RIGHT, fill = Y)
text = Text(frame2, yscrollcommand = scrollbar.set, height = 10)
text.pack()
text.bind('<ButtonPress>', lambda e: 'break')
scrollbar.config(command = text.yview)
#thisAfter()
################ Saved Feed
scrollbar = Scrollbar(frame3)
scrollbar.pack(side = RIGHT, fill = Y)
text2 = Text(frame3, yscrollcommand = scrollbar.set, height = 10)
text2.pack()
scrollbar.config(command = text.yview)
################ Plot
f = plt.Figure(dpi=50, figsize=(13, 4))
plt.xkcd()
a = f.add_subplot(111)
def animate(i):
xL = wgtDict['Lab']
yL = wgtDict['Weight']
a.clear()
a.plot(xL, yL)
canvas = FigureCanvasTkAgg(f, frame4)
canvas.get_tk_widget().pack(side = LEFT, fill = BOTH)
ani = animation.FuncAnimation(f, animate, interval=1000)
# This is some kind of 'while true' loop fyi
GUI.mainloop()

How do I show two figures(plots) in a single window?

fig and fig1 give two different plots. Two different windows pop up. I want to show these two plots in a single window, may be separated by a line in the middle. How can I do that?
packing_options = get_packing_options(min_w, max_w, min_l, max_l, rect_list, step_size = 1, \
result_list = []
for opt in packing_options:
step_w = float(get_max(opt.sheets))
tmp_sheets = trim_sheets(opt.sheets, max(min_w,step_w), min_l)
tmp_l = float(get_max(tmp_sheets,False))
tmp_result_list = []
tmp_w = step_w
while area/tmp_w >= tmp_l:
tmp_sheet = Sheet(tmp_w, area/tmp_w)
tmp_result_list.append(find_best_packing_GA(tmp_sheet, sheets_to_rect_list(tmp_sheets), \
Pm = 0, rotate_prob = 0, flex = True, only_vertical = True))
tmp_w = tmp_w + step_w
result_list.append(best_individual(tmp_result_list)[0])
best, avg_fit, best_index = best_individual(result_list)
fig = packing_options[best_index].plot_sheets()
dataPlot = FigureCanvasTkAgg(fig, master = window)
dataPlot.draw()
dataPlot.get_tk_widget().pack(side='top', fill='both', expand=1)
fig1 = best.plot_sheets()
dataPlot1 = FigureCanvasTkAgg(fig1, master = window)
dataPlot1.draw()
dataPlot1.get_tk_widget().pack(side='top', fill='both', expand=1)
This is the picture of the output: https://imgur.com/NZaZkwa

Python Tkinter & matplotlib - RuntimeError

Okay so I wrote this code...
#!/usr/bin/env
import sys
import time
import subprocess
from Tkinter import *
import numpy
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
import matplotlib.pyplot as plt
import threading
CDatei = subprocess.Popen("/home/pi/meinc++/Spi")
print("Hallo")
i = 0
x = 0
def GetValue():
with open("/home/pi/meinc++/BeispielDatei.txt","r") as Datei:
for line in Datei:
time.sleep(0.01)
return line
def WithoutNull(input):
ReturnValue = input
while ReturnValue is None:
ReturnValue = GetValue()
return ReturnValue
def UebergabeWert():
while x == 0:
WholeString = WithoutNull(GetValue())
StringVar, DatumVar = WholeString.strip().split(' - ')
IntStringVar = [int(v) for v in StringVar.split()]
return IntStringVar, DatumVar
def MinutenWert():
Maximum = 0
Minimum = 0
i = 0
LaengeArray = 0
Multiplikator = 10000
ArrayValue = [-999999]*Multiplikator
AlteZeit = time.time()
while 1:
CompleteValue, Trash = UebergabeWert()
ArrayValue[i] = CompleteValue[0]
i = i + 1
ArrayFilter = filter(lambda c: c != -999999,ArrayValue)
ArraySumme = numpy.sum(ArrayFilter)
LaengeArray = len(ArrayFilter)
Mittelwert = ArraySumme/LaengeArray
ArraySortierung = sorted(ArrayFilter)
Maximum = ArraySortierung[LaengeArray-1]
Minimum = ArraySortierung[0]
NeueZeit = time.time()
if NeueZeit-AlteZeit >= 60:
AlteZeit = time.time()
ArrayValue[i:Multiplikator] = [-999999]*(Multiplikator-i)
i = 0
yield Mittelwert
yield Maximum
yield Minimum
yield LaengeArray
yield ArrayFilter
def UebergabeTkinter():
while 1:
Mittelwert = next(MinutenWertYield)
Maximum = next(MinutenWertYield)
Minimum = next(MinutenWertYield)
LaengeArray = next(MinutenWertYield)
ArrayFilter = next(MinutenWertYield)
CompleteValue, DatumVar = UebergabeWert()
Variable1.set(CompleteValue[0])
Variable2.set(CompleteValue[1])
Variable3.set(CompleteValue[2])
Variable4.set(CompleteValue[3])
VariableMittelwert.set(Mittelwert)
VariableMaximum.set(Maximum)
VariableMinimum.set(Minimum)
t = threading.Thread(target = Grafik)
t.start()
root.update()
def Grafik():
GrafikAnfang = time.time()
Array = 0
ArrayGrafik = [0]*20
GrafikEnde = 1
while 1:
CompleteValue, DatumVar = UebergabeWert()
ArrayGrafik[Array] = CompleteValue[0]
LaengeArrayGrafik = len(ArrayGrafik)
fig = Figure(figsize = (3, 3))
axis = fig.add_subplot(111)
axis.legend()
axis.grid()
canvas = FigureCanvasTkAgg(fig, master = root)
canvas.get_tk_widget().grid(row=10,column=0,rowspan=2,columnspan=2)
LinienBreite = numpy.linspace(1,LaengeArrayGrafik,LaengeArrayGrafik)
axis.plot(LinienBreite,ArrayGrafik,'b-')
axis.set_xticks(LinienBreite)
DatumArray = [DatumVar]
axis.set_xticklabels(DatumArray)
canvas.draw()
fig.clear()
print Array
if GrafikEnde-GrafikAnfang < 600:
Array = Array + 1
GrafikEnde = time.time()
if GrafikEnde-GrafikAnfang >= 600:
del ArrayGrafik[0]
def Exit():
root.destroy()
return
try:
MinutenWertYield = MinutenWert()
root = Tk()
Leiste = Menu(root)
root.config(menu = Leiste)
DateiMenu = Menu(Leiste)
Leiste.add_cascade(label = "datei", menu = DateiMenu)
DateiMenu.add_command(label = "Exit", command = Exit)
EditMenu = Menu(Leiste)
Leiste.add_cascade(label = "edit", menu = EditMenu)
Variable1 = IntVar()
Variable2 = IntVar()
Variable3 = IntVar()
Variable4 = IntVar()
VariableMittelwert = IntVar()
VariableMaximum = IntVar()
VariableMinimum = IntVar()
Ausgang = 0
for column in range(0,8,2):
String1 = "Ausgang "
String1 += `Ausgang`
Ausgang = Ausgang + 1
Label(text = String1).grid(row=0,column=column)
Ausgang = 0
for column in range(0,8,2):
String1 = "Der Wert von "
String2 = " ist: "
String1 += `Ausgang`
Ausgang = Ausgang + 1
String3 = String1+String2
Label(text = String3).grid(row=2,column=column)
Label(text = "Der Mittelwert ist: ").grid(row=4,column=0)
Label(text = "Das Maximum ist: ").grid(row=5,column=0)
Label(text = "Das Mimimum ist: ").grid(row=6,column=0)
Label1 = Label(root, textvariable = Variable1)
Label1.grid(row = 2, column = 1)
Label2 = Label(root, textvariable = Variable2)
Label2.grid(row = 2, column = 3)
Label3 = Label(root, textvariable = Variable3)
Label3.grid(row = 2, column = 5)
Label4 = Label(root, textvariable = Variable4)
Label4.grid(row = 2, column = 7)
LabelMittelwert = Label(root, textvariable = VariableMittelwert)
LabelMittelwert.grid(row = 4, column = 1)
LabelMaximum = Label(root, textvariable = VariableMaximum)
LabelMaximum.grid(row = 5, column = 1)
LabelMinimum = Label(root, textvariable = VariableMinimum)
LabelMinimum.grid(row = 6, column = 1)
UebergabeTkinter()
print "Hallo"
root.mainloop()
except KeyboardInterrupt:
CDatei.kill()
root.quit()
root.destroy()
and when i run it, it says "RuntimeError: main thread is not in the main loop".
Short explanation of the code: It's a code to read out sensor data from a text file -
GetValue().
If the Data is Null it'll read out again - WithoutNull().
The Data is then splitted into data and timestamp (cause it has the format val1, val2, val3, val4, time) - UebergabeWert.
Then the maxima, minima and average of the data will be measured - MinutenWert()
After this, the values are set as labels and go their way into Tkinter - UebergabeTkinter()
The Tkinter build is mainly in Try:
What I wanted to do there, is to implement a graph to Tkinter, but because of the fast changing values it got tremendously slow so i decided to put the graph build in a thread and run it parallel to Tkinter. Unfortunately, it doesn't seem to work and I don't know why
Any suggestions?

Looping a function using after() method

I designed a GUI to plot a graph from the text file. However, the plots will not update when I added new points into the text file. I tried using the after() method to keep looping my function to plot the graph but it fails to work. It would not update my plots and it would not even print out 'Updating...' as shown in the code. Would like to know what went wrong and is there a better way to update my plots? Thanks.
class Timer:
def __init__(self, parent):
self.parent = parent
self.time1 = " "
self.time_label = Label(topFrame, text=self.time1, font = "Helvetica 12 bold")
self.time_label.grid(row = 1, column = 1)
self.random_lbl = Label(topFrame, text="Virtual Microgrid", font = "Helvetica 16 bold italic")
self.random_lbl.grid(row = 0, column = 1)
self.random_lbl = Label(topFrame, text="GRAPHS", font = "Helvetica 12 bold" )
self.random_lbl.grid(row = 2, column = 5)
self.update_clock()
def update_clock(self):
self.time2 = time.strftime("%H:%M:%S")
self.time1 = self.time2
self.time_label.config(text=self.time1)
self.parent.after(200, self.update_clock)
def update(self):
self.animate()
print("Updating.....")
self.parent.after(1, self.update)
def animate():
graph_data = open('example.txt', 'r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs.append(x)
ys.append(y)
graph_data = open('example1.txt', 'r').read()
lines = graph_data.split('\n')
xs1 = []
ys1 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs1.append(x)
ys1.append(y)
graph_data = open('example2.txt', 'r').read()
lines = graph_data.split('\n')
xs2 = []
ys2 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs2.append(x)
ys2.append(y)
graph_data = open('example3.txt', 'r').read()
lines = graph_data.split('\n')
xs3 = []
ys3 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs3.append(x)
ys3.append(y)
graph_data = open('example4.txt', 'r').read()
lines = graph_data.split('\n')
xs4 = []
ys4 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs4.append(x)
ys4.append(y)
fig = Figure(figsize=(13,3.25))
a = fig.add_subplot(111)
a.plot(xs,ys,color='red')
a.plot(xs1,ys1,color='blue')
a.plot(xs4,ys4,color='black')
a.set_title ("SOURCE", fontsize=8)
a.set_ylabel("Voltage/V", fontsize=8)
a.set_xlabel("Time/s", fontsize=8)
a.grid()
fig5 = Figure(figsize=(13,3.25))
f = fig5.add_subplot(111)
f.plot(xs2,ys2,color='red')
f.plot(xs3,ys3,color='blue')
f.set_title ("LOAD", fontsize=8)
f.set_ylabel("Voltage/V", fontsize=8)
f.set_xlabel("Time/s", fontsize=8)
f.grid()
canvas = FigureCanvasTkAgg(fig, master=rightFrame)
canvas.get_tk_widget().grid(row = 2, column = 1, sticky = "nswe")
canvas.draw()
canvas5 = FigureCanvasTkAgg(fig5, master=rightFrame)
canvas5.get_tk_widget().grid(row = 3, column = 1, sticky = "nswe")
canvas5.draw()
I suggest that you close the file every time after you get all the data.
Look at following
Is close() necessary when using iterator on a Python file object

Using animated graph with Tkinter GUI python

I am developing a python code where my computer reads data being transmitted using serial communication and my program presents this data in graphical format. New data is received every 0.1 seconds after which the graph is updated.
The code is:
import matplotlib
matplotlib.use("TkAgg")
from matplotlib import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
from random import *
from Serial import *
import Tkinter as tk
import ttk
import xlwt
import serial
COMPORT = "COM7"
BUAD = 115200
def init():
connected = False
global ser
global COMPORT, BUAD
ser = serial.Serial(COMPORT, BUAD)
while not connected:
serin = ser.read()
connected = True
def TransmitCommand(Command):
SCommand = Command + 'y'
ser.write(SCommand)
def TransmitData(Data):
SData = str(Data) + 'y'
ser.write(SData)
def ClosePort():
ser.close()
def RecieveData():
return ser.readline()
################################################################################
############################ Graph1 #######################################
################################################################################
F1 = Figure(figsize=(15,8), dpi=80)
rc("font", size = 10)
Figure
a1 = F1.add_subplot(111)
tList = []
xList = []
yList = []
zList = []
fList = []
xfList = []
yfList = []
zfList = []
fxList = []
fyList = []
fzList = []
t = 0.00
t1 = 0
x = 0
y = 0
z = 0
ex = 0
ey = 0
ez = 0
r1 = 0
r2 = 0
r3 = 0
l = 0
txp = 0
typ = 0
tzp = 0
global fx1, fy1, fz1
fx1 = 0.00000
fy1 = 0.00000
fz1 = 0.00000
PPS1 = 1
def Play1():
global PPS1
TransmitCommand('SendData')
#print 'Done'
PPS1 = 0
def Pause1():
global PPS1
TransmitCommand('StopData')
PPS1 = 1
def Stop1():
global PPS1
TransmitCommand('StopData')
PPS1 = 2
def Extract1():
pass
def Save1():
pass
def SaveGraph1():
pass
def animate1(i):
global l, ex, ey, ez, t, x, y, z, tList, xList, yList, zList, r1, r2, r3
global fx1, fy1, fz1, txp, typ, tzp, xt, yt, zt
if(PPS1 == 0):
tList.append(t)
xList.append(x)
yList.append(y)
zList.append(z)
t = int(RecieveData())
x = int(RecieveData())
if(l == 0):
x = (x*0.707)/300
else:
x = ex - (x*0.707)/300
if(x > 0):
if(xList[l-1] == 0)|(xList[l-1] < 0):
fx1 = (1.0/(t - txp))*1000
txp = t
r1 = 1
y = int(RecieveData())
if(l == 0):
y = (y*0.707)/300
else:
y = ey - (y*0.707)/300
if(y > 0):
if(yList[l-1] == 0)|(yList[l-1] < 0):
fy1 = (1.0/(t - typ))*1000
typ = t
r2 = 1
z = int(RecieveData())
if(l == 0):
z = (z*0.707)/300
else:
z = ez - (z*0.707)/300
if(z > 0):
if(zList[l-1] == 0)|(zList[l-1] < 0):
fz1 = (1.0/(t - tzp))*1000
tzp = t
r3 = 1
if(l == 0):
ex = x
ey = y
ez = z
l = l+1
if(PPS1 == 2):
tList = []
xList = []
yList = []
zList = []
t = 0
x = 0
y = 0
z = 0
a1.clear()
a1.plot(tList, xList, label = "ax")
a1.plot(tList, yList, 'r', label = "ay")
a1.plot(tList, zList, 'g', label = "az")
a1.set_ylim(-1,1)
a1.set_xlabel("Time (ms)")
a1.set_ylabel("Acceleration (g)")
a1.legend()
def GenerateGraph1(Master):
dataPlot = FigureCanvasTkAgg(F1, master=Master)
dataPlot.show()
dataPlot.get_tk_widget()
display1 = tk.Canvas(Master, width=100, height=400, bg ="white")
display1.pack(side = 'right')
button1 = tk.Button(display1, text='Play', command=Play1, font='Times 12', bd=5,
height = 2, width = 10, anchor = 'w').grid(row = 0, column = 0)
button2 = tk.Button(display1, text='Pause', command=Pause1, font='Times 12', bd=5,
height = 2, width = 10, anchor = 'w').grid(row = 1, column = 0)
button3 = tk.Button(display1, text='Stop', command=Stop1, font='Times 12', bd=5,
height = 2, width = 10, anchor = 'w').grid(row = 2, column = 0)
button4 = tk.Button(display1, text='Extract Data', command=Extract1, font='Times 12', bd=5,
height = 2, width = 10, anchor = 'w').grid(row = 3, column = 0)
button5 = tk.Button(display1, text='Save Data', command=Save1, font='Times 12', bd=5,
height = 2, width = 10, anchor = 'w').grid(row = 4, column = 0)
button5 = tk.Button(display1, text='Save Graph', command=SaveGraph1, font='Times 12', bd=5,
height = 2, width = 10, anchor = 'w').grid(row = 5, column = 0)
button5 = tk.Button(display1, text='Send Mail', command=Save1, font='Times 12', bd=5,
height = 2, width = 10, anchor = 'w').grid(row = 6, column = 0)
toolbar = NavigationToolbar2TkAgg(dataPlot, Master)
toolbar.update()
dataPlot._tkcanvas.pack()
def show_frame():
frame = GenerateGraph(Graph)
frame.tkraise()
Main = tk.Tk()
init()
n = ttk.Notebook(Main, width= 800, height = 400)
n.grid(row=6,column=0, columnspan=9)
n.columnconfigure(0, weight=1)
n.rowconfigure(6, weight=1)
f1 = ttk.Frame(n);
n.add(f1, text='Acceleration vs Time')
GenerateGraph1(f1)
ani1 = animation.FuncAnimation(F1, animate1, interval=100)
mainloop()
Arduino code is:
int toggle1 = 0;
boolean Graph = 0;
int x = 0;
int y = 0;
int z = 0;
int i = 0;
const int groundpin = 18; // analog input pin 4 -- ground
const int powerpin = 19; // analog input pin 5 -- voltage
const int xpin = A3; // x-axis of the accelerometer
const int ypin = A2; // y-axis
const int zpin = A1; // z-axis (only on 3-axis models)
#include <elapsedMillis.h>
elapsedMillis timeElapsed;
void Acceleration(){
Serial.print(timeElapsed);
Serial.print("\n");
Serial.print(analogRead(xpin));
Serial.print("\n");
Serial.print(analogRead(ypin));
Serial.print("\n");
Serial.print(analogRead(zpin));
Serial.print("\n");
}
void setup()
{
Serial.begin(115200);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(xpin, INPUT);
pinMode(ypin, INPUT);
pinMode(zpin, INPUT);
Serial.write('1');
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 25000; // compare match register 16MHz/64/10Hz
TCCR1B |= (1 << WGM12); // CTC mode
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS11);
pinMode(groundpin, OUTPUT);
pinMode(powerpin, OUTPUT);
digitalWrite(groundpin, LOW);
digitalWrite(powerpin, HIGH);
}
ISR(TIMER1_COMPA_vect){
if(Graph == 1){
Acceleration();
}}
void loop() {
String brightness, recieve, r1;
int b1, b2, ledPin;
while(Serial.available() == 0) {}
recieve = Serial.readStringUntil('y');
r1 = recieve + "t";
if(recieve == "SendData"){Graph = 1;}
if(recieve == "StopData"){Graph = 0;timeElapsed = 0;}
if(recieve == "motor1"){
ledPin = 8;
while(Serial.available() == 0){}
brightness = Serial.readStringUntil('y');
b1 = brightness.toInt();
analogWrite(ledPin, b1);}
if(recieve == "motor2"){
ledPin = 9;
while(Serial.available() == 0){}
brightness = Serial.readStringUntil('y');
b1 = brightness.toInt();
analogWrite(ledPin, b1);}
}
}
I am taking data from a vibration sensor. I used stopwatch to time the difference between the time that the vibrations actually started and the time at which the graph began to show the change in data. For the first data set the time difference was 5 seconds, for data set 2 the difference was 1 minute 10 seconds and for the third set it was 2 minutes. The effect became more pronounced as I added a second graph and the rest of my GUI. I need this software to be able to run for hours which means at one point my GUI might become unresponsive and I also need the data to be real-time. What could be the problem causing this and how do I solve it. There may be a better way to show real-time data in GUI as a graph but since I am new to python I dont know.
this simple animation example will plot a new red dot every second, the method should be more stable than what you're doing; I've had an app running over 4 months that plots once a minute like this:
import matplotlib.pyplot as plt
import random
import time
plt.ion()
x = 0
while x<100:
y = random.random()
plt.plot(x,y,marker='.',c='red')
x+=1
time.sleep(1)
plt.tight_layout()
plt.show()
plt.pause(0.1)
You said you need it to be "real time", but it may be that the execution time of your code is taking longer than the 0.1 seconds that you get new data. It might be best to update the graph every 10 data points; or as I'm doing... once a minute.

Categories

Resources