一般来说使用最多的S函数的原型为:
[sys,x0,str,ts]=f(t,x,u,flag,p1,p2,……)
其中f是S函数的函数名。Simulink会在仿真过程的每个步长内多此调用f。flag的值随着仿真过程自动变化,其值对应的S函数子方法如下:
补充一点:mdlDerivatives和mdlUpdate分别对应的是连续的状态变量和离散的状态变量,S-Function中mdlDerivatives的sys输出的是dx,但是output里面使用的是x,意思是Derivative中sys输出的是状态变量的一阶导数,这时候看上表,mdloutput使用的它的积分值,也就是状态变量本身;mdlUpdate应该也是如此。
这里输出的微分值,
这里使用的是微分值的积分。
理论定义:S函数的输出y或采样时间t与输入u有直接联系,就是直接馈入;如果输出y和采样时间t与输入u都没关系就不存在直接馈入情况。直接馈入存在时,输人u和输出y在同一个采样时刻计算得到,对于有状态量存在的模块,状态量在输入u与输出y之间架起了一座缓存桥,在一个采样时刻,输出值由上一个计算得到的状态值进行计算得到,通过当前时刻的输入值计算得到当前时刻的状态值。这样,输出值与输入值之间不存在直接连通关系,直接馈入不再存在。试想如果若干直接馈入的模块通过反馈构成了一个环形,就会出现所谓的“代数环”了。
注意:模块是否直接将馈入有一个简答的判断方法,就是查看mdlOutputs和mdlGetTimeOfNextVarHit两个子方法中有没有用到输入u。如果用到了,这个输入端口的直接亏馈入direct feedthrough就必须设置为1。
其他参数表示:
输出参数表示如下:
采样时间表:由一个包含两个元素的数组表示[m,n]表示,m为模块的采样时间周期,或连续或离散或继承父层模型的采样时间,表示每隔多长时间采样一次;n为采样时间的偏移量,表示与采样时间周期所表示的时刻点的偏差时间。
一个简答的小例子:
为S函数设置为3个参数,用来传递矩阵A、B、C到S函数中,在Update和Output子方法中分别使用其中部分参数,Update的参数列表中仅需要使用A和B,Output子方法参数列表中仅需使用参数C,输入口的维数要设置为2。状态变量采用离散状态变量,在S函数中按列排序。然后需要判断直接馈入,由于输入y由状态变量x决定,不由输入u决定,所以不存在直接馈入。代码如下:
function [sys,x0,str,ts,simStateCompliance] = sfun_mask(t,x,u,flag,A,B,C)
switch flag,
case 0,
[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;
case 1,
sys=mdlDerivatives(t,x,u);
case 2,
sys=mdlUpdate(t,x,u,A,B);
case 3,
sys=mdlOutputs(t,x,u,C);
case 4,
sys=mdlGetTimeOfNextVarHit(t,x,u);
case 9,
sys=mdlTerminate(t,x,u);
otherwise
DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 2;
sizes.NumOutputs = 1;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1; % at least one sample time is needed
sys = simsizes(sizes);
x0 = [0 0]';
str=[];
ts = [0,0];
simStateCompliance = 'UnknownSimState';
function sys=mdlDerivatives(t,x,u)
sys = [];
function sys=mdlUpdate(t,x,u,A,B)
sys = A * x + B * u;
function sys=mdlOutputs(t,x,u,C)
sys = C*x;
function sys=mdlGetTimeOfNextVarHit(t,x,u)
sampleTime = 1;
sys = t + sampleTime;
function sys=mdlTerminate(t,x,u)
sys = [];
将上述S函数名填入S-Function模块的S-Function一栏,将A、B、C语句定义在Command Windows中运行之后,将参数A、B、C填入S-Function parameters一栏。如下图:
常见错误:
1、 flag=3时仿真出错,往往由于输出维数配置不当或者使用了输入u但是没有在初始化时将输入端口配置为直接馈入。
2、参数未定义,明明S函数参数列表中设置了参数却没有添加到每个子方法的参数列表中导致子方法中参数未定义错误。