Writing TLC for Level 2 M files s function

9 views (last 30 days)
Hello Everyone !
I am having a lot of problems in writing TLC file for my Level 2 Matlab sfunction while configuration of the 'Simulink Desktop Real-time' to external hardware.
I will be very grateful if anyone can help or guide me. I am attaching the s-function for the reference:
function SV_iG5A_L2(block)
%MSFUNTMPL_BASIC A Template for a Level-2 MATLAB S-Function
% The MATLAB S-function is written as a MATLAB function with the
% same name as the S-function. Replace 'msfuntmpl_basic' with the
% name of your S-function.
% Copyright 2003-2018 The MathWorks, Inc.
%%
%% The setup method is used to set up the basic attributes of the
%% S-function such as ports, parameters, etc. Do not add any other
%% calls to the main body of the function.
%%
setup(block);
%endfunction
%% Function: setup ===================================================
%% Abstract:
%% Set up the basic characteristics of the S-function block such as:
%% - Input ports
%% - Output ports
%% - Dialog parameters
%% - Options
%%
%% Required : Yes
%% C MEX counterpart: mdlInitializeSizes
%%
function setup(block)
% Register number of ports
block.NumInputPorts = 2;
block.NumOutputPorts = 1;
% Setup port properties to be inherited or dynamic
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;
% Override input port properties
block.InputPort(1).Dimensions = 1;
block.InputPort(1).DatatypeID = 0; % double
block.InputPort(1).Complexity = 'Real';
block.InputPort(1).DirectFeedthrough = true;
block.InputPort(2).Dimensions = 1;
block.InputPort(2).DatatypeID = 0; % double
block.InputPort(2).Complexity = 'Real';
block.InputPort(2).DirectFeedthrough = true;
% Override output port properties
block.OutputPort(1).Dimensions = 1;
block.OutputPort(1).DatatypeID = 0; % double
block.OutputPort(1).Complexity = 'Real';
% Register parameters
block.NumDialogPrms = 0;
% Register sample times
% [0 offset] : Continuous sample time
% [positive_num offset] : Discrete sample time
%
% [-1, 0] : Inherited sample time
% [-2, 0] : Variable sample time
block.SampleTimes = [1/10 0];
% Specify the block simStateCompliance. The allowed values are:
% 'UnknownSimState', < The default setting; warn and assume DefaultSimState
% 'DefaultSimState', < Same sim state as a built-in block
% 'HasNoSimState', < No sim state
% 'CustomSimState', < Has GetSimState and SetSimState methods
% 'DisallowSimState' < Error out when saving or restoring the model sim state
block.SimStateCompliance = 'DefaultSimState';
%% -----------------------------------------------------------------
%% The MATLAB S-function uses an internal registry for all
%% block methods. You should register all relevant methods
%% (optional and required) as illustrated below. You may choose
%% any suitable name for the methods and implement these methods
%% as local functions within the same file. See comments
%% provided for each function for more information.
%% -----------------------------------------------------------------
% block.RegBlockMethod('PostPropagationSetup', @DoPostPropSetup);
% block.RegBlockMethod('InitializeConditions', @InitializeConditions);
% block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Outputs', @Outputs); % Required
% block.RegBlockMethod('Update', @Update);
% block.RegBlockMethod('Derivatives', @Derivatives);
block.RegBlockMethod('Terminate', @Terminate); % Required
%end setup
%%
%% PostPropagationSetup:
%% Functionality : Setup work areas and state variables. Can
%% also register run-time methods here
%% Required : No
%% C MEX counterpart: mdlSetWorkWidths
%%
% function DoPostPropSetup(block)
% block.NumDworks = 1;
%
% block.Dwork(1).Name = 'x1';
% block.Dwork(1).Dimensions = 1;
% block.Dwork(1).DatatypeID = 0; % double
% block.Dwork(1).Complexity = 'Real'; % real
% block.Dwork(1).UsedAsDiscState = true;
%%
%% InitializeConditions:
%% Functionality : Called at the start of simulation and if it is
%% present in an enabled subsystem configured to reset
%% states, it will be called when the enabled subsystem
%% restarts execution to reset the states.
%% Required : No
%% C MEX counterpart: mdlInitializeConditions
%%
% function InitializeConditions(block)
%end InitializeConditions
%%
%% Start:
%% Functionality : Called once at start of model execution. If you
%% have states that should be initialized once, this
%% is the place to do it.
%% Required : No
%% C MEX counterpart: mdlStart
%%
% function Start(block)
%
% block.Dwork(1).Data = 0;
%end Start
%%
%% Outputs:
%% Functionality : Called to generate block outputs in
%% simulation step
%% Required : Yes
%% C MEX counterpart: mdlOutputs
%%
function Outputs(block)
cont=block.InputPort(1).Data;
freq_i=block.InputPort(2).Data;
m = modbus('serialrtu', 'COM3');
m.Parity = 'even';
m.Timeout = 1;
% m.BaudRate = 19200;
% Save the Server ID specified.
serverId = 1;
% Write a value 0 of type 'int16' to a Holding Register at address 6.
write(m, 'holdingregs', 5, freq_i, serverId, 'int16');
write(m, 'holdingregs', 6, cont, serverId, 'int16');
% outputs
% Holding Registers
% Read 5 Holding Registers of type 'int16' starting from address 7.
data = read(m, 'holdingregs', 10, 1, serverId, 'int16');
modbusData.Freq_O = data;
block.OutputPort(1).Data = modbusData.Freq_O;
%end Outputs
%%
%% Update:
%% Functionality : Called to update discrete states
%% during simulation step
%% Required : No
%% C MEX counterpart: mdlUpdate
%%
% function Update(block)
%
% block.Dwork(1).Data = block.InputPort(1).Data;
%end Update
%%
%% Derivatives:
%% Functionality : Called to update derivatives of
%% continuous states during simulation step
%% Required : No
%% C MEX counterpart: mdlDerivatives
%%
% function Derivatives(block)
%end Derivatives
%%
%% Terminate:
%% Functionality : Called at the end of simulation for cleanup
%% Required : Yes
%% C MEX counterpart: mdlTerminate
%%
function Terminate(block)
% end Terminate
  1 Comment
