搜档网
当前位置:搜档网 › 第十章_用S函数扩展Simulink

第十章_用S函数扩展Simulink

第十章_用S函数扩展Simulink
第十章_用S函数扩展Simulink

第十章 用S-函数扩展Simulink

通过第八、第九章的学习,用户对用Simulink建模的基本思想已经有了清晰的认识,Simulink为用户提供了许许多多的内置库模块,用户只需使用这些库模块构建系统即可。但在实际应用中,用户通常会发现有些过程用Simulink的库模块不容易建模。这时,可以使用S-函数来扩展Simulink。S-函数结合了Simulink框图图形化的特点和MATLAB编程灵活方便的优点,从而给用户提供增强和扩展Simulink 的强大机制,同时它也是使RTW(Real Time Workshop)实现实时仿真的关键。

10.1 S-函数概述

10.1.1 S-函数的基本概念

S-函数是System function系统函数的简称,是指采用非图形化(即计算机语言,而非Simulink 系统模块)的方式描述的功能模块。在MATLAB中,用户除了可以使用MATLAB代码编写S-函数以外,还可以使用C、C++、FORTRAN或Ada语言编写S-函数,只不过用这些语言编写程序时需要用编译器生成动态连接库(DLL)文件,然后在Simulink中直接调用。

S-函数是由一种特殊的语法构成的,用来描述并实现动态系统的。它采用一种特殊的调用语法,使函数和Simulink求解器进行交互。这种交互与求解器和Simulink仿真模型间的交互相类似:S-函数接受来自Simulink求解器的相关信息,并对求解器发出的命令做出适当的响应。

S-函数作为与其它语言结合的接口,可以使用这个语言所提供的强大功能。例如,使用MATLAB语言编写的S-函数称为M文件S-函数,它可以充分利用MATLAB所提供的丰富资源,方便地调用各种工具箱函数和图形函数;而使用C语言编写的S-函数被称为C-MEX文件S-函数,则可以实现对操作系统和外部设备等的访问,也可以提供与操作系统的接口。另外,S-函数可以使用其他多种语言编写,因此可以实现代码的移植,即将已有的代码结合进来,而不需在Simulink中重新实现算法。

S-函数中采用非图形化的方式描述系统,其内部采用文本方式输入描述系统的公式、方程,这种方式非常适合复杂动态系统的数学描述,且可以在仿真过程中对仿真进行精确的控制。

10.1.2 如何使用S-函数

在动态系统仿真中,要想将S-函数加入Simulink仿真模型中,用户需要将User Defined Functions 模型库中的S-Function模块拖进该模型中。S-Function模块是一个单输入单输出模块,如果有多个输入与输出信号,用户需要使用Mux模块和Demux模块对信号进行组合或分离。S-Function模块仅仅是以图形的方式提供给用户一个S-函数的使用接口,在它的参数设置对话框中仅包含S-函数的名称及函数所需的参数列表(见图10.1),而S-函数所实现的功能则由S-函数源文件描述,S-函数源文件必须由用户自行编写。

使用S-函数的步骤如下:

一、在系统的Simulink仿真框图中添加S-function模块,并进行正确的设置;

二、创建S-函数源文件。创建S-函数源文件的方法有多种。用户可以按照S-函数的语法格式自行编写代码,但是这样做很麻烦,且容易出错。Simulink在S-function Examples模型库中为用户提供了针对不同语言的很多S-函数模板和例子,用户可以根据自己的需要修改相应的模板或例子即可完成S-函数源文件的编写工作;

三、在系统的Simulink仿真框图中按照定义好的功能连接输入输出端口。

这里需要说明的是,S-function模块中S-函数名称必须和用户建立的S-函数源文件的名称完全相同,S-function模块中的S-函数参数列表必须按照S-函数源文件中的参数顺序赋值,且参数之间需要用逗号隔开。另外,用户也可以使用子系统封装技术对S-函数进行封装,这样做的好处是可以增强系统模型的可读性。

122

123

为了方便用户编写C MEX S 函数,Simulink 的User Defined Functions 模型库中为用户编写C MEX S 函数提供了一个图形化的集成的图形开发环境S-function builder。用户只需在S-function builder 中相应的位置写入相应的名称和代码即可编译成相应的MEX 文件。

为了使读者尽快掌握S-函数的使用步骤,先举一个简单的例子。 例10.1 使用S-函数实现系统:2*y u =。

解:一、在Simulink 模型框图中添加S-function 模块,打开S-funfction 模块的参数设置对话框,参数S-function name 需设置为timestwo。 二、创建S-函数源文件。

1、打开M 文件S-函数模板文件Sfuntmpl.m,并在指定目录下另存为timestwo.m。打开M 文件S-函数模板文件Sfuntmpl.m 的方法由两种:

方法一,在MATLAB 命令窗口键入edit Sfuntmpl 即可;

方法二,在Simulink 浏览器中寻找S-function demos 模型库,其中包含各种语言编写的S-函数例子和模板。对于本例,用户只需点击M-file S-functions 就可以看到M 文件S-函数模板文件Sfuntmpl.m 和几个编程例子,双击模板文件Sfuntmpl.m 即可。 2、修改模板。找到函数mdlInitializeSizes,修改以下代码:

size.NumOutputs=1; size.NumIutputs=1;

找到函数mdOutputs,将代码sys=[ ]改为sys=2*u 至此,已经写好了该S-函数的源文件,保存修改即可。

三、在Simulink 模型框图中按要求添加并连接各个模块。系统Simulink 仿真模型如图10.2所示。 四、运行仿真。仿真结果可以从Scope 模块中观察。结果如图10.2所示。 10.1.3 与S-函数相关的术语

用户对S-函数相关的术语的理解对于了解S-函数的工作原理、编写S-函数源文件是非常有用的。

一、仿真例程(Routines)

图10.1 S -函数模块、参数设置对话框及其源文件的关系

124

Simulink 在仿真的不同阶段调用S-函数的不同的功能函数以完成不同的任务。对于M 文件S-函数, Simulink 通过传递一个flag 参量给S-函数,通知S-函数当前所处的仿真阶段,以便执行相应的功能函数。S-函数的功能函数包括初始化、计算输出、更新离散状态、计算导数、结束仿真等。这些功能函数称为仿真例程或回调函数(call back function)。在写M 文件S-函数时,用户只需用MATLAB 语言为每个flag 对应的功能函数编写代码即可。表10.1列出了各仿真阶段的功能函数及其对应的flag 值。

表10.1 各仿真阶段的仿真例程及其flag 值

仿真阶段 S-函数仿真例程(回调函数) Flag 值(M 文件S-函数)

