Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

writing a tlc file for Level-2 M-file S-function

583 views
Skip to first unread message

Arzhaev

unread,
Sep 3, 2010, 2:22:07 AM9/3/10
to
Hi all!
I’m a new in writing Level-2 M-file S-function and corresponding tlc file.
My wish is to generate code for working with sensors hardware xsens MTiG using COM.
My level-2 M-file S-function works in Simulink-model. But when I add a Target Preferences Block it’s required corresponding tlc file for S-function.
As you I understand that I have to write a corresponding .tlc file to tell RTW how to generate code for this S-Function. There are to many methods of external driver in setup and outputs block and no inputs.
What can I do to generate tlc file. My Level-2 M-file S-function is mapped below.
Thanks, Arzhaev.

function getMTdata(block)
%MSFUNTMPL_BASIC A template for a Leve-2 M-file S-function
% The M-file 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.
%
% It should be noted that the M-file S-function is very similar
% to Level-2 C-Mex S-functions. You should be able to get more
% information for each of the block methods by referring to the
% documentation for C-Mex S-functions.
%
% Copyright 2003-2009 The MathWorks, Inc.

%%
%% The setup method is used to setup 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 S-function block's basic characteristics such as:
%% - Input ports
%% - Output ports
%% - Dialog parameters
%% - Options
%%
%% Required : Yes
%% C-Mex counterpart: mdlInitializeSizes
%%
function setup(block)

% Register number of ports
block.NumInputPorts = 1;
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 = false;
% Override output port properties
block.OutputPort(1).Dimensions(1)= 1;
block.OutputPort(1).Dimensions(2)= 9;
block.OutputPort(1).DatatypeID = 0; % double
block.OutputPort(1).Complexity = 'Real';

% Register parameters
block.NumDialogPrms = 4;
block.DialogPrmsTunable = {'Tunable','Tunable','Tunable','Tunable'};

% 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 = [0.01 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 M-file 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('Outputs', @Outputs); % Required
block.RegBlockMethod('Update', @Update);
%block.RegBlockMethod('Derivatives', @Derivatives);
block.RegBlockMethod('Terminate', @Terminate); % Required
block.RegBlockMethod('SetInputPortSamplingMode', @SetInpPortFrameData);
block.RegBlockMethod('CheckParameters', @CheckPrms);
block.RegBlockMethod('ProcessParameters', @ProcessPrms);
global h;
h = actxserver('MotionTracker.CMT');
serial = 'XXXX';
try
h.cmtCreateInstance(serial);
catch
delete(h);
return;
end
baudrate = 0;
singleScanTimeout=1000;
scanTries=1;
portNumbers=h.cmtScanPorts(baudrate,singleScanTimeout,scanTries);
COMport=portNumbers;
try
h.cmtOpenPort(COMport,baudrate);

catch
delete(h);
return;
end
[deviceId] = h.cmtGetMtDeviceId(0);
dec2hex(deviceId);
h.cmtGotoConfig();
settings=1;%(counter)
samplefreq=120;
mode=2;%position + calibrated data
h.cmtSetDeviceMode(mode, settings, samplefreq, deviceId);
%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;
block.AutoRegRuntimePrms;
global h;


%%
%% 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;



%endfunction

%%
%% Outputs:
%% Functionality : Called to generate block outputs in
%% simulation step
%% Required : Yes
%% C-MEX counterpart: mdlOutputs
%%
function Outputs(block)
global h

if ~ishandle(h),
error('The HANDLE ////');
end
try
h.cmtGotoMeasurement(); % start processing data
% init data variable
Channels=9;
d=zeros(1,Channels);
MT_BeingPlotted = 0;
status=0;
DisplayMode='caldata';
[d,status,N]=MMT_get_data(h, Channels, MT_BeingPlotted, DisplayMode);
[m n]=size(d);
if m>0
block.OutputPort(1).Data= d;
end
catch %
cmtResult = h.cmtGetLastResult;
disp(['error occurred: ' num2str(cmtResult)]);
end


function [d, status, N] = MMT_get_data(h, Channels, MT_BeingPlotted, DisplayMode)

if nargin==4, % error in Channels input is not handled here....
if ~ishandle(h),
error('The HANDLE to the Motion Tracker Object (CMT) must be passed to this function');
end
else
error('too many or too few input arguments')
end

N = 0; % number of obtained samples
BufferMax = 1; % defined in CMT, see documentation
d=zeros(1,Channels); % init d
status=0; % reset for each new sample
deviceId = h.cmtGetMtDeviceId(MT_BeingPlotted);
% obtain all samples from CMT buffer
try
for i = 1:BufferMax,
%pause(0.001)
h.cmtGetNextDataBundle();

if strcmp(DisplayMode,'caldata'), % Determine which data to retrieve from CMT
data = h.cmtDataGetCalData(deviceId); % get calibrated data from local buffer
elseif strcmp(DisplayMode,'euler'),
data = h.cmtDataGetOriEuler(deviceId); % get orientation data from local buffer
elseif strcmp(DisplayMode,'quat'),
data = h.cmtDataGetOriQuat(deviceId); % get orientation data from local buffer
elseif strcmp(DisplayMode,'matrix'),
data = h.cmtDataGetOriMatrix(deviceId); % get orientation data from local buffer
end

data=double(data);% convert to double
N = N + 1;
d(N,1:Channels)=data(1:Channels); % copy read values to output
status = 1;
end
catch

end
%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)
% stop processing before removing object

clear all
%end Terminate
function SetInpPortFrameData(block, idx, fd)

block.InputPort(1).SamplingMode = 0;
block.OutputPort(1).SamplingMode = 0;

function ProcessPrms(block)

block.AutoUpdateRuntimePrms;

%endfunction
function CheckPrms(block)
Stheading = block.DialogPrm(1).Data;

if Stheading <= -pi || Stheading > pi
error('Step size must be a scalar between 0 and 1.');
end
Stlocation = block.DialogPrm(2).Data;
Stfrequency = block.DialogPrm(3).Data;

if (Stfrequency ~=50)&&(Stfrequency ~=100)
error('Frequency must be 50 or 100.');
end

%endfunction

Phil Goddard

unread,
Sep 14, 2010, 8:44:14 PM9/14/10
to

Writing tlc files is way to complicated to describe in any sort of detail via a newsgroup posting, and impossible to debug for anyone who doesn't have the particular driver that you are using.

You are going to have to spend some time reading the TLC section of the RTW documentation, looking at the examples, and then asking _specific_ questions to the newsgroup as you start writing your own tlc file.

Phil.

Lucas

unread,
Nov 16, 2010, 12:31:04 PM11/16/10
to
I'm having the same problems of Arzhaev. There is no way to generate such file automatically? If such tlc files could be generated from our M-file S-functions this process would be much easier. I understand the need of tlc files, but i see no point in writing them. Matlab should generate an initial but executable version of this code automatically, if the developers want to optmize the code generation, then they should try to modify it.

I think my function is not so complicated as Arzhaev's, so im posting it here to ask for the help of any good soul that could tell me how the corresponding tlc file should be. Thanks in advance.

Lucas

Code:
function custom_error(block)
%custom_sat Customized Saturation block

%%
setup(block);

%endfunction

%% Function: setup ===================================================
function setup(block)

try % Wrap in a try/catch, in case no S-function parameters are entered
errorProb = block.DialogPrm(1).Data;
up = block.DialogPrm(2).Data;
low = block.DialogPrm(3).Data;

catch
errorProb = 50;
up = 0;
low = 0;
end
block.NumInputPorts = 2;
block.NumOutputPorts = 2;

% Setup port properties to be inherited or dynamic

block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;

% Override input port properties

block.InputPort(2).DatatypeID = 8; % double
block.OutputPort(2).DatatypeID = 8; % double
%block.InputPort(2).Complexity = 'Real';

