matlab serial read too slow?

35 views (last 30 days)
tlawren
tlawren on 27 Apr 2012
I'm trying to read a serial device that is transferring data (120 bytes) at 10 Hz and I'm having trouble getting Matlab to keep up with the device. Is 120 bytes at 10 Hz too fast for Matlab? It doesn't seem like it should be.
Here is my code that creates and opens my serial object.
% Create serial object and open connection
ba = 120; % bytes
ser = serial('COM21',...
'BaudRate',115200,...
'InputBufferSize',10*ba,... % 10 times ba for monitoring
'BytesAvailableFcn',{@readser},...
'BytesAvailableFcnMode','byte',...
'BytesAvailableFcnCount',ba, ...
'UserData',ud ...
);
fopen(ser);
And, this is readser
function readser(obj,event)
% Read data
baa = obj.BytesAvailable;
fread(obj,baa,'uint8');
disp(ba);
The reason I'm thinking Matlab can't keep up with my device is because I get the following output in the Command Window.
120
120
120
240
0
Error using serial/fread (line 131)
SIZE must be greater than 0.
I've only displayed the last 3 120's. There could be 100's to 1000's before. Does this look like a speed issue in Matlab? How does the BytesAvailable callback get triggered and then there be 0 BytesAvailable? Does it get triggered faster than fread can clear the buffer?
EDIT: ba in readser should be baa. I know this doesn't matter, because the two variables reside in different scopes, so they can have the same name. It helps avoid confusion though.

Answers (2)

Walter Roberson
Walter Roberson on 27 Apr 2012
BytesAvailableFcn will be called for each time the count is reached. It gets called at 120 and then it gets called again at 240. When your call for 120 gets scheduled and finds 240 bytes there, it reads the 240 and empties the buffer, leaving 0 bytes for the already-scheduled call after that.
Your code should detect the 0 and skip the fread(), or else your code should only read ba bytes even when more are available, knowing that there is already a call scheduled to read the next ba bytes.
  6 Comments
Walter Roberson
Walter Roberson on 27 Apr 2012
You should avoid output in an input interrupt service routine. Output is relatively slow.
The output to the command window (via disp) has to be queued by MATLB in order to go out in the right order, and the MATLAB command window output driver has to interpret all of the output for proper formatting and in order to take care of underlining URLs, giving the correct color to error messages, and other fancy stuff. The graphics drivers have to get involved, frame buffering is needed, smooth scroll rather than jump scroll, everything has to be recorded in a buffer in order to allow the user to scroll backwards through the output, etc..
It is thus better for an input routine to do the minimum of work needed to keep the input stream working properly (e.g., might include checking CRC and sending back a NAK for the packet) together with any "hard real-time" response work. Anything that can wait for "soft real-time" or that is not real-time should usually be queued and handled by a lower-priority routine.
tlawren
tlawren on 30 Apr 2012
I removed the display line and let the code run and it still kicks out the error (SIZE must be greater than 0) after about 3-4 minutes. And, I don't have any packet checking functions in the callback yet either. I'm really starting to think that Matlab may not be able to handle what I'm trying to do. Or, the Matlab setup I've got can't handle what I'm trying to do. Would a compiled solution work better? I would like to stick with Matlab, but I may not be able to.
Also, I've considered configuring my BAFcn to read two packets at once, and thus reduce the total number of reads in half, but that changes my experiment, so I would like to avoid it.

Sign in to comment.


Sean de Wolski
Sean de Wolski on 27 Apr 2012
It looks rather like MATLAB is too fast and is trying to pull the data before it arrives (hence size of zero available).
  1 Comment
tlawren
tlawren on 27 Apr 2012
It seems to me like it is too slow. Using Walter's explanation below, a BAFcn call gets scheduled on one 120 count and then before the BAFcn can read the buffer, as second BAFcn is scheduled by another 120 count. Because the first BAFcn hasn't read the buffer when the call is scheduled, when the first BAFcn goes to read the buffer, there are actually two data sets there to read. After the first read, the second BAFcn goes to read the buffer (b/c it was previously scheduled) and there is nothing there, so it errors. Even if there was something there (a third BAFcn call scheduled), there will always be one too many scheduled calls. Eventually, there will be an error. Does this make sense? I'm kind of thinking on screen, so I may not make sense.

Sign in to comment.

Categories

Find more on Startup and Shutdown in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!