初始化

mdlInitializeSizes 0 计算下一个采样点 mdlGetTimeofNextVarHit 4 计算输出值 mdlOutputs

3 更新离散状态 mdlUpdate 2 计算导数 mdlDerivatives 1 结束仿真

mdlTerminate

9

二、直接馈入(Direct Feedthrough)

直接馈入是指模块的输出或采样时间(变速率模型)直接由其某个输入端口控制。判断一个S-函数是否具有直接馈入的标准是:

某时刻系统的输出y 包含该时刻系统的输入u,即计算系统输出的方程中包含输入变量u; 若系统是一个变采样时间系统,且下一个采样点的计算与输入u 有关。

馈入标志的设置不仅关系到系统模型中的系统模块的执行顺序,而且关系到对代数环的检测和处理。因此正确设置馈入标志是非常重要的。

三、采样时间和偏移量(Sample time & offsets)

M 文件和C MEX 文件S-函数都允许用户十分方便地设定S-函数被调用的时间。

采样时间在离散系统中控制采样点的间隔,偏移量则用于延迟采样点。一个采样点对应的时间值由下列公式计算:

TimeHit=n×period+offset

其中,n 表示当前仿真步,是整数。

如果用户定义了一个离散采样时间,Simulink 就会在所定义的每个采样点调用S-函数的mdlOutputs 和mdlUpdate 例程。

对于连续时间系统,采样时间和偏移量的值均应设置为零。采样时间还可以继承来自驱动模块、目

图10.2 例10.1系统Simulink 仿真模型及其结果

125

标模块或系统最小的采样时间,这种情况下,采样时间值设置为-1。

四、动态输入(Dynamically sized inputs)

S-函数支持动态可变维数的输入。S-函数的输入变量的维数取决于驱动S-函数模块的输入信号维数。仿真开始时,通过size 或length 函数确定输入信号的维数。然后就可以利用这个维数来估计连续状态数目、离散状态数目和输出向量的维数。

在M 文件S-函数中动态设置输入维数时,应该把sizes 数据结构的对应成员设置为-1。

比如在例10.1中,如果将函数mdlInitializeSizes 中的代码设置成size.NumOutputs=-1; size.NumIutputs=-1; 则当输入是两维信号,分别为幅值为1和3的正弦信号,系统的输出也是两维信号,结果如图10.3所示。

10.2 S-函数工作原理

了解S-函数的工作原理对于用户掌握S-函数的编写方法是非常有用的,对用户对于Simulink 的仿真原理的理解也是很有帮助的。本节介绍S-函数的工作原理。

在具体介绍S-函数的工作原理之前,首先需要回顾一下Simulink 模块的工作原理。 Simulink 中的每个模块都有三个基本元素:输入向量、状态向量和输出向量,分别表示为u ,x 和y 。图10.4反映了它们之间的关系。在Simulink 模块的三个元素中,状态向量是最重要的,也是最灵活的概念。在Simulink 中状态向量可以分为连续状态、离散状态或两者的结合。输入、输出及状态的关系可以用状态方程描述:

输出方程:(,,)o y f t =x u 连续状态方程:(,,)d d f t =x x u 离散状态方程:1(,)k u f t +=x x,u

其中[]1k d +=x x

x 。

Simulink 在仿真时将上述方程对应不同的仿真阶段,它们分别是计算模块的输出、更新离散状态、计算连续状态的微分。在仿真开始和结束,还包括初始化和结束仿真两个阶段。在每个阶段,Simulink 都反复地调用模块。

至此,读者已经接触到了几个关于仿真的概念:仿真步长(Simulation step)、仿真阶段(Simulation stage)。为了深入了解S-函数的工作原理,还需了解一个概念:仿真循环(Simulation loop)。一个仿真循环就是由仿真阶段按一定顺序组成的执行序列。对于每个模块,经过一次仿真循环就是一个仿真步长,而在同一个仿真步长中,模型中各模块的仿真按照事先排好的顺序依次执行。这个过程可以用图10.5表示。

从图中可以看出,在仿真开始时,Simulink 首先对模型进行初始化,此阶段不属于仿真循环。在所有模块都初始化后,模块进入仿真循环,在仿真循环的每个阶段,Simulink 都要调用模块或者

S-函数。

图10.3 例10.1进行动态输入设置后的仿真结果

图10.4 Simulink 模块的基本模型

126

由于在积分时,对仿真步长有要求,所以此时需要将仿真步长细化。完成一个仿真循环就进入下一个仿真步长,如此循环直至仿真结束。

在调用模型中的S-函数时,Simulink 会调用用户定义的S-函数的例程来实现每个仿真阶段要完成的任务。这些任务包括:

一、初始化:仿真开始前,Simulink 在这个阶段初始化S-函数,完成的主要工作包括:

1、初始化包含S -函数所有信息的结构体SimStruct;

2、确定输入输出端口的数目和大小;

3、确定模块的采样时间;

4、分配内存和Sizes 数组。

二、计算下一个采样时刻。如果模型使用变步长求解器,那么就需要在当前仿真步长内确定下一个采样点的时间,也即下一个仿真步长的大小; 三、计算输出:计算所有输出端口的输出值。 四、更新离散状态:此例程在每个仿真步长处都要执行一次,为当前时间的仿真循环更新离散状态; 五、数值积分:这个阶段只有模块具有连续状态和非采样过零点时才会存在。如果S-函数存在连续状态,Simulink 就在细化的小时间步长中调用S-函数的输出(mdlOutputs)和微分(mdlDerivatives)例程。如果存在非采样过零点,Simulink 将调用S -函数中的输出(mdlOutputs )和过零检测(mdlZeroCrossngs)例程,以定位过零点。

10.3 编写M 文件S-函数

由前面的介绍可以知道,S-函数是由一系列仿真例程组成的。这些仿真例程就是S-函数特有的语法结构,用户编写S-函数的任务就是在相应的例程中填写适当的代码,供Simulink 及MATLAB 求解器调用。M 文件S-函数结构明晰,易于理解、书写方便,可以调用丰富MATLAB 函数,所以在实际工作中得到了广泛的应用。

M 文件S-函数利用Flag 标志控制调用例程函数的顺序。各仿真阶段的仿真例程及对应的标志值如表10.1所示。