Faisal
Faisal on 12 Sep 2023
The following is the main part (output function) which can be considered as a shorter version of the above code:
function Outputs(block)
cont=block.InputPort(1).Data;
freq_i=block.InputPort(2).Data;
m = modbus('serialrtu', 'COM3');
m.Parity = 'even';
m.Timeout = 1;
% m.BaudRate = 19200;
% Save the Server ID specified.
serverId = 1;
% Write a value 0 of type 'int16' to a Holding Register at address 6.
write(m, 'holdingregs', 5, freq_i, serverId, 'int16');
write(m, 'holdingregs', 6, cont, serverId, 'int16');
% outputs
% Holding Registers
% Read 5 Holding Registers of type 'int16' starting from address 7.
data = read(m, 'holdingregs', 10, 1, serverId, 'int16');
modbusData.Freq_O = data;
block.OutputPort(1).Data = modbusData.Freq_O;

Sign in to comment.

Accepted Answer

Jan Houska
Jan Houska on 12 Sep 2023
Hi Faisal,
unfortunately you will not be able to write a TLC for this function that would be usable in Simulink Desktop Real-Time. This is because of the modbus object and its methods that do not have equivalent in compiled code and are not supported in the real-time kernel.
You have two possibilities. Either you can use the model in Connected IO mode which does not use code generation and your Level 2 MATLAB S-function would run as it is. Or, if you need Run In Kernel mode, you can use Packet Input and Packet Output block with the Serial Port driver and implement the data layer of the Modbus protocol using Simulink blocks.
Good Luck, Jan
  3 Comments
Jan Houska
Jan Houska on 14 Sep 2023
Hi Faisal,
the fact that model runs longer than required is due to the fact that it is too computationally (or I/O) intensive. You cannot make a model run faster by just running it in Connected IO mode. The fact that real-time requirements have not been met can be observed at the Missed Ticks output of any Simulink Desktop Real-Time block.
Without knowing your model, its complexity, required sample rate, etc., I don't know if it is realistic to improve its performance to meet real-time requirements. But this is where I'd start - using the profiler, I'd try to find out why is the model 6x slower than real time, optimize the slow parts, and stay with Connected IO mode that should then run fast enough for real time. One possible reason for the slow run could be if your S-function waits for data to be received. Generally, in a real time model, you should never wait - you just check the status of incoming data, read if some available, and continue whether data are available or not.
For Run In Kernel mode, you will not need to write a TLC. But Simulink Desktop Real-Time support for RS-232 is limited to raw data transmission and reception. So you will need to implement the Modbus data layer yourself, which may not be a simple task.
Good Luck, Jan
Faisal
Faisal on 24 Sep 2023
Hello Jan,
Thank you very much for the answers. Although your suggestions were accurate and will work for a single modbus connected to one serial port, it seemed I had another problem.
I was connecting two modbus objects through a single serial port. The sample-based connecting to one device, disconnecting, connecting anthor device and repetition of this process for the whole simulation run (at each sample) made the simulation slow. I guess it is not possible to connect two devices with one modbus through one serial port and run experiments synchronized with the system clock.
So, for future references to other peers:
I connected the one device outside the function call; cleared that modbus object; connected the new device and took measurements using while loop based on tic and toc function in the MATLAB script.
This solved the problem for taking measurements but I will need another bodbus hardware to connect both devices at the same time, which I have ordered.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!