S-Function解析
S函数即系统函数System Function的意思,为什么要使用S函数呢?是因为在研究中,有时需要用到复杂的算法设计等,而这些算法因为其复杂性不适合用普通的Simulink模块来搭建,即matlab所提供的Simulink模块不能满足用户的需求,需要用编程的形式设计出S函数模块,将其嵌入到系统中。如果恰当地使用S函数,理论上,可以在Simulink下对任意复杂的系统进行仿真。
S函数具有固定的程序格式,用matlab语言可以编写S函数,此外还允许用户使用C、C++、Fortran和Ada等语言进行编写,用非matlab语言进行编写时,需要采用编译器生成动态链接库DLL文件。在主窗口中输入sfundemos,或者点击Simulink->User-Defined Functions->S-Function Examples,即可出现如图1所示的界面,可以选择对应的编程语言查看演示文件。
Matlab为了用户使用方便,有一个S函数的模板sfuntmpl.m,一般来说,我们仅需要在sfuntmpl.m的基础上进行修改即可。在主窗口输入edit sfuntmpl即可出现模板函数的内容,可以详细地观察其帮助说明以便更好地了解S函数的工作原理。
模板函数的定义形式为function[sys,x0,str,ts]=sfuntmpl(t,x,u,flag),一般来说,S函数的定义形式为[sys,x0,str,ts]=sfunc(t,x,u,flag,p1,…Pn),其中的sfunc为自己定义的函数名称,以上参数中,t、x、u分别对应时间、状态、输入信号,flag为标志位,其取值不同,S函数执行的任务和返回的数据也是不同的,pn为额外的参数,sys为一个通用的返回参数值,其数值根据flag的不同而不同,x0为状态初始数值,str在目前为止的matlab版本中并没有什么作用,一般str=[]即可,ts为一个两列的矩阵,包含采样时间和偏移量两个参数,如果设置为[0 0],那么每个连续的采样时间步都运行,[-1 0]则表示按照所连接的模块的采样速率进行,[0.25 0.1]表示仿真开始的0.1s后每0.25s运行一次,采样时间点为TimeHit=n*period+offset。
S函数的使用过程中有2个概念值得注意:
1、direct feedthrough,系统的输出是否直接和输入相关联,即输入是否出现在输出端的标志,若是为1,否则为0,一般可以根据在flag=3的时候,mdlOutputs函数是否调用输入u来判断是否直接馈通。
2、dynamically sized inputs,主要给出连续状态的个数、离散状态的个数、输入数目、输出数目和直接馈通否。
采样时间ts
仿真步长就是整个模型的基础采样时间,各个子系统或模块的采样时间,必须以这个步长为整数倍。连续信号和离散信号对计算机而言其实都是采样而来的,只是采样时间不同,连续信号采样时间可认为趋于0且基于微分方程,离散信号采样时间比较长基于差分方程。离散信号当前状态由前一个时刻的状态决定,连续信号可以通过微分方程计算得到。如果要将连续信号离散化还要考虑下信号能否恢复的问题,即香农定理。
采样时间点的确定:下一个采样时间=(n*采样间隔)+ 偏移量,n表示当前的仿真步,从0开始。对于连续采样时间,ts可以设置为[0 0],其中偏移量为0;对于离散采样时间,ts假设为[0.25 0.1],表示在S-函数仿真开始后0.1s开始每隔0.25s运行一次,当然每个采样时刻都会调用mdlOutPuts和mdlUpdate函数;对于变采样时间,即离散采样时间的两次采样时间间隔是可变的,每次仿真步开始时都需要用mdlGetTimeNextVarHit计算下一个采样时间的时刻值。ts可以设置为[-2 0]。对于多个任务,每个任务都可以以不同的采样速率执行S-函数,假设任务A在仿真开始每隔0.25s执行一次,任务B在仿真后0.1s每隔1s执行一次,那么ts设置为[0.25 0.1;1.0 0.1],具体到S-函数的执行时间为[0 0.1 0.25 0.5 0.75 1.0 1.1…]。如果用户想继承被连接模块的采样时间,ts只要设置为[-1 0]。
在实际仿真过程中,Simulink会自动将flag设置为0,进行初始化过程,然后将flag的数值设置为3,计算模块的输出,一个仿真周期后,Simulink将flag的数值先后设置为1和2,更新系统的连续和离散状态,再将其设置为3,计算模块的输出,如此循环直至仿真结束条件满足。
1 | function [sys,x0,str,ts,simStateCompliance] = sfuntmpl_c(t,x,u,flag) |