Plotting serial data using GNUplot and Python

Sometimes it can be useful or necessary to plot some data that you get from your microcontroller. As most microcontrollers do have a USART peripheral the data to be plotted can be sent to the computer via the serial connection.

The most popular program for plotting and working with datasets and performing mathematical operations on them is probably MATLAB (Octave being an open source alternative).

When it comes to simply plotting a stream of data there is a much easier method to do so – it’s even free and fully open source!

plot

GNUplot is a handy program operated from the command line that let’s you plot mathematical functions and also allows reading and plotting data from simple text files. In conjunction with the scripting language Python and a bash script I managed to fully automate the process of reading the data from the serial port, writing it to a file and plotting it.

In order to use the script you will have to install GNUplot, Python and the Python serial module if you haven’t done this already:

sudo apt-get install gnuplot python python-serial

Now let’s have a look at the Python script that takes the serial data and saves it to a file:

read.py

#!/usr/bin/env python

# import the serial module so we can access the serial port
import serial 

# set up serial port
serialPort0 = serial.Serial('/dev/ttyACM0', 19200)

# open file object in write mode
dataFile = open('data.dat', 'w')
 
# get number of samples to take
# don't prompt user --> piped in from bash script
numberSamples = int(raw_input(""))
 
# get specified number of samples
for i in range(numberSamples):
  print i # output sample number to screen
  
  reading0 = serialPort0.readline()
  
  dataFile.write(str(i) + ' ' + str(reading0)) # write sample number and reading to the file
  
# close file object, good practice
dataFile.close()

# close serial port to free it for other applications
serialPort0.close()

The script opens the serial port /dev/ttyACM0 at 19200 baud. You might want to change this line to fit your needs.

The it reads in the number of samples to take from the commmand promt, this value is given by the bash script.

It will count up the number of samples and read in one line of data from the serial port. The sample number along with the reading will be written
to the file data.dat

In my case the microcontroller just sends a raw ADC reading via the serial port followed by a linefeed character: 1023\n.

This is an excerpt of the data file used to generate the above plot:

0 572
1 606
2 229
3 271
4 281
5 250

And this is the bash script that takes the number of samples, calls the python script with the specified number of samples and instructs GNUplot to plot the data found in the file:

read.sh

#!/bin/bash

echo "Sampling..."

# execute python script to sample and save data
# number of samples is given by first argument of this script
echo $1 | ./read.py 
# instruct gnuplot to plot sampled data
gnuplot -persist -e "set xlabel 'Sample number'; set ylabel 'ADC reading'; set grid; plot 'data.dat' using 1:2 with lines" 

echo "Done!"

You can call the script by simply typing the name of the script followed by the number of samples, e.g. 100:

./read.sh 100

This line will read 100 values from the serial port and the plot them.

You can change the labels on the X- and Y-Axis by changing xlabel and ylabel respectively.

For more info on GNUplot and the Python serial module visit the GNUplot project page and the PySerial page

6 thoughts on “Plotting serial data using GNUplot and Python

  1. HI,
    Really thanks for your example, I just wonder how can I adjust it into windows environment?
    Can I replace the data.dat into data.txt? And what should I replace the bash script for in windows?
    Also, what should I replace for in ” serialPort0 = serial.Serial(‘/dev/ttyACM0′, 19200) ” if I’m using STM32F4discovery and want to read out the data that generated by MEMS?
    sorry, I’m a totally new guy in Python and STMF4… thanks for your help!

    1. The Python module used to read out the serial port is called PySerial which is available for Python 2.7 and Python 3.
      Have a look at their documentation, it will clear up how serialPort0 = serial.Serial(‘/dev/ttyACM0′, 19200) works. Basically it opens the serial port /dev/ttyACM0 at 19200 baud. On Windows that would be something like COM3 (change it to fit your situation).

      The script just takes the received data and plots it using gnuplot. You will have to look at the gnuplot documentation to find out how the script works.

      Cheers,
      Elia

Leave a Reply

Your email address will not be published. Required fields are marked *


× 5 = forty