MATLAB Answers

0

How can I read the latest data at a specified frequency which is lesser than the frequency at which data is coming to a serial port?

I would like to know if there is any way to read the data which comes after every five seconds without having to worry about input buffer getting full.
My MATLAB code is grabbing data from the serial port which is pushed there at a rate of 10Hz(say) by a device. I would like to be able to read the latest string from the buffer every 5 seconds (say), and ignore the rest of it.

2 Answers

Answer by MathWorks Support Team on 22 May 2012
 Accepted Answer

There are four ways in which the data can be read at a specified frequency which is lesser than the frequency at which data is coming to a serial port without worrying about the input buffer getting full.
These are as given below. Option 1 is most recommended.
1) Set 'ReadAsyncMode' property to 'manual' for the serial port object.
This tells MATLAB to discard any data which arrives until you specifically ask to read data using the READASYNC command. Any read command you execute, will get whatever data arrives after that point. If data arrives infrequently, you will have to wait for the data. You can also specify a certain number of bytes to read using the READASYNC command.
One issue you will have to deal with is a partial packet, where you request to read in the middle of a packet arriving. You will need a reliable way to read at least two packets of data (and thus insuring that you will have at least one full packet regardless of when the read operation started) and be able to detect the start of the packet.
2) Only open the port when you want to receive data.
If the port is closed, data is not read. However, you could run into some issue here with how the sending device reacts to the port not being open. You could experiment with this option but it is not recommended.
3) Flush the buffer and then read
Here you would execute an FREAD to read all the bytes currently in the input buffer using the 'BytesAvailable' property of the serial port object. Then start a new read. This would be the same as option 1 but with some extra code and time on your part. Additionally, flushing the read buffer takes time and may have a noticeable impact on the acquisition rate if the rates are near or higher than 30Hz or if the input data is large. Hence option 1 is recommended over this option.
If you have the Instrument Control toolbox, you can also use the FLUSHINPUT command to flush the serial port input buffer instead of doing a read operation to flush the data.
4) Use a callback (like the TimerFcn or BytesAvailableFcn) to periodically read all the data from the serial port, find the latest complete packet received, and store that packet.
The issues that have to be dealt with here are being able to detect the beginning and end of a packet of data, and may be to store any partial packets received at the end of the input buffer to pre-prepend to the next read command. You would just need to make sure the input buffer is large enough by setting the 'InputBufferSize' property and the callback executes frequently enough to prevent loss of data. A good rule of thumb is to not plan on a callback executing more that 10 times per second. If MATLAB will be busy doing other operations, however, this is not a reliable method, because there is no way to predict how frequently the callback will be called when MATLAB is busy performing other operations.

  1 Comment

Thanks for your answer. I have the same problem but in Simulink when using Packet Input block from real time toolbox. Do you have any solution in Simulink?

Sign in to comment.


Answer by Domenico Perillo on 26 Jul 2017

Hello, I am having the same issues so I am trying to apply solution #1. However I am still unable to properly read serial port (about 212Hz) at my specified frequency (20 Hz); Below there is the code I am using, any help is appreciated, thanks.
% code
%RESETTING MATLAB ENVIRONMENT
instrreset
clear
clc
close all
global delta_t; delta_t=0.05; %sample time
dim=1000;
data_t=zeros(dim,6); % data log
%%START
s=serial('COM7','InputBufferSize',512,'Baudrate',115200);
s.ReadAsyncMode = 'manual';
s.Terminator = 'LF';
i=0; salti=0;
fopen(s);
t0 = clock;
while etime(clock,t0) < 60 % 1 minute data acquisition
tic
i=i+1;
stopasync(s);
readasync(s);
data=fscanf(s,'n,%f,%f,%f,%f,%f,%f,x\n');
data=transpose(data);
if length(data)~=6 %if a partial packet is read then go back
i=i-1; %and read again till you read a complete one
salti=salti+1;
continue
end
data_t(i,:)=data; %data logging
pause(delta_t - toc); %wait for sample time
end
fclose(s);
end

  0 Comments

Sign in to comment.