A Circular Reference

Adventures of a vagabond electron.

Real Time Plotting With Matlab

| Comments

Introduction

The need to plot (and filter) digital data from a sensor or front end circuit is ubiquitous in embedded systems. It’s always good to plot/filter/process the data in the same environment, so it’s always good to plot data in Matlab (if you have access to it). This post will talk about how to write a simple .m file to read data from the serial port of a PC and plot it onto a figure. We will do this in “real-time”, kind of like how an oscilloscope does.

Implementation

I assume that you already have a microcontroller or something else that will sample the analog signal you want to plot, convert the HEX values into ASCII and send it over a UART/RS232 interface to your PC. The problem this post addresses is capturing this data from Matlab and plotting it continuously.

The capture part is really straight forward, you just have to create a serial port object, open it and perform fread() on it, like shown below:

1
2
3
4
5
6
7
8
9
10
s = serial('COM1'); %assigns the object s to serial port
set(s, 'InputBufferSize', 1024); %number of bytes in input buffer
set(s, 'FlowControl', 'hardware');
set(s, 'BaudRate', 19200);
set(s, 'Parity', 'none');
set(s, 'DataBits', 8);
set(s, 'StopBit', 1);
set(s, 'Timeout',10);
fopen(s); %opens the serial port
a=fread(s,1,'char'); %read 1 byte to a, make sure that the input buffer size is > the no of bytes you read.

Once you get the data into matlab using fread(), the next problem is plotting this data using plot(). By default, plot() clears old data in the figure and re-draws the figure at every call. To avoid this and to have plot() append data you need to set hold on

Now you have a graph that is updated in real time, with each sample. This might be good enough if your sampling rate is slow (a few 100mS or so); but for a faster sampling rate (mine was 4mS) it is too slow and soon my PC started catching fire. More importantly, the real strength of Matlab/Octave lies in vector operations – and it really does well in handling large chunks of data.

So to improve the performance, we modify the design to `fread()’ 1 second worth of samples and plot all of that data in one shot, every second. Further, to create an oscilloscope effect, one screen will display X seconds of data; after that the screen will be refreshed and another X seconds are displayed 1s at a time. This goes on for Y number of times.

Now ideally, you want Y to be infinite, and the capture should only stop when you press a button or something. So we add a callback function myCallback for the WindowButtonDownFcn event to cause the capture to stop when you click on the plot figure with your mouse.

Notes

While debugging my code I encountered a few problems:

  • If for some reason, your script breaks and you are not able to close the serial port, the next time when you try to run the script you will get a port open error. One way to solve this is the execute the commands
1
newobjs = instrfind ; fclose(newobjs);

at the begining of the script.

  • If matlab does not receive data on the serial port, the object times out and you get a warning. You could catch this by something like:
1
2
3
4
5
6
7
8
9
10
11
lastwarn(''); % reset lastwarn 
try
   a=fread(s,Fs*Ip_Data_Size,'char'); %read 1s data 
   if(~isempty(lastwarn))
       error(lastwarn)
   end
catch err
    disp('Timeout occurred, exiting');
    fclose(s); %close the serial port 
    return; % Stop Script 
end
  • It is also faster to have calculate the X and Y scales statically instead of using
1
axis auto;

With that you should have a nice real time plotter working as in this video. The next step is to add on-the-fly filtering.

The code for the plotter is here. Each input data sample is assumed to be in the form +xxxx- where xxxx are any hex character in ASCII. For example the data samples of 0x123F and 0xD278 would be sent as +123F-+D278- .. and so on.

Comments