Simulink - Obtain fixed-width vector from MATLAB function block output

8 次查看(过去 30 天)
Hello,
For context, I am using the STM32 Hardware Support Add-On and Simulink in order to deploy a model on a STM32 MCU.
After some signal processing, the model extracts 2 values (double), and I want these values to be sent through USART to another device.
This is the model I've come up with :
My goal is to generate a uint8 vector containing :
'A = ___ | B = ___'
My first idea for this seemingly trivial task was to use sprintf :
function data = fcn(valA, valB)
msg = sprintf('A = %06.2f | B = %06.2f\r\n', valA, valB);
data = uint8(msg);
I got this error message :
Error:'data' is inferred as a variable-size matrix, but its size is specified as inherited or fixed. Verify 'data' is defined in terms of non-tunable parameters, or select the 'Variable Size' check box and specify the upper bounds in the Size box.
However, since I'm running code generation tools, I cannot use variable-size signals, so ticking the "Variable Size" box is not an option. I have tried many things, but could not solve this issue. Here is what I ended up with :
function data = USART(valA, valB)
%% Min/max values definition
% Min/max values for A and B are defined to keep them at a fixed number
% of characters
max_A = 999.99;
max_B = 999.99;
valA = min(max_A, valA);
valA = max(0, valA);
valB = min(max_B, valB);
valB = max(0, valB);
%% Truncating values 2 digits after decimal point
% A and B are being rounded 2 digits after the decimal point
valB = round(valB * 100) / 100;
valA = round(valA * 100) / 100;
%% USART frame generation
% If the frame exceeds a set number of characters (50), it is truncated.
% If the frame character count is below a set number of characters (50), it
% is padded with spaces until it reaches this count.
% Note : this messes up any carriage return/new line.
message = sprintf('A = %06.2f | B = %06.2f', valA, valB);
if numel(message) > 50
message = message(1:50);
elseif numel(message) < 50
message = [message, repmat(' ', 1, 50-numel(message))];
end
data = uint8(message);
end
My reasoning is that :
  1. valA or valB have a maximum character count (both before/after the decimal point) ;
  2. The sprintf formatting ensures that if the values are smaller than the maximum character count, the missing characters are padded with zeros ;
  3. The truncating/padding instructions ensures that signal width is constant (redundant).
This functions runs great in MATLAB, and generates a fixed length uint8 vector no matter what values valA and valB were given, positive, negative, small, big...
However, in Simulink, same error remains.
The only case where I can get any output from data is when I use hard coded values :
function data = fcn()
valA = 123.123;
valB = 456.456;
message = sprintf('A = %06.2f | B = %06.2f\r\n', valA, valB);
data = uint8(message);
This compiles and gets deployed on the target device, but hard-coded values have no practical use.
How can this be solved ? How can I get my desired output ?
Thanks in advance,
Nicolas
  1 个评论
Nicolas
Nicolas 2024-2-27
编辑:Nicolas 2024-2-27
I would also be grateful if someone could share an example model that sends data from a variable through the USART Write block.
Thanks again,
Nicolas

请先登录,再进行评论。

采纳的回答

Fangjun Jiang
Fangjun Jiang 2024-2-27
编辑:Fangjun Jiang 2024-2-27
  2 个评论
Nicolas
Nicolas 2024-3-1
Thanks, this is the block I needed (and I couldn't find).
Quick note for anyone using this block with STM32 features : for some reason, Compose String block's %f formatting option didn't work for me, and I had to make another subsystem to convert my doubles into strings.
Not pretty, but it seems to work pretty good.
Fangjun Jiang
Fangjun Jiang 2024-3-1
编辑:Fangjun Jiang 2024-3-1
What is the issue, @Nicolas ? You had the correct format to generate the fixed width numerical numbers for a double data type.
valA = 123.123;
valB = 456.456;
message = sprintf('A = %06.2f | B = %06.2f\r\n', valA, valB)
message =
'A = 123.12 | B = 456.46 '
compose("A = %06.2f | B = %06.2f\r\n", valA, valB)
ans =
"A = 123.12 | B = 456.46 "
compose('A = %06.2f | B = %06.2f\r\n', valA, valB)
ans = 1×1 cell array
{'A = 123.12 | B = 456.46←↵'}

请先登录,再进行评论。

更多回答(0 个)

产品


版本

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by