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

8 visualizaciones (últimos 30 días)
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 comentario
Nicolas
Nicolas el 27 de Feb. de 2024
Editada: Nicolas el 27 de Feb. de 2024
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

Iniciar sesión para comentar.

Respuesta aceptada

Fangjun Jiang
Fangjun Jiang el 27 de Feb. de 2024
Editada: Fangjun Jiang el 27 de Feb. de 2024
  2 comentarios
Nicolas
Nicolas el 1 de Mzo. de 2024
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 el 1 de Mzo. de 2024
Editada: Fangjun Jiang el 1 de Mzo. de 2024
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←↵'}

Iniciar sesión para comentar.

Más respuestas (0)

Productos


Versión

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by