Serial Receive Block Variable Data Size

6 views (last 30 days)
Cihanoglu
Cihanoglu on 30 Jun 2025
Edited: Cihanoglu on 3 Jul 2025
Hi,
I’m working with a data logger that sends measurements over a USB serial interface. I’d like to read the data using Simulink’s Serial Receive block, but I’m running into a problem: the block requires a fixed message length, while my measurements vary in digit count, so each message can be longer or shorter.
I’ve tried setting a maximum data size, but then the block misses the terminator since it relies solely on the fixed length. I’ve also experimented with a smaller fixed size in non-blocking mode, buffering incoming bytes and then parsing complete messages—but approaches that i tried introduce delays that are unacceptable for my application.
I’d appreciate any suggestions or solutions to handle variable-length serial messages in Simulink without significant latency.

Answers (1)

Anjaneyulu Bairi
Anjaneyulu Bairi on 3 Jul 2025
Hey,
Currently, the Serial Receive block in the Instrument Control Toolbox does not support string outputs or variable-size outputs. Depending on your workflow, there are alternative methods for reading the data:
  • You can use a MATLAB Function block that leverages MATLAB's serialport functionality to read the data.
  • Alternatively, you can configure the Serial Receive block to read the data as a stream of uint8 values. These can then be buffered and converted to strings outside of the block. To do this, set the data type to uint8, disable the header and terminator, and specify a fixed output size. Keep in mind that, depending on the output size you specify, the data from the block may not contain a complete NMEA string and could span across multiple NMEA strings.
Hope this helps!
  1 Comment
Cihanoglu
Cihanoglu on 3 Jul 2025
Edited: Cihanoglu on 3 Jul 2025
Hi thanks for the answer,
I’m having trouble using serialport and serial objects with Simulink—they’re not supported for code generation. In MATLAB, I can read the data with these just fine, but my application requires working within Simulink.
The data logger sends messages already in uint8 format. I don’t convert them to strings because Simulink code generation doesn’t support string functions, so I parse the data directly in uint8.
I'm using no terminator, no header, and a fixed maximum size. This allows me to receive the data, but the messages get shifted. For example, the block expects 36 bytes. If I send only 24, the remaining 12 bytes are missing, and the message shifts by 12 bytes in every cycle.
Currently, I use a buffer: I collect each message into the buffer and only output messages that match the correct format. However, this introduces delays and doesn’t always work reliably. Because the control parameters for the right format shifts also.
I’m attaching my buffer code and example input messages and output messages.
function [lineOut, lenOut, valid] = CRLFStreamParser(dataIn,count)
MAX_BUF = int32(512);
MAX_LINE = int32(256);
CR = uint8(13);
LF = uint8(10);
persistent buf bufLen
if isempty(buf)
buf = zeros(MAX_BUF,1,'uint8');
bufLen = int32(0);
end
lineOut = zeros(MAX_LINE,1,'uint8');
lenOut = int32(0);
valid = false;
lastNZ = int32(0);
for i = int32(count):-1:1
if dataIn(i)~=0
lastNZ = i;
break;
end
end
n = min(lastNZ, MAX_BUF - bufLen);
if n>0
d = dataIn(1:n);
buf(bufLen + (1:n)) = d(:);
bufLen = bufLen + n;
end
endIdx = int32(0);
for i = int32(1):(bufLen-1)
if buf(i)==CR && buf(i+1)==LF
endIdx = i+1;
break;
end
end
if endIdx>0
lenOut = min(endIdx, MAX_LINE);
lineOut(1:lenOut) = buf(1:lenOut);
valid = true;
rem = bufLen - endIdx;
if rem>0
buf(1:rem) = buf(endIdx+1:bufLen);
end
bufLen = rem;
end
end

Sign in to comment.

Products


Release

R2024a

Community Treasure Hunt

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

Start Hunting!