I have a number of sensors attached to my Raspberry Pi; I'm sending their data to my PC twice a second using TCP. I would like to continuously graph these values using matplotlib.
The method I'm currently using seems inefficient (I'm clearing the subplot and redrawing it every time) and has some undesirable drawbacks (the scale gets readjusted every time; I would like it stay from 0.0 - 5.0). I know there's a way of doing this without having to clear and redraw but can't seem to figure it out. The following is my current code:
import socket import sys import time from matplotlib import pyplot as plt # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connect the socket to the port where the server is listening server_address = ('192.168.0.10', 10000) print >>sys.stderr, 'connecting to %s port %s' % server_address sock.connect(server_address) # Initial setup for the bar plot plt.ion() fig = plt.figure() ax = fig.add_subplot(1,1,1) x = [1,2,3] labels = ['FSR', 'Tilt', 'IR'] ax.set_xticklabels(labels) y = [5.0,5.0,5.0] ax.bar(x,y) fig.autofmt_xdate() plt.draw() #Grab and continuously plot sensor values try: for i in range(300): amount_received = 0 amount_expected = len("0.00,0.00,0.00") # Receive data from RasPi while amount_received < amount_expected: data = sock.recv(14) amount_received += len(data) print >>sys.stderr, 'received "%s"' % data # Plot received data y = [float(datum) for datum in data.split(',')] ax.clear() ax.bar(x,y) plt.draw() time.sleep(0.5) #Close the socket finally: print >>sys.stderr, 'closing socket' sock.close()
You could use
Plot the bar plot once and save the return value, which is a collection of Rects:
rects = plt.bar(range(N), x, align='center')
Then, to change the height of a bar, call
for rect, h in zip(rects, x): rect.set_height(h)
import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation def animate(frameno): x = mu + sigma * np.random.randn(N) n, _ = np.histogram(x, bins, normed=True) for rect, h in zip(patches, n): rect.set_height(h) return patches N, mu, sigma = 10000, 100, 15 fig, ax = plt.subplots() x = mu + sigma * np.random.randn(N) n, bins, patches = plt.hist(x, 50, normed=1, facecolor='green', alpha=0.75) frames = 100 ani = animation.FuncAnimation(fig, animate, blit=True, interval=0, frames=frames, repeat=False) plt.show()
Since i am doing something very similar with my Raspberry Pi, i can share my details of the same. It is inspired by this blog post.
The code for server side which pushes the data can be found here. You can probably see that after installing the dependencies, it is very similar to your code and eventually you would find a
socket.send() even in my code.
For the client side, this is the link to the HTML file and this is the JS that gets executed on the browser, which uses Flot Plotting library. I am sure the demo on their home page is awesome enough to be noticed!