M 文件S-函数的仿真流程同图10.5介绍的S-函数的仿真流程。在初始化阶段,通过标志0调用S -函数,并请求提供输入输出个数、初始状态和采样时间等信息。然后,仿真开始。下一个标志为4,请求S-函数提供下一步的采样时间(这个例程在单采样速率系统下不被调用)。接着flag=3计算模块的输出,flag=2更新离散状态,当需要计算连续状态导数时flag=1。然后求解器使用积分例程计算状态的值。计算状态导数和更新离散状态之后通过标志3计算模块的输出。这样就完成了一个仿真步长的工作。当到达结束时间时,采用标志9完成结束前的处理工作。 10.3.1 M 文件S-函数模板

图10.5 S -函数仿真流程

Simulink为用户提供了各种语言编写S-函数的模板文件。这些S-函数的模板文件中定义了S-函数的框架结构,用户可以根据自己的需要修改。

编写M文件S-函数时,需要使用M文件S-函数模板文件sfuntmpl.m文件。该文件包含了所有的S -函数的例程,及包含1个主函数和6个子函数。在主函数中,程序使用一个多分支语句(Switch-case)根据标志将执行流程转移到相应的例程函数。主函数的参数Flag标志值是由系统(Simulink引擎)调用时给出的。读者可以打开并阅读该M文件S-函数模板文件。

一、打开模板文件的方法由两种,用户可以在MATLAB命令窗口中键入:

>> edit sfuntmpl

或者双击User-defined Function \S-function Examples\M-file S-functions\Leveal-1 M-file S-functions1\ Leveal-1 M-file template模块。

二、M文件S-函数模板文件代码

M文件S-函数模板文件的代码如下:

%主函数

function [sys,x0,str,ts] = sfuntmpl(t,x,u,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数据结构

sizes.NumContStates = 0; % 连续状态数,缺省为0

sizes.NumDiscStates = 0; % 离散状态数,缺省为0

sizes.NumOutputs = 0; % 输出量个数,缺省为0

sizes.NumInputs = 0; % 输入量个数,缺省为0

sizes.DirFeedthrough = 1; % 有无直接馈入,有取1,无取0,缺省为1

sizes.NumSampleTimes = 1; % 采样时间个数,至少取1

sys = simsizes(sizes); % 返回sizes数据结构所包含的信息

127

x0 = []; % 设置初始状态

str = []; % 保留变量,置为空矩阵

ts = [0 0]; % 采样时间:[采样周期 偏移量],采样时间取0表示为连续系统

% 计算导数例程子函数:计算连续状态的导数,用户需在此例程输入连续状态方程。

% 该子函数可以不存在。

function sys=mdlDerivatives(t,x,u)

sys = []; % sys表示连续状态导数

% 状态更新例程子函数:计算离散状态的更新。

% 用户除了需在此输入离散状态方程外,还可以输入其它每个仿真步长都有必要执行的代码。

% 该子函数可以不存在。

function sys=mdlUpdate(t,x,u)

sys = []; % sys表示下一个离散状态,即x(k+1)

% 计算输出例程子函数: 计算模块输出。该子函数必须存在,用户在此输入系统的输出方程。 function sys=mdlOutputs(t,x,u)

sys = []; % sys表示系统输出y

% 计算下一个采样时间, 只有变采样时间系统才调用此仿真例程。

function sys=mdlGetTimeOfNextVarHit(t,x,u)

sampleTime = 1; % 设置下一次的采样时间是1s以后

sys = t + sampleTime; % sys 表示下一个采样时间点

% 仿真结束调用的例程函数:用户需在此输入结束仿真所需要的必要工作。

function sys=mdlTerminate(t,x,u)

sys = [];

三、M文件S-函数模板文件的几点说明

主函数包含四个输出参数:sys数组返回某个子函数,它的含义随着调用子函数的不同而不同;x0为所有状态的初始化向量;str是保留参数,总是一个空矩阵;Ts返回系统采样时间。

主函数的四个输入参数分别是采样时间t,状态x,输入u和仿真流程控制标志变量flag。

输入参数后面还可以附加一系列用户仿真需要的参数。

编写用户自己的S-函数时,应将函数名改为sfuntmpl改为S-function模块中设置的函数名。

读者可能已经发现一个令人困惑的问题:不论在哪个仿真阶段,例程子函数的返回变量都是sys。要

128

搞清楚这个问题,还要回到Simulink如何调用S-函数上来。前面讲过,Simulink在每个仿真步长的仿真循环中的每个仿真阶段都要调用S-函数。在调用时,Simulink不但根据所处的仿真阶段为flag传入不同的值,还会为返回变量sys指定不同的角色。即是说尽管是相同的sys变量,但在不同的仿真阶段其意义是不相同的,这种变化由Simulink自动完成。

10.3.2 M文件S-函数的应用举例

了解了M文件S-函数模板文件的代码、代码中各个部分完成的功能及各参数的含义后,用户可以着手利用S-函数进行系统仿真了。下面我们使用M文件S-函数实现几种不同的系统。

一、含用户参数的简单系统

M文件S函数除了模板文件中要求的几个必需的参数,还可以加入用户自定义的参数,自定义参数需要在S-函数的输入参数中列出。在含用户自定义参数的S函数中,主函数要做适当的修改以便将自定义参数传递到子函数中,子函数也需要相应的修改以便接受自定义参数。在编写S-函数时,应能区分哪些参数会影响哪一个子函数的执行,要针对这些参数做相应的修改。还需注意的一点是,S-function模块中的参数设置对话框中的参数输入顺序应与S-函数中自定义参数的顺序相同。

例10.2 用S-函数实现gain模块:增益值作为S-函数用户自定义参数输入。

解:(1)编写S-函数的源文件

修改M文件S-函数的主函数:增加自定义参数,采用新的函数名:

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

由于增益参数只是用来计算输出值的,因而对初始化例程和计算输出例程子函数做修改,其他例程均不需调用,不用做修改

case 0,

[sys,x0,str,ts]=mdlInitializeSizes(gain);

case 3,

sys=mdlOutputs(t,x,u,gain);

修改初始化例程子函数:

function [sys,x0,str,ts]=mdlInitializeSizes(gain)

sizes.NumContStates = 0;

sizes.NumDiscStates = 0;

sizes.NumOutputs = 1;

sizes.NumInputs = 1;

sizes.DirFeedthrough = 1;

定义计算输出例程子函数

function sys=mdlOutputs(t,x,u,gain)

sys = gain*u; % 输出=增益×输入

(2)建立如图10.6所示的系统仿真模型,将自定义参数设置为3,运行仿真,仿真结果如图10.6所示,验证了S-函数的正确性。

129

130

二、连续系统的S-函数描述

用S-函数实现一个连续系统时,首先需要修改初始化例程子函数mdlInitialSizes,包括正确设置连续状态个数、状态初始值和采样时间。其次,需要编写计算导数例程子函数,将状态的导数向量通过sys 变量返回。如果存在多个系统状态,可以通过索引x(1),x(2)等得到各个状态,此时,变量sys 即为一个向量,包含所有各个连续状态的导数。最后,也需在计算输出例程子函数中编写系统的输出方程。下面举例说明。

例10.3 试用S-函数对蹦极跳系统做仿真分析。

蹦极跳是一种挑战身体极限的运动,蹦极者系着一根弹力绳从高处的桥梁或山崖向下跳。如果蹦极者系在一个弹性系数为k 的弹力绳索上。定义绳索下端的初始位置为0,则蹦极者受到的弹性力是

0()00kx x b x x ?>?=?≤?

,整个蹦极跳系统的数学模型

12()mx

mg b x a x a x x =+?? 其中m 为物体的质量,g 为重力加速度,x 为物体的位置,第二项是物体受到的弹性力,第三与第四

项表示空气的阻力。

设桥梁距离地面高度为50米,绳索长度30米,

图10.7 蹦极跳系统坐标系

图10.6 含用户参数的简单系统仿真

131

由此可知蹦极者初始站在桥上时的初始位置(0)30x =?,初始速度(0)0x

= ;根据对蹦极跳系统的描述,我们可以分析出该系统的坐标系如图10.7所示。其余参数分别取为50k =,121a a ==,70m kg =,

210/g m s =。下面我们分析此蹦极跳系统对于70kg 重的蹦极者是否安全。

解:为了使用S-函数对蹦极跳系统进行仿真计算,需将其数学模型转变为如下状态方程形式

122

112222()///x x x g b x m a x m a x x m =?

?=+???

,其中12,x x x x == (1)编写S-函数的源文件

① 修改M 文件S-函数的主函数:增加自定义参数,采用新的函数名: function [sys,x0,str,ts] = jumping(t,x,u,flag,l,m,d,k)

由于增添了自定义参数来计算导数和输出值的,因而对初始化例程子函数、计算导数和输出例程的子函数做修改 case 0,

[sys,x0,str,ts]=mdlInitializeSizes(l,m,d,k); case 1,

sys=mdlDerivatives(t,x,u,l,m,d,k); case 3,

sys=mdlOutputs(t,x,u,l,m,d,k); 修改初始化例程子函数:

function [sys,x0,str,ts]=mdlInitializeSizes(l,m,d,k) sizes.NumContStates = 2; sizes.NumDiscStates = 0; sizes.NumOutputs = 1; sizes.NumInputs = 0; sizes.DirFeedthrough = 1; x0 = [-l;0];

定义计算导数例程子函数

function sys=mdlDerivatives(t,x,u,l,m,d,k) if x(1)>=0 b=-k*x(1); else b=0; end

sys = [x(2);10+b/m-1/m*x(2)-1/m*abs(x(2))*x(2)]; 定义计算输出例程子函数

function sys=mdlOutputs(t,x,u,l,m,d,k) sys = [d-l-x(1)];

132

(2)建立如图10.8所示的系统仿真模型,并按正确的顺序输入自定义参数l,m,d,k 的值,运行仿真,仿真结果也如图10.8所示。由仿真曲线可知,本蹦极跳系统对于70kg 重的蹦极者来说是非常危险的,因为仿真结果显示蹦极者有触地的危险,为了满足大体重的蹦极爱好者的要求,必须对系统参数做适当的调整。具体如何调整,我们下章再做介绍。

三、离散系统的S-函数描述

用S-函数实现离散系统时,首先要对初始化例程子函数mdlInitializeSizes 做适当修改,包括声明离散状态的个数、对状态进行初始化、确定采样时间等,其次需要定义状态更新和计算输出例程子函数mdlUpdate 和mdlOutputs,分别需要输入表示离散系统的离散状态方程和输出方程。 例10.4 编写S-函数实现输出对输入的单位延迟,即(1)()y k u k +=。 解:单位延迟系统的状态方程可以表示为(1)()x k u k +=,()()y k x k =。 (1)编写S-函数的源文件

① 修改M 文件S-函数的主函数:采用新的函数名:

function [sys,x0,str,ts] = sfun_unitdelay(t,x,u,flag) ② 修改初始化例程子函数: sizes.NumContStates = 0; sizes.NumDiscStates = 1; sizes.NumOutputs = 1; sizes.NumInputs = 1; sizes.DirFeedthrough = 0; sizes.NumSampleTimes = 1;

x0 = 0;

ts = [0.1 0];

定义状态更新例程子函数

图10.8 蹦极跳系统的仿真模型及仿真结果

133

function sys=mdlUpdate(t,x,u) sys = u;

定义计算输出例程子函数

function sys=mdlOutputs(t,x,u) sys = x;

(2)建立如图10.9所示的系统仿真模型,运行仿真,仿真结果如图10.9所示,验证了S-函数的正确性。

四、混合系统的

S-函数描述

既包含离散状态,又包含连续状态的系统称为混合系统。这里我们介绍如何用S-函数描述一个连续积分器后接一个离散单位延迟的混合系统。

例10.5 编写S-函数实现一个连续积分器后接一个离散单位延迟的混合系统。

解:首先,在初始化例程要定义两个采样时间:连续采样时间和离散采样周期,于是在这两个采样时间决定的采样点,Simulink 都会调用S-函数源文件,并依次用flag 来指定要调用的例程。

在混合系统中,与离散状态和连续状态有关的S-函数例程都有可能执行,但各自的执行时间不同。连续状态的导数计算是在每个微时间步都要进行的,但离散状态的更新以及系统的输出计算,只在离散采样点到达时才完成。但这一点Simulink 是无法区分什么时候该更新什么时候不该更新。因为Simulink 从初始化获得的信息只是该系统既有离散状态又有连续状态,据此只能决定该函数的仿真循环应该包含连续状态的微分计算和离散状态的更新例程,没有足够的信息来判断当前时刻是否是离散采样点。

这时常用的技巧是,在mdlUpdate 和mdlOutputs 中由程序判断当前时刻是否是离散采样点。mdlUpdate 例程中完成此功能的语句是:

if abs(round((t - doffset)/dperiod) - (t - doffset)/dperiod) < 1e-8 sys = x(1); % 是离散采样点,将离散状态更新为当前连续状态 else

sys = []; % 不是离散采样点,离散状态保持不变 end

mdlOutputs 例程中完成此功能的语句类似,这里就不赘述了。

图10.9 单位延迟系统的仿真模型及结果

本系统的S-函数源文件的代码如下:

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

dperiod = 1; % 设置离散采样周期和偏移量

doffset = 0;

switch flag

case 0

[sys,x0,str,ts]=mdlInitializeSizes(dperiod,doffset);

case 1

sys=mdlDerivatives(t,x,u);

case 2,

sys=mdlUpdate(t,x,u,dperiod,doffset);

case 3

sys=mdlOutputs(t,x,u,doffset,dperiod);

case 9

sys = []; % do nothing

otherwise

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

end

function [sys,x0,str,ts]=mdlInitializeSizes(dperiod,doffset)

sizes = simsizes;

sizes.NumContStates = 1; % 一个连续状态

sizes.NumDiscStates = 1; % 一个离散状态

sizes.NumOutputs = 1; % 一个输出

sizes.NumInputs = 1; % 一个输入

sizes.DirFeedthrough = 0; % 没有直接馈入

sizes.NumSampleTimes = 2; % 两个采样时间

sys = simsizes(sizes);

x0 = ones(2,1); % 初值均设置为1

str = [];

ts = [0 0; % 采样时间是[0 0]表示连续系统

dperiod doffset]; % 离散采样时间及偏移量,主程序开始时已设置

function sys=mdlDerivatives(t,x,u)

sys = u; % 连续系统是积分环节

function sys=mdlUpdate(t,x,u,dperiod,doffset)

if abs(round((t - doffset)/dperiod) - (t - doffset)/dperiod) < 1e-8

sys = x(1); % 离散系统是单位延迟

else

sys = [];

134

end

function sys=mdlOutputs(t,x,u,doffset,dperiod)

if abs(round((t - doffset)/dperiod) - (t - doffset)/dperiod) < 1e-8

sys = x(2); % 输出采样延迟

else

sys = [];

end

10.4 编写C MEX S-函数

10.3节介绍的M文件S-函数由于具有易于编写和理解的特点,在仿真计算中得到了广泛的应用。但是它有一些缺点:首先,M文件S-函数使得每个仿真步都必须激活MATLAB解释器,以致仿真速度变慢;其次,当需要利用RTW从Simulink框图生成实时代码时,框图中不能含有M文件S-函数。而C MEX S-函数不仅运算速度快,而且可以用来生成独立的仿真程序。现已的C语言编写的程序还可以方便地通过包装程序结合至C MEX S-函数中。C MEX S-函数结合了C语言的优势,可以实现对操作系统和硬件的访问,实现与串口或网络的通信,编写设备驱动程序等。

本节介绍C MEX S-函数的概念及编程使用方法。

10.4.1 MEX文件

M文件S-函数在MATLAB环境下可以通过解释器直接执行,而C文件或其它语言编写的S-函数,则需要先编译成可以在MATLAB内运行的二进制代码:动态连接库或静态连接库,然后才可以使用,这些经过编译的二进制文件就称作MEX文件。在Windows系统下MEX文件后缀是dll。要将C文件S-函数编译成动态连接库,需MATLAB命令窗口键入:

>> mex my_sfunction.c % my_sfunction.c是用户自己编写的C文件S-函数文件名 要使用mex命令,需要先在系统中安装C编译器。如果系统中还没有设置编译器,则要在命令窗口键入:

>> mex -setup

然后按照提示选取VC、BC或其它C编译器。建议使用VC编译器。生成的文件my_sfunction.dll即是所需的动态连接库。当C文件中使用了其它库文件时,编译时应该在其后面加上引用的库文件名。如 >> mex my_sfunction.c kernel32.lib

其实M文件S-函数也可以编译成MEX文件再使用,此时MATLAB调用的是动态连接库而不是M文件本身。M文件S-函数编译成MEX文件实际上是先用特定的命令将其转换成C文件S-函数,再调用C编译器编译链接的。这样编译的代码一般比M文件的S-函数执行速度快,且其代码是二进制的,具有保密性。要将M文件编译成MEX文件,可在MATLAB命令窗口键入:

>> mcc –S mfilename

其中,-S选项表示编译的是S-函数。在Windows系统下生成文件mfilename.c、mfilename.h、mfilename_simulink.c和mfilename.dll。在这个过程中,mcc自动调用了mex命令将生成的C代码编译成动态连接库。

10.4.2 C MEX S-函数模板

与M文件S-函数类似,Simulink也为用户提供了编写C MEX S-函数的模板。通常使用模板文件sfuntmpl_basic.c,它为用户提供了C MEX S-函数的框架结构。该文件包含了常用的几个例程,这对于一般的应用已经足够了。文件sfuntmpl_doc.c则包含了所有的例程,并附有详细的说明。

每个C MEX S-函数的开头应包含下列语句:

#define S_FUNCTION_NAME your_sfunction_name_here

135

#define S_FUNCTION_LEVEL 2

#include "simstruc.h"

其中your_sfunction_name_here是用户要编写的S-函数的名字,即S-function模块要输入的S -函数名。S-函数的格式随之Simulink版本的不同而略有不同,这里S_FUNCTION_LEVEL说明了该S-函数适用的Simulink版本。头文件simstruc.h定义了S-函数的一个重要数据结构。S-函数的有关信息都保存在此数据结构中。另外,头文件simstruc.h还包含着其它重要的头文件,如tmwtypes.h,头文件tmwtypes.h定义了各种数据类型。

另外,和编写普通的C文件相同,在文件的顶部还应包含适当的头文件或定义其它的宏或者变量。在它的尾部必然包含下面代码:

#ifdef MATLAB_MEX_FILE

#include "simulink.c"

#else

#include "cg_sfun.h"

#endif

宏MATLAB_MEX_FILE用于告诉编译器该S-函数正被编译成MEX文件。这组代码的含义是如果该文件正被编译成MEX文件(Windows下为dll文件),包含simulink.c;如果正在使用RTW将整个Simulink 框图编译成实时的独立程序(Windows下为exe文件),包含头文件cg_sfun.h。模板中其它的代码是几个和M文件S-函数中功能类似的S-函数例程。和M文件S-函数不同,Simulink不是通过显式的flag 参数来指定调用C MEX S-函数例程的。这是因为Simulink在交互时会自动地在合适的时候调用每个S -函数的例程。下面分别介绍C MEX S函数在不同仿真阶段的例程。

一、初始化

C MEX S-函数的初始化部分包括下面三个不同的例程函数:

1、mdlInitializeSizes:在该函数中给出各种数量信息;

2、mdlInitializeSampleTimes:在该函数给出采样时间;

3、mdlInitializeConditions:在该函数给出初始状态。

mdlInitializeSizes通过宏函数对状态、输入、输出等进行设置。工作向量的维数也是在此例程中设置。C MEX S-函数还需要在此例程声明期望的输入参数的个数。表10.2列出了初始化所用到的部分宏函数。初始化工作实际上都是通过宏函数访问SimStruct数据结构的。

表10.2 S-函数初始化所用的宏函数

宏 函 数 定 义 功 能 描 述

ssSetNumContStatus(S, numContStates) 设置连续状态个数

ssSetNumDiscStatus(S, numDiscStates) 设置离散状态个数

ssSetNumOutputs(S, numOutputs) 设置输出个数

ssSetNumInputs(S, numInputs) 设置输入个数

ssSetDirectFeedthrough (S,dirFeedThrou) 设置是否存在直接前馈

ssSetNum SampleTimes (S, numSampleTimes) 设置采样时间数目

ssSetNumInputArgs(S, numInputArgs) 设置输入参数个数

ssSetNumIWork (S, numIWork) 设置整数型工作向量维数 ssSetNumRWork (S, numRWork) 设置实数型工作向量维数 ssSetNumPWork (S, numPWork) 设置指针型工作向量维数 实际上是为各个工作向量分配内存提供依据。

二、使用输入和输出

在C MEX S-函数中,对输入输出的操作也是通过描述该S-函数的SimStruct进行的。比如,在C MEX S-函数中如果需要对输入进行操作,需要先使用宏函数:

input=ssGetInputPortRealSignalPtrs(S,index)

136

137

该宏函数的返回中含有指向输入向量的指针,其中每个元素通过*input[i]来访问。同样,如果需要对输出进行操作,需要先使用下列宏函数得到指向输出的指针: output=ssGetOutputPortRealSignal (S,index)

有关输入与输出相关的宏函数见表10.3。

表10.3 有关输入与输出的宏函数

宏函数

功能描述

ssGetInputPortRealSignalPtrs 获得指向输入的指针(double 型) ssGetInputPortSignalPtrs 获得指向输入的指针(其它数据类型) ssGetInputPorWidth 获得输入信号的宽度

ssGetInputPortOffsetTime 获得输入端口的采样时间偏移量 ssGetInputPortSampleTime 获得输入端口的采样时间 ssGetOutputPortRealSignal 获得指向输出的指针 ssGettOutputPorWidth 获得输出信号的宽度

ssGetOutputPortOffsetTime 获得输出端口的采样时间偏移量 ssGetOutputPortSampleTime

获得输出端口的采样时间

三、使用参数

使用用户自定义参数时,在初始化时,必须说明参数的个数。为了得到指向存储参数的数据结构的指针,必须使用宏函数ptr=ssGetSFcnParam(S,index);为了得到存储在此数据结构中的指向参数值本身的指针,需要使用宏:mxGetPr(ptr);使用参数值时要使用宏:param_value=* mxGetPr(ptr). 四、使用状态

若S 函数中包含连续或离散状态,则需要编写mdlDerivatives 或mdlUpdate 子函数。使用宏:ssGetRealDiscStates(S)可以得到指向离散状态向量的指针;使用宏函数:ssGetContStates(S) 可以得到指向离散状态向量的指针。在mdlDerivatives 函数中,连续状态的导数由状态和输入量计算而得,可以通过宏*dx=ssGetX(S)将SimStruct 结构体中的连续状态导数指针指向得到的结果,然后修改所指向的值。在多状态情况下,需要通过索引得到dx 中的每个元素。它们被返回给求解器,求解器再积分求出状态。需要指出的是,在离散系统中,没有对应于dx 的变量,由于状态是由S-函数更新的,不需要求解器再做工作。

10.4.3 C MEX S 函数应用举例

这里给出几个C S 函数的示例,以帮助用户更快地掌握C S 函数的编程方法。 例10.6 S-函数csfunc 描述了一个用状态方程表示的线性连续系统:

x

Ax Bu y Cx Du

=+=+

下面是其C MEX S-函数的完整源代码和注释。

#define S_FUNCTION_NAME csfunc1 /* S-函数名称 */ #define S_FUNCTION_LEVEL 2 #include "simstruc.h"

#define U(element) (*uPtrs[element]) /* 宏定义,方便对输入的索引 */ /* 定义状态方程中的参数 A B C D 阵 */

static real_T A[2][2]={ { -0.09, -0.01 } ,

{ 1 , 0 } /* 在C S 函数中有一套自己的数据*/ }; /* 类型表示方法,real_T 表示双精 */ static real_T B[2][2]={ { 1 , -7 } , { 0 , -2 }

};

static real_T C[2][2]={ { 0 , 2 } ,

{ 1 , -5 }

};

static real_T D[2][2]={ { -3 , 0 } , /* 存在直接馈入*/

{ 1 , 0 }

};

static void mdlInitializeSizes(SimStruct *S)

{

ssSetNumSFcnParams(S, 0); /* 不含用户参数,设置为零 */

if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {

return; /* 若参数不匹配,Simulink将发出警告 */

}

ssSetNumContStates(S, 2); /* 系统有两个连续状态*/

ssSetNumDiscStates(S, 0); /* 系统无离散状态*/

if (!ssSetNumInputPorts(S, 1)) return; /* 如果输入端口数不为1,则返回*/

/* S-functions块只有一个输入端口,当需要多个输入时,必须使用mux模块把需要输入的信号合成一个向量*/

ssSetInputPortWidth(S, 0, 2); /* 输入信号宽度为2 */

ssSetInputPortDirectFeedThrough(S, 0, 1); /* 设置馈通标志为1 */

if (!ssSetNumOutputPorts(S, 1)) return; /* 如果输出端口数不为1,则返回*/

ssSetOutputPortWidth(S, 0, 2); /* 输出信号宽度为2 */

ssSetNumSampleTimes(S, 1); /* 1个采样时间 */

ssSetNumRWork(S, 0); /* 不使用工作向量 */

ssSetNumIWork(S, 0);

ssSetNumPWork(S, 0);

ssSetNumModes(S, 0);

ssSetNumNonsampledZCs(S, 0);

ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);

}

static void mdlInitializeSampleTimes(SimStruct *S)

{

ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);

/*连续系统的采样时间设置为0,等同于ssSetSampleTime(S, 0, 0) */

ssSetOffsetTime(S, 0, 0.0);

}

#define MDL_INITIALIZE_CONDITIONS

static void mdlInitializeConditions(SimStruct *S)

{

real_T *x0 = ssGetContStates(S); /* 获得指向连续状态的指针*/

int_T lp;

for (lp=0;lp<2;lp++) {

*x0++=0.0; /* 各状态初值设置为0 */

}

138

139

static void mdlOutputs(SimStruct *S, int_T tid)

{ /*获得指向输出向量、连续状态向量和输入端口的指针 */

real_T *y = ssGetOutputPortRealSignal(S,0); real_T *x = ssGetContStates(S);

InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0); UNUSED_ARG(tid); /* not used in single tasking mode */ /* y=Cx+Du 输出方程 */

y[0]=C[0][0]*x[0]+C[0][1]*x[1]+D[0][0]*U(0)+D[0][1]*U(1); y[1]=C[1][0]*x[0]+C[1][1]*x[1]+D[1][0]*U(0)+D[1][1]*U(1); }

#define MDL_DERIVATIVES

static void mdlDerivatives(SimStruct *S) {

real_T *dx = ssGetdX(S); /* 获得指向状态导数向量的指针 */ real_T *x = ssGetContStates(S);

InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0); /* xdot=Ax+Bu 状态方程 */

dx[0]=A[0][0]*x[0]+A[0][1]*x[1]+B[0][0]*U(0)+B[0][1]*U(1); dx[1]=A[1][0]*x[0]+A[1][1]*x[1]+B[1][0]*U(0)+B[1][1]*U(1); }

static void mdlTerminate(SimStruct *S) {

UNUSED_ARG(S); /* unused input argument */ }

#ifdef MATLAB_MEX_FILE /* 是否编译成MEX 文件 ? */ #include "simulink.c" /* 包含MEX 文件的接口机制 */ #else

#include "cg_sfun.h" /* 代码生成注册函数 */ #endif

例10.7 由C MEX S 函数实现对下列van der pole 方程的求解。

???

???==1

22

1221)1(x x x m x x x 并要求m 值和状态初值0x 由用户输入。

解 建立如图10.10的系统仿真方程。Van der pole 方程由C MEX S 函数实现,其C 程序代码如下:

#define S_FUNCTION_NAME van_der2 #define S_FUNCTION_LEVEL 2 #include "simstruc.h"

#define M ssGetSFcnParam(S,0) #define X00 ssGetSFcnParam(S,1)

static void mdlInitializeSizes(SimStruct *S) /* 得到指向存储参数的数据结构的指针 */

ssSetNumSFcnParams(S, 2); /* 两个用户参数 */

if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {

return; /* Parameter mismatch will be reported by Simulink */

}

ssSetNumContStates(S, 2); /* 两个连续状态 */

ssSetNumDiscStates(S, 0);

if (!ssSetNumInputPorts(S, 0)) return; /* 系统无输入端口 */

if (!ssSetNumOutputPorts(S, 1)) return;

ssSetOutputPortWidth(S, 0, 2); /* 输出信号为2维 */

ssSetNumSampleTimes(S, 1); /*一个采样时间 */

ssSetNumRWork(S, 0);

ssSetNumIWork(S, 0);

ssSetNumPWork(S, 0);

ssSetNumModes(S, 0);

ssSetNumNonsampledZCs(S, 0);

ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);

}

static void mdlInitializeSampleTimes(SimStruct *S)

{

ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);

ssSetOffsetTime(S, 0, 0.0);

}

#define MDL_INITIALIZE_CONDITIONS

static void mdlInitializeConditions(SimStruct *S)

{

real_T *x0 = ssGetContStates(S);

const real_T *x00=mxGetPr(X00); /* 得到存储在数据结构中的指向参数值本身的指针 x0[0] =x00[0];

x0[1] = x00[1];

}

static void mdlOutputs(SimStruct *S, int_T tid)

{

real_T *y = ssGetOutputPortRealSignal(S,0);

real_T *x = ssGetContStates(S);

y[0]=x[0];

y[1]=x[1];

}

#define MDL_DERIVATIVES

static void mdlDerivatives(SimStruct *S)

{

real_T *dx = ssGetdX(S);

real_T *x = ssGetContStates(S);

const real_T m = *mxGetPr(M);

140

141

dx[0] = -m*x[0] * (1.0 - x[1] * x[1]) - x[1]; dx[1] = x[0]; }

static void mdlTerminate(SimStruct *S) {

UNUSED_ARG(S); /* unused input argument */ }

#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else

#include "cg_sfun.h" /* Code generation registration function */ #endif

由例10.6和10.7给出的程序可以看出,C MEX S-函数是通过一套宏函数获得指向存储在SimStruct 中的输入、输出、状态、状态导数及用户参数的指针来引用这些变量,从而完成对系统的描述。

10.4.4 S-function Builder

Simlink 为用户编写常用的 C MEX S-函数提供了一个非常方便的开发工具――S-function Builder。S-function Builder 可以使读者不需了解任何宏函数就可以编写出自己的C MEX S-函数。用户只需在S-function Builder 界面中的相应位置写入所需的信息和代码即可。S-function Builder 会自动生成C MEX S-函数源文件。用户只要单击Build 按钮,S-function Builder 就会自动编译,自动生成用户所需的MEX 文件。

下面通过例子介绍S-function Builder 的应用。

例10.8 利用S-function Builder 实现对Van der pole 方程的求解。

解 从Simulink 游览器中将S-function Builder 图标拖至新建的模型文件中。

双击S-function Builder 图标,即可打开如图10.11(a)所示的S-function Builder 界面。用户可以看出1、4、5、6选项卡对应着S-函数的四个常用例程。用户只需在相应的例程函数中填写所需的信息和代码即可。下面给出使用S-function Builder 编写S-函数的方法。

图10.10 例10.7系统仿真模型及S

-函数参数对话框

美赛数学建模专用-第七章 Simulink 基础

美赛数学建模专用- 第七章Simulink 基础 Chapter 7: Introduction to Simulink 一.Simulink 初步(Primer of Simulink) MATLAB Simulink是一个动态仿真系统,用于对动态系统进行仿真和分析,预先模拟实际系统的特性和响应,根据设计和使用要求,对系统进行修改和优化。 Simulink提供了图形化用户界面,只须点击鼠标就可以轻易的完成模型的创建、调试和仿真工作,用户不须专门掌握一种程序设计语言。 Simulink可将系统分为从高级到低级的几个层次,每层又可以细分为几个部分,每层系统构建完成后,将各层连接起来构成一个完整系统。 模型创建完成后,可以启动系统的仿真功能分析系统的动态特性,其内置的分析工具包括各种仿真算法、系统线性化、寻求平衡点等。仿真结果可以以图形方式在示波器窗口显示,也可将输出结果以变量形式保存起来,并输入到MATLAB中以完成进一步的分析。 Simulink可以仿真线性和非线性系统,并能创建连续时间、离散时间或二者混合的系统。支持多采样频率系统。 Simulink Version 6.0 (R14) 05-May-2004 Model analysis and construction functions. Simulation sim - Simulate a Simulink model. sldebug - Debug a Simulink model. simset - Define options to SIM Options structure. simget - Get SIM Options structure Linearization and trimming. linmod - Extract linear model from continuous-time system. linmod2 - Extract linear model, advanced method. dlinmod - Extract linear model from discrete-time

第七章 Simulink 基础

第七章Simulink 基础 一.Simulink 初步 MATLAB Simulink是一个动态仿真系统,用于对动态系统进行仿真和分析,预先模拟实际系统的特性和响应,根据设计和使用要求,对系统进行修改和优化。 Simulink提供了图形化用户界面,只须点击鼠标就可以轻易的完成模型的创建、调试和仿真工作,用户不须专门掌握一种程序设计语言。 Simulink可将系统分为从高级到低级的几个层次,每层又可以细分为几个部分,每层系统构建完成后,将各层连接起来构成一个完整系统。 模型创建完成后,可以启动系统的仿真功能分析系统的动态特性,其内置的分析工具包括各种仿真算法、系统线性化、寻求平衡点等。仿真结果可以以图形方式在示波器窗口显示,也可将输出结果以变量形式保存起来,并输入到MATLAB中以完成进一步的分析。 Simulink可以仿真线性和非线性系统,并能创建连续时间、离散时间或二者混合的系统。支持多采样频率系统。 Simulink的三大步骤:模型创建与定义、模型的分析、模型的修正。 Simulink的运行: 1.命令窗口下点击Simulink图标(或键入Simulink命令)→Sim→sim模块

2.打开模型创建窗口:在工具栏中选择“建立新模型”的图标,弹出名为Untitled的空白窗口。 二.Simulink 的基本模块 simulink浏览器窗口左侧的simulink项上单击鼠标右键,弹出菜单“Open the ‘Simulink’Labrary’”选项,将打开simulink模块库窗口。1.信号源模块:source,模块及功能见(表8—1) 2.输出模块:Sinks, 模块及功能见(表8—2) 3. 连续系统模块:Continuous, 模块及功能见(表8—3) 4. 离散系统模块:Discrete, 模块及功能见(表8—4) 5. 数学运算模块:Math, 模块及功能见(表8—5) 6.函数和表模块:Function & Tables, 模块及功能见(表8—6) 7. 非线性系统模块:Nonlinear, 模块及功能见(表8—7) 8. 信号与系统模块:Signal & Systems, 模块及功能见(表8—8) 三. Simulink 建模 1.模块的创建与操作 (1) 创建模块: (1)在浏览器列表中点击需要的模块,按住鼠标左键并拖曳至模型窗口即可。 (2)双击模块可在弹出的对话框中修改相应的模块参数 (3)在模块下方名称处双击可改变模块名称。 (2)模块操作 (a)模块的选择 (b)移动模块 (c)模块的缩放 (d)复制模块:四种方法: *在选定模块处,按下鼠标右键并拖动至适当位置; *选定模块,在工具栏中(或Edit菜单中)选中Copy与Paste 按钮; *在选定的模块处点击鼠标右键,在弹出的菜单中选择Copy与Paste选项;

Simulink 基础

第七章Simulink 基础 Chapter 7: Introduction to Simulink 一.Simulink 初步(Primer of Simulink) MATLAB Simulink是一个动态仿真系统,用于对动态系统进行仿真和分析,预先模拟实际系统的特性和响应,根据设计和使用要求,对系统进行修改和优化。 Simulink提供了图形化用户界面,只须点击鼠标就可以轻易的完成模型的创建、调试和仿真工作,用户不须专门掌握一种程序设计语言。 Simulink可将系统分为从高级到低级的几个层次,每层又可以细分为几个部分,每层系统构建完成后,将各层连接起来构成一个完整系统。 模型创建完成后,可以启动系统的仿真功能分析系统的动态特性,其内置的分析工具包括各种仿真算法、系统线性化、寻求平衡点等。仿真结果可以以图形方式在示波器窗口显示,也可将输出结果以变量形式保存起来,并输入到MATLAB中以完成进一步的分析。 Simulink可以仿真线性和非线性系统,并能创建连续时间、离散时间或二者混合的系统。支持多采样频率系统。 Simulink Version 6.0 (R14) 05-May-2004 Model analysis and construction functions. Simulation sim - Simulate a Simulink model. sldebug - Debug a Simulink model. simset - Define options to SIM Options structure. simget - Get SIM Options structure Linearization and trimming. linmod - Extract linear model from continuous-time system. linmod2 - Extract linear model, advanced method. dlinmod - Extract linear model from discrete-time system.

第七章 SIMULINK交互式(matlab基础教程)

第 7 章 S IMULINK 交互式 仿真集成环境 SIMULINK 是MATLAB 最重要的组件之一,它向用户提供一个动态系统建模、仿真和综合分析的集成环境。在这环境中,用户无须书写大量的程序,而只需通过简单直观的鼠标操作,选取适当的库模块,就可构造出复杂的仿真模型。SIMULINK 的主要优点: ● 适应面广。可构造的系统包括:线性、非线性系统;离散、连续及混合系统;单任务、 多任务离散事件系统。 ● 结构和流程清晰。它外表以方块图形式呈现,采用分层结构。既适于自上而下的设计 流程,又适于自下而上逆程设计。 ● 仿真更为精细。它提供的许多模块更接近实际,为用户摆脱理想化假设的无奈开辟了 途径。 ● 模型内码更容易向DPS ,FPGA 等硬件移植。 基于本书定位,为避免内容空泛,本节对于SIMULINK 将不采用横断分层描述,即不对SIKULINK 库、模块、信号线勾画标识等进行分节阐述。本节将以四个典型算例为准线,纵向描述SIMULINK 的使用要领。 7.1 连续时间系统的建模与仿真 7.1.1 基于微分方程的SIMULINK 建模 本节将从微分方程出发,以算例形式详细讲述SIMULINK 模型的创建和运行。 【例7.1-1】在图7.1-1所示的系统中,已知质量1=m kg ,阻尼2=b N.sec/m ,弹簧系数100=k N/m ,且质量块的初始位移05.0)0(=x m ,其初始速度0)0(='x m/sec ,要求创建该系统的SIMULINK 模型,并进行仿真运行。 图7.1-1 弹簧—质量—阻尼系统 (1)建立理论数学模型 对于无外力作用的“弹簧—质量—阻尼”系统,据牛顿定律可写出

相关主题