我是靠谱客的博主 慈祥裙子,最近开发中收集的这篇文章主要介绍matlab/simulink中带参数的S-Function(S函数)的写法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

S函数的相关概念与写法,直接在帮助文件中搜:【MATLAB S-Functions Create custom blocks defined】、【S-Function Concepts】等

 

S函数模块可以从下图中拖出来:

图 1

其中S-Function是正宗的S函数模块,旁边还有一个S-Function builder是给新手用的,只要学会了S函数模块,S builder模块自然一看就懂。

使用S函数模块的步骤:①写S函数的.m文件, 并把m文件所在的文件夹加入搜索路径,如下图2所示。②在simulink中拖出S函数,并填上m文件的名字,如果有参数(下文会讲到),也把参数名填上,如下图3所示。然后就可以执行仿真了

图2

图3

 

下面是最关键的部分,如何写S函数:

写S函数的本质就是写一堆回调函数,C/C++程序员对回调函数应该很熟悉了,既然是回调函数,那写之前必须要知道形参和返回值的格式,这个格式从哪查?直接在matlab命令行执行: edit sfuntmpl,就直接打开了官方提供的模板,连格式都不用查了,直接仿照官方模板把函数体改改盖就行了,方便。

(1)S函数的总函数

把官方模板的代码拷到一个新文件里,并命名为自定义名称,我取的名字是oneOrderModule.m,然后把函数名也改成和文件名相同,我的是这样的:function [sys,x0,str,ts,simStateCompliance] = oneOrderModule(t,x,u,flag, T)

我与官方版不同的是,自己加了一个参数T,如果你还想添加更多参数,直接在形参表里添加就行了。添加的形参的实参值,来自于图3的第二个输入框,这个输入框可填常量,也可以填工作区变量名。

形参:①当前的仿真时间t,单位为秒,该参数可以用来描述变参数系统,例如你想实现【在t>2S时,把系统增益给改掉】这一功能,就可以通过判定t的值来实现;②x为状态列向量;③输入列向量u;④flag为当前状态机的第几步,例如实参送进来的flag=0代表S函数需要初始化,flag=1代表要更新连续状态

返回值:在不同的状态步下(也即flag不同时),返回值的意义是不同的,在模板文件的注释中都讲到了:

例如flag=0时,需要返回:输入输出状态变量等的大小SIZES、状态变量的初值X0等。。。
又如flag=3时,返回值sys代表输出向量Y,也即状态空间表达式第2式,Y=CX+DU

不同flag下返回值得写法,将在下面的各个函数中依次讲解

(2)系统初始化

当我么在函数中检测到flag=0时,意味着simulnk需要我们返回系统初始化的一些信息。
实际上,我们可以直接把flag=0时需要执行的代码直接写在switch-case中,但是为了使程序更清晰,我们也仿照官方模板,在case中调用初始化函数mdlInitializeSizes,我们把代码写在初始化函数中。

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

sizes = simsizes;

sizes.NumContStates  = 1;%连续状态向量的元素数目
sizes.NumDiscStates  = 0;%离散状态向量的元素数目
sizes.NumOutputs     = 2;%输出向量的元素数目
sizes.NumInputs      = 1;%输入向量的元素数目
sizes.DirFeedthrough = 1;%输入是否直接馈通到输出
sizes.NumSampleTimes = 1;   % 采样时间矩阵的行数(必须设为>=1),另外列数固定为2,无需设置

sys = simsizes(sizes);%把以上赋值好的结构赋给返回值
x0  = [0];%设置状态向量的初值
str = [];%保留参数,不用管
ts  = [0 0];%采样时间设置,必须为mx2维度,其中m为上面sizes.NumSampleTimes的值
simStateCompliance = 'UnknownSimState';

此函数中,按照回调函数的要求,sys的返回要返回一些成员的尺寸大小,我们可以一个个为sys(1)、sys(2)。。等依次赋值,但我们不会这么做,因为官方模板为我们提供了一个辅助数据结构的实体simsizes,直接把他复制出来把成员值改好,再赋值给返回值sys即可。simsizes的成员有6个,其中有2个需要单独讲一下:

①直接馈通标志DirFeedthrough,这个东西实际上就是看看状态空间表达式第2式Y=CX+DU中的D矩阵是否为0矩阵,如果不是,那我们必须把馈通标志设为1。从回调函数来看,只要我们把DirFeedthrough设成了1,那么当flag=3时,系统会把t、u两个参数传进总函数oneOrderModule中,如果DirFeedthrough设成了0,那么当flag=3时,我们在oneOrderModule函数或者mdlOutputs函数中中将无法读到t的值(实际读出来总是0),也无法读到u的值(实际读出来总是一个只含Nan元素的向量)。

②采样时间矩阵的行数NumSampleTimes
这个东西有些复杂,从直观上看,它决定了【采样时间矩阵ts】的行数,ts矩阵是NumSampleTimes行2列的矩阵。ts的每一行均包含一个数据对:[ 采样时间   偏移量 ],这些数据对不是乱填的,可选就这么几种形式:

采样时间可以理解为采样周期,真正的采样时刻=n*周期+偏移量。
对于连续系统,采样时间应设为0,matlab也提供宏CONTINUOUS_SAMPLE_TIME,该宏的值=0。
对于固定步长的离散系统,可以直接设置采样间隔和偏移,形如:[ 0.1   0.02 ]
对于变步长的离散系统,可以设置为:[VARIABLE_SAMPLE_TIME,  0.0],这种参数需要同时把simulink求解器solver设置成变步长的。
继承前一模块的采样点,可以设置为:[INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET或0]。

更多知识点,可以搜索这几个宏名来学习。

 

(3)连续系统更新、离散系统更新

这两个函数分别为mdlDerivatives和mdlUpdate,如果需要支持自定义的参数,那么直接修改函数的形参表即可,在我的例子中,我附加了一个T参数,那么我的连续系统更新函数是这样的:

function sys=mdlDerivatives(t,x,u, T)
A = [-1/T];
B = [1/T];
sys = A*x+B*u;

原理是这样的,典型一阶系统的微分方程:

如果系统中存在离散状态,那么就在mdlUpdate中写出离散状态空间表达式即可,如果没有离散状态,就直接sys返回空矩阵。

(4)输出函数

function sys=mdlOutputs(t,x,u)
C = [1 
    1];
D = [0
    1];
 sys = C * x + D * u;
%sys = [x t];

这个也没啥好说的,描述一下输出向量即可。不过提醒一下,如果使用了 u或t 参数,不要忘记把馈通标志置1,否则在本函数中收不到t和u的实参值。

这个函数描述了两个输出: y(1)=x,y(2)=x+u

 

 

下面看一下仿真结果:

和预想的一样,没毛病。

最后

以上就是慈祥裙子为你收集整理的matlab/simulink中带参数的S-Function(S函数)的写法的全部内容,希望文章能够帮你解决matlab/simulink中带参数的S-Function(S函数)的写法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部