Live plotting data from the serial port using Python, Matplotlib and an Arduino

Yesterday I set out to figure out how to live plot data measured by my Arduino using Python and Matplotlib. While there is plenty information and code how to achieve this, I missed some easy and understandable code. So how to do this:

First we need some Arduino sketch that uses the serial port to send data. I’ve used some temperature setup from the Arduino Starter Kit found here:
http://www.oomlout.com/oom.php/products/ardx/circ-10

Now let’s take a look at the python code. You need pySerial, numpy and matplotlib of course.

import serial
import numpy as np
from matplotlib import pyplot as plt

Then you open the connection to the serial port:

ser = serial.Serial('/dev/ttyACM0', 9600)

Now we need to activate matplotlib’s interactive mode:

plt.ion() # set plot to animated

After this we select the range of the x-axis and fill those 50 values with zeros:

ydata = [0] * 50

Now we start the plot. To make matplotlib aware of more incoming data don’t forget the comma after ‘line’:

ax1=plt.axes()  

# make plot
line, = plt.plot(ydata)
plt.ylim([10,40]) # set the y-range to 10 to 40

Now comes the tricky part. First i read data from the serial port and check if it’s in the right format. The Arduino returns values in the form “x.y” where x and y are numbers. Sometimes the script reads two values at once which would lead to an error while plotting so I split the incoming value at the dot and check if there’s only one dot in there and the length of the split is 2.

To understand the following part I need to explain what I did to get the plot working. At the moment we have the x-axis with 50 zeros. Now I read one value at a time from the serial port. append it to the y-data array and afterwards I delete the first element from the y-data array so that the total number of elements in my array is 50 at all times.

Now I automatically adjust the y-limits by using the min and max values from the y-data array and give it a +-10 range.

And finally I tell matplotlib that there is new data to plot by using line.set_xdata and line.set_ydata. To refresh the plot you just have to use plt.draw():

# start data collection
while True:  
	data = ser.readline().rstrip() # read data from serial 
                                   # port and strip line endings
	if len(data.split(".")) == 2:
		ymin = float(min(ydata))-10
		ymax = float(max(ydata))+10
		plt.ylim([ymin,ymax])
		ydata.append(data)
		del ydata[0]
		line.set_xdata(np.arange(len(ydata)))
        line.set_ydata(ydata)  # update the data
        plt.draw() # update the plot

And the whole script altogether:

import serial
import numpy as np
from matplotlib import pyplot as plt
ser = serial.Serial('/dev/ttyACM0', 9600)

plt.ion() # set plot to animated

ydata = [0] * 50
ax1=plt.axes()  

# make plot
line, = plt.plot(ydata)
plt.ylim([10,40])

# start data collection
while True:  
	data = ser.readline().rstrip() # read data from serial 
                                   # port and strip line endings
	if len(data.split(".")) == 2:
		ymin = float(min(ydata))-10
		ymax = float(max(ydata))+10
		plt.ylim([ymin,ymax])
		ydata.append(data)
		del ydata[0]
		line.set_xdata(np.arange(len(ydata)))
        line.set_ydata(ydata)  # update the data
       	plt.draw() # update the plot

3 Gedanken zu „Live plotting data from the serial port using Python, Matplotlib and an Arduino

  1. Hello!

    I tried this code on my PC, and I could get the plot as expected. However, the process was a bit slow, and the program even stopped responding. Do you know what can be done to fix it?

    Thank you!

    Lucas.

    1. I think that the program is slow and hangs because of the min and max searches at the beginning of the loop.

      You can set up the limits statically in the minimum and máximum expected values and do not recalculate them within the loop. I think min and max invoked over an unordered array are of cost n^2.

  2. Hi!
    I tested this script on my PC (Windows system) but I had a problem.
    The graph window went blank and started a loop trying to open (the hourglass symbol)!
    Have you seen this problem?

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>