% Override output port properties

block.OutputPort(1).DatatypeID = block.InputPort(1).DatatypeID; % double
block.OutputPort(1).Complexity = block.InputPort(1).Complexity;


block.NumDialogPrms = 3;
block.DialogPrmsTunable = {'Tunable','Tunable','Tunable'};

% Register continuous sample times [0 offset]
block.SampleTimes = [0 0];

%% -----------------------------------------------------------------
%% Options
%% -----------------------------------------------------------------
% Specify if Accelerator should use TLC or call back into
% M-file
block.SetAccelRunOnTLC(false);

%% -----------------------------------------------------------------
%% Register methods called during update diagram/compilation
%% -----------------------------------------------------------------

block.RegBlockMethod('CheckParameters', @CheckPrms);
block.RegBlockMethod('SetInputPortSamplingMode', @SetInpPortSamplingMode);
block.RegBlockMethod('ProcessParameters', @ProcessPrms);
block.RegBlockMethod('PostPropagationSetup', @DoPostPropSetup);
block.RegBlockMethod('Outputs', @Outputs);
block.RegBlockMethod('Terminate', @Terminate);
%end setup function

%% Function: CheckPrms ===================================================
function CheckPrms(block)

errorProb = block.DialogPrm(1).Data;
up = block.DialogPrm(2).Data;
low = block.DialogPrm(3).Data;

% The error probability and the input variation must be a value between 0 and 100
if errorProb < 0 || errorProb > 100;
error('The error probability must be a value between 0 and 100');
end

if low > up;
error('The Lower Limit must be less than the Upper Limit');
end

if up < low;
error('The Upper Limit must be greater than the Lower Limit');
end

% If the upper or lower bound is specified via a dialog, make sure there
% is a specified bound. Also, check that the value is of type double
if isempty(errorProb),
error('Enter a value for the error probability.');
end
if ~strcmp(class(errorProb), 'double')
error('The error probability must be of type double.');
end


if isempty(up),
error('Enter a value for the Upper Limit.');
end
if isempty(low),
error('Enter a value for the Lower Limit.');
end

%end CheckPrms function

%% Function: ProcessPrms ===================================================
function ProcessPrms(block)

%% Update run time parameters
block.AutoUpdateRuntimePrms;

%end ProcessPrms function

%% Function: DoPostPropSetup ===================================================
function DoPostPropSetup(block)

%% Register all tunable parameters as runtime parameters.
block.AutoRegRuntimePrms;

%end DoPostPropSetup function

%% Function: Outputs ===================================================
function Outputs(block)

errorProb = block.DialogPrm(1).Data;
up = block.DialogPrm(2).Data;
low = block.DialogPrm(3).Data;
sigVal = block.InputPort(1).Data;

dtType = block.InputPort(1).Datatype;

r = randi(100);
r2 = randi(100);

error = block.InputPort(2).Data;

if error == false && (sigVal > up || sigVal < low),
error = true;
elseif error == false && sigVal < up && sigVal > low && r <= errorProb,
error = true;
if strcmp(dtType,'boolean')
if sigVal == 0
sigVal = true;
else
sigVal = false;
end
elseif r2 <= 50
if sigVal == 0
sigVal = up + 1;
else
sigVal = up + abs(sigVal);
end
else
if sigVal == 0
sigVal = low - 1;
else
sigVal = low - abs(sigVal);
end
end
end

block.OutputPort(1).Data = sigVal;
block.OutputPort(2).Data = error;


%end Outputs function
%% Function: Terminate ===================================================
function SetInpPortSamplingMode(block, idx, fd)

block.InputPort(idx).SamplingMode = fd;
block.OutputPort(idx).SamplingMode = fd;

%endfunction


%% Function: Terminate ===================================================
function Terminate(block)
%end Terminate function


"Phil Goddard" <philN...@goddardconsulting.ca> wrote in message <i6p4su$pv7$1...@fred.mathworks.com>...

0 new messages