simulink之S函数
simulink中用户可以使用已有的模块构建系统模型,如果遇到无法由内建模块构成的模型时,编写S-函数也能完成仿真,不但灵活,而且可以采用C,C++,Fortran或Ada云烟,只要生成dll文件,就可以在simulink中直接调用。S-函数允许用户向模型中添加自己编写的模块,按照简单规则,在S-函数添加算法。将S-函数名称放在S-Function模块中,利用simulink的封装并定义用户接口。
一、Simulink模块的数学模型
Simulin模块包括输入、输出和状态三个部分,其中输出是输入和状态的函数。状态向量分为连续状态和离散状态。若没有状态的模块,用一个空向量表示即可。因此:
输出y = f(x, u, t); x表状态;u表示输入,t表示时间
根据x状态的不同,连续状态:dx = f(x, u, t); 离散状态: x(i+1) = f(x(i), u, t);x为二者之和
二、Simulink仿真过程
初始化阶段和仿真运行阶段:前者主要是完成模块参数的确定工作,后者主要是求解器和系统共同作用,求解器实现传递模块的输出工作,完成积分状态导数,采样时间确定等;系统主要是计算模块的输出,更新状态,导数的计算、判断模块的过零事件及其他。计算连续状态包括两步,首先,求解器为待更新的系统提供当前状态、事时间与输出值;接着系统计算状态导数并传递给求解器;然后求解器对状态导数积分,计算新的状态值,更新模块输出,如有模块发出过零警告;最后会触发系统探测过零的准确时间。编程时,求解器和系统是通过不同的标志位实现执行对象的切换的。
仿真过程中包括包括初始化阶段和数值积分、更新离散状态、计算输出、计算下一个采样时间点和仿真结束六个部分;
a、初始化阶段主要是完成结构体SimStruct的初始化;设置S-函数的所有必要信息,主要包括设置输入输出的端口数,设置采样时间、分配存储空间等
b、更新连续状态,数值积分,完成连续状态的求解和非采样过零点定位。S-函数有连续状态,调用mdlDerivatives和mdlOutput函数,若有非采样过零点,调用mdlOutput和mdlZeroCrossing子函数完成输出和过零点的定位工作。
c、更新离散状态,该函数在每一步都会执行更新
d、计算输出,计算所有输出端的输出值
e、计算下一个采样时间点,若用变步长求解器仿真时,需要不停计算下一步仿真的步长,否则无需多次计算仿真步长
f、仿真结束,仿真结束是调用
三、S-函数的工作方式
S-函数的基本形式: function[sys, x0, str, ts] = functionName(t, x, u, flag, p1,...,pn),说明:赋值好左侧就是定义函数的标准形式,关键字function开始,接着就是 [sys, x0, str, ts]返回参数列表,不能有任何的变化,sys是通用返回参数,返回值的意义与flag参数紧密相关;x0是初始状态值;str保留值,必须设置为空矩阵;ts采样周期变量,两列分别表采样时间间隔与采样时间偏移。右侧的functionName是函数名称,可以按照标识符的要求自定义,(t, x, u, flag, p1,...,pn)作为传入参数列表,t表示时间,x表示状态,u表示输入信号,flag是求解器和系统运行的关键标识符,只有p1,...pn可以改变,其他的都不能变化。
S-函数的运行流程完全靠flag标识符决定:
falge = 0时,进入仿真初始阶段,调用mdlInitializeSizes(xInitial);初始化子函数,对参数进行初始化设置;
falge = 1时,进入仿真,调用子函数mdlDerivatives(t, x, u)更新连续状态变量
falge = 2时,进入仿真,调用子函数mdlUpdate(t, x, u)更新离散状态变量
falge = 3时,进入仿真,调用子函数mdlOutputs(t, x, u)计算模块的输出信号
falge = 4时,进入仿真,调用子函数mdlGetTimeOfNextVarHit(t, x, u)计算下一个采样时间,并提供采样时间
falge = 9时,进入仿真,调用子函数mdlTerminate(t, x, u),做结束的处理工作,终止仿真的过程