您的位置:首页 > 其它

S-functions

2015-09-29 21:44 274 查看
1、S-function文件作用、简介

S-function是system-function的缩写,是一种对模块库进行扩展的工具。当MATLAB提供的基本库模块不能满足用户的要求时,就需要自己创造满足自己的要求的模型。

S-function,在simulink的User-defined
functions项下。 可以用m、C、C++、Ada、FORTRAN语言编写,通过编译生成MEX文件动态链接MATLAB。本文主要介绍m语言编写。

2、使用场合

(1)生成用户自行研究中可能反复调用的S函数模块

(2)创建代表硬件驱动的模块

(3)通过S函数将摸个系统描述成一组数学方程组

(4)构建用于图形动画表现的S函数模块

3、S-function写法

为了降低开发人员对S-function的M文件编写投入的精力和时间,Matlab提供了编写S函数的M文件的标准模版,文件名为sfuntmpl.m,保存路径为D:\MATLAB7\toolbox\simulink\blocks。使用模板文件的好处是,比较方便,而且条理清晰,程序员也可以根据自己的思想去写。在调用时,Simulink会根据所处的仿真阶段为flag传入不同的值,而且还会为sys这个返回参数指定不同的角色,也就是说尽管是相同的sys变量,但在不同的仿真阶段其意义却不相同,这种变化由simulink自动完成。

(1)关于Size数组的介绍

Sizes数组是s-function函数信息的载体,它内部的字段意义为:

NumContStates:连续状态的个数(状态向量连续部分的宽度),默认值为0

NumDiscStates:离散状态的个数(状态向量离散部分的宽度),默认值为0

NumOutputs: 输出变量的个数(输出向量的宽度),默认值为0

NumInputs:输入变量的个数(输入向量的宽度),默认值为0

DirFeedthrough:有无直接馈入,默认值为1

NumSampleTimes:采样时间的个数,默认值为1

如果字段代表的向量宽度为动态可变,则可以将它们赋值为-1。

注意DirFeedthrough是一个布尔变量,它的取值只有0和1两种,0表示没有直接馈入,此时用户在编写mdlOutputs子函数时就要确保子函数的代码里不出现输入变量u;1表示有直接馈入。

NumSampleTimes表示采样时间的个数,也就是ts变量的行数,与用户对ts的定义有关。

需要指出的是,由于s-function会忽略端口,所以当有多个输入变量或多个输出变量时,必须用mux模块或demux模块将多个单一输入合成一个复合输入向量或将一个复合输出向量分解为多个单一输出。

(1) 输入输出参数说明

S-function默认的4个输入参数为t、x、u和flag,它们的次序不能变动,代表的意义分别为:

t:代表当前的仿真时间,这个输入参数通常用于决定下一个采样时刻,或者在多采样速率系统中,用来区分不同的采样时刻点,并据此进行不同的处理。

x: 表示状态向量,这个参数是必须的,甚至在系统中不存在状态时也是如此。它具有很灵活的运用。

u:表示输入向量。

flag:是一个控制在每一个仿真阶段调用哪一个子函数的参数,由Simulink在调用时自动取值。

S-function默认的4个返回参数为sys、x0、str和ts,它们的次序不能变动,代表的意义分别为:

sys:是一个通用的返回参数,它所返回值的意义取决于flag的值。

x0: 是初始的状态值(没有状态时是一个空矩阵[]),这个返回参数只在flag值为0时才有效,其他时候都会被忽略。

str:这个参数没有什么意义,是MathWorks公司为将来的应用保留的,m文件s-function必须把它设为空矩阵。

ts:是一个m×2的矩阵,它的两列分别表示采样时间间隔和偏移。

(3)模版文件及其详细进行说明:

function [sys,x0,str,ts] = sfuntmpl(t,x,u,flag)

% sfuntmpl为模版对应的文件名称,创建自己的S函数是,应该重新起名

% 前面四个变量是simulink调用s-function时自动传入,一般不要改动

% 根据用户需要可以在里面添加自己的变量,如mysfun(t,x,u,flag,a,b,c)

% 用户将自己的算法放到合适的s-function子函数中去。

% flag有六个不同取值,用于选择六种不同的子函数进行执行

switch flag,

case 0,

[sys,x0,str,ts]=mdlInitializeSizes; %调用初始化子函数

case 1,

sys=mdlDerivatives(t,x,u); %调用计算模块导数的子函数

case 2,

sys=mdlUpdate(t,x,u); %调用更新模块离散状态的子函数

case 3,

sys=mdlOutputs(t,x,u); %调用计算模块输出的子函数

case 4,

sys=mdlGetTimeOfNextVarHit(t,x,u);% 调用计算下一个采样时点的子函数

case 9,

sys=mdlTerminate(t,x,u); %调用结束仿真的子函数

otherwise

error(['Unhandled flag = ',num2str(flag)]);

end %结束

% 下面对各个子函数进行编写

function [sys,x0,str,ts]=mdlInitializeSizes

sizes = simsizes;

sizes.NumContStates = 0;

sizes.NumDiscStates = 0;

sizes.NumOutputs = 0;

sizes.NumInputs = 0;

sizes.DirFeedthrough = 1;

sizes.NumSampleTimes = 1; % at least one sample time is needed

sys = simsizes(sizes);

x0 = [];

str = [];

ts = [0 0];

function sys=mdlDerivatives(t,x,u)

sys = [];

function sys=mdlUpdate(t,x,u)

sys = [];

function sys=mdlOutputs(t,x,u)

sys = [];

function sys=mdlGetTimeOfNextVarHit(t,x,u)

sampleTime = 1;

sys = t + sampleTime;

function sys=mdlTerminate(t,x,u)

sys = [];

(4)举例子

function [sys,x0,str,ts] = limintm(t,x,u,flag,lb,ub,xi)

switch flag,

case 0,

[sys,x0,str,ts]=mdlInitializeSizes(lb,ub,xi);

case 1,

sys=mdlDerivatives(t,x,u,lb,ub);

case {2,9},

sys = [];

case 3,

sys=mdlOutputs(t,x,u);

otherwise

error(['Unhandled flag = ',num2str(flag)]);

end

function [sys,x0,str,ts]=mdlInitializeSizes(lb,ub,xi)

sizes = simsizes;

sizes.NumContStates = 1;

sizes.NumDiscStates = 0;

sizes.NumOutputs = 1;

sizes.NumInputs = 1;

sizes.DirFeedthrough = 0;

sizes.NumSampleTimes = 1;

sys = simsizes(sizes);

x0 = xi;

str = [];

ts = [0 0];

function sys=mdlDerivatives(t,x,u,lb,ub)

if(x <= lb & u<0) | (x >= ub & u > 0)

sys = 0;

else

sys = u;

end

function sys=mdlOutputs(t,x,u)

sys = x;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: