第7章 Simulink仿真环境
通过本章的学习,读者将获得以下知识:
· 理解Simulink的概念及其应用;
· 掌握如何使用Simulink搭建系统模型及其特点;
· 掌握如何使用Simulink进行系统仿真并进行调试。
在学习本章时,读者既可按照作者介绍的先后顺序去逐步深入了解,也可以先通过第7.2节或第7.11节的学习来掌握Simulink建模的大概过程和基本步骤,然后再通过学习其他小节的内容来掌握建模过程中的各种具体的操作细节和一些仿真计算的理论问题。
7.1 Simulink概述
下面先向读者介绍一个非常简单的示例,旨在使读者在进行深入学习之前先对Simulink有一个感性的认识。
【创建模型目的】:计算两个不同频率正弦函数相加后再积分的结果,并显示结果的波形。
【创建模型的步骤】:
· 在MATLAB 7.0界面窗口选择File→New→Model菜单项,弹出如图7-1和图7-2所示的窗口;
· 在如图7-1所示窗口左边选中Sources库,然后在右边选Sine Wave模块并按住鼠标左键不放,将它拖到如图7-2所示的窗口中。重复该操作添加第二个Sine Wave模块;
按上一步中的方法向图7-2的窗口中添加Math Operations库中的Add模块、Continuous库中的Integrator模块和Sinks库中的Scope模块;
图7-1 Simulink模块库浏览器
图7-2 新建模型窗口
· 按如图7-3所示连接模块。连接模块的操作方法:用鼠标指向源模块的输出端口,当鼠标变成十字架形时按住鼠标左键不放,然后拖动鼠标指向目标模块输入端口后松开;
· 设置Sine Wave模块的参数。鼠标左键双击Sine Wave模块,弹出如图7-4所示参数设置对话框,设置Frequency为2,然后单击“OK”按钮;
· 单击按钮运行仿真,然后用鼠标左键双击模型中Scope模块,弹出如图7-5所示的输出波形。
图7-3 简单示例模型
图7-4 设置参数
图7-5 输出波形
7.1.1 Simulink的概念
Simulink是MATLAB提供的实现动态系统建模和仿真的一个软件包,它是MATLAB的一个重要组成部分,而且具有相对独立的功能和使用方法。它支持线性和非线性、连续时间系统、离散时间系统、连续和离散混合系统建模,且系统可以是多进程的。
Simulink的一个突出特点是它支持图形用户界面(GUI),模型由模块组成的框图来表示。用户建模通过简单的单击和拖动鼠标的动作就能完成。如果把建模比做建造房子,那么采用高级语言或MATLAB语言直接编写仿真程序的方式来构建模型就好比是从一堆沙子开始来建房子,这种方式不但麻烦容易出错,而且有许多重复操作,建造者的主要精力不是放在房子的结构设计上,而是浪费在如何将沙子变成砖块以及如何将它们组合起来等技术性的问题上,这显然不利于设计者去设计出更多有创造性的结构。在计算机仿真里,就等于设计者把精力放在具体算法的实现上,而不是模型和算法设计本身。Simulink通过自带的模块库(如图7-1所示)为用户提供多种多样的基本功能模块,用户可以直接调用这些模块,而不必从最基本的做起。这样就可以让设计者把精力放在更为重要的更具创造性的算法和模块结构的设计上来。
Simulink的每个模块对于用户来说都相当于一个“黑匣子”,用户只需知道模块的输入和输出以及模块功能即可,而不必管模块内部是怎么实现的。因此,用户使用Simulink进行系统建模的任务就是如何选择合适的模块并把他们按照自己的模型结构连接起来,最后进行调试和仿真。如果仿真结果不满足要求,可以改变模块的相关参数再运行,直到结果满足要求为止。至于在仿真时各个模块是如何执行的、各模块间是如何通信的、仿真的时间是如何采样的以及事件是如何驱动的等细节问题,用户都不用去管,因为这些事情Simulink都解决了。如何添加和删除模块、如何连接各个模块以及如何修改模块的参数和属性等问题将在本章后面的各小节会陆续给予详细的介绍。
Simulink最新版本是Simulink6.0(包含在MATLAB 7.0里),启动Simulink有3种方式。
· 在MATLAB 7.0的命令窗口直接键入“>>Simulink”命令;
· 用鼠标左键单击MATLAB 7.0工具条上的Simulink按钮;
· 在MATLAB 7.0菜单上选择“File→New→Model”选项。
运行后会弹出如图7-1所示的Simulink模块库浏览器窗口,使用第3种方式打开时还会弹出如图7-2所示的新建模型窗口。单击图7-1工具条左边的图标(建立新模型)也会弹出如图7-2所示的窗口。
和Windows窗口类似,在Simulink的模块窗口和模块库窗口的“View”菜单下选择或取消“Toolbar”和“Status Bar”选项,就可以显示或隐藏工具条和状态条。在进行仿真过程中,模型窗口的状态条会显示仿真状态、仿真进度和仿真时间等相关信息。
注意:本章是以Simulink 6.0版为例进行介绍的。
7.1.2 Simulink的工作环境
按照第7.1.1节介绍的方法启动Simulink后,就可以看到如图7-1所示的Simulink模块库浏览器。在建模的过程中会经常对它进行操作,下面介绍该界面各个部分的用途,如图7-6所示。
图7-6 Simulink模块库浏览器的结构
对于熟悉Windows窗口的读者来说,Simulink模块库浏览器的界面应该很容易掌握,在这里就不做详细介绍了。读者可以单击每个标题前的加号,将列出库里的模块,而且还能了解到每个模块的功能说明,在第7.1.6小节将向读者详细地介绍其中一些库中的常用模块。
接下来向读者介绍Simulink模型窗口界面。模型建立好之后开始进行各项操作,大部分的操作都是在模型窗口完成的,因此读者需要熟练掌握这些操作,并且要了解其中的各个菜单(如表7-1~表7-6所示)和按钮(如图7-11所示)的功能。
1.“File”菜单
“File”菜单中各选项的名称与功能如表7-1所示。
表7-1 “File”菜单
图7-7 “Preferences”对话框
图7-8 模型报告文件
2.“Edit”菜单
“Edit”菜单中各选项的名称与功能如表7-2所示。
表7-2 “Edit”菜单
3.“View”菜单
该菜单的内容较多,但大部分命令都很容易理解掌握。其中“Model Browser Options ”、“Block Data Tips Optioons”和“Port Values”用于设置在鼠标指针移到某一模块时有没有模块及其端口的相关提示信息,菜单的子选项用于选择在提示信息中显示哪些内容。“View”菜单中各主要选项具体的名称与功能如表7-3所示。
表7-3 “View”菜单
图7-9 模型资源管理器
4.“Simulation”菜单
“Simulation”菜单如图7-10所示,下面将介绍该菜单中各选项的功能。
“Start”:开始运行仿真。
“Stop”:停止仿真。
“Configuration Parameters”:设置仿真参数和选择解法器(设置方法在第7.7.2节介绍)。“Normal”、“Accelerator”、“External”分别表示正常工作模式、加速仿真和外部工作模式。
图7-10 “Simulation”菜单
5.“Format”菜单
该菜单主要用于设置字体、屏幕颜色、模块名的显示、模块显示颜色、信号和端口类型和宽度等,各项都较容易掌握,各子菜单的功能如表7-4所示。
表7-4 “Format”菜单
6.“Tools”菜单
该菜单的内容较多,大部分是用来打开各种编辑器或设置对话框,用以设置与模型的仿真相关的参数。“Tools”菜单中各主要选项的功能如表7-5所示。
表7-5 “Tools”菜单
图7-11 模型窗口的工具栏
7.“Help”菜单
“Help”菜单中各主要选项的名称与功能如表7-6所示。
表7-6 “Help”菜单
图7-12 模块支持的数据类型
7.1.3 Simulink的工作原理
虽然Simulink为用户屏蔽了许多繁琐的编程工作,但用户要想更灵活高效地使用它,就必须了解它的工作原理。由前面的示例可以看出Simulink建模大体可分成两步。创建模型的图标和控制Simulink对它进行仿真。但是用户可能并不明白这些图形化的模型和现实系统之间到底存在着怎样的映射关系,以及Simulink是如何对这些模型进行仿真的。下面就来解决这两个问题。
1.图形化的模型和现实系统之间的映射关系
现实中的每一个系统都有输入、输出和状态3个基本元素,以及它们之间随时间变化的数学函数关系。Simulink模型中每一个图形化的模块代表现实系统中一个元件的输入、输出和状态间随时间变化的函数关系,即元件或系统的数学模型,如图7-13所示。系统的数学模型是由一系列数学方程式(代数环、微分和差分等式)来描述的,每一个模块都代表一组数学方程,Simulink中称这些方程为模块或模型的方法(即一组MATLAB函数)。模块和模块之间的连线代表系统中各元件输入/输出信号的连接关系,也代表了随时间变化的信号值。
图7-13 模块的图形化表示
2.Simulink是如何对图形化模型进行仿真的
Simulink对模型进行仿真的过程,就是在用户定义的时间段内根据模型提供的信息计算系统的状态和输出的过程。当用户开始仿真,Simulink分以下几个阶段来运行仿真。
(1)模型编译阶段
Simulink引擎调用模型编译器,将模型编译成可执行的形式。编译器主要完成以下任务:
· 评价模块参数的表达式以确定它们的值;
· 确定信号属性(如名字、数据类型等);
· 传递信号属性以确定未定义信号的属性;
· 优化模块;
· 展平模型的继承关系(如子系统);
· 确定模块运行的优先级;
· 确定模块的采样时间。
(2)连接阶段
Simulink引擎创建按执行的次序排列的方法(也即函数)运行列表,同时定位和初始化存储每个模块的运行信息的存储器。
(3)仿真环阶段
Simulink引擎在从仿真的开始时间到结束时间,在每一个时间间隔点按顺序计算系统的状态和输出。这些计算状态和输出的时间点就称作时间步,相邻两个时间点间的长度就称作步长,步长的大小取决于求解器的类型。该阶段又分成两个子阶段。
· 仿真环初始化阶段。该阶段只运行一次,用于初始化系统的状态和输出。
· 仿真环迭代阶段。该阶段在定义的时间段内每隔一个时间步就重复运行一次,用于在每一个时间步计算模型的新的输入、输出和状态,并更新模型使之能反应系统最新的计算值。在仿真结束时,模型能反应系统最终的输入、输出和状态值。
7.1.4 Simulink模型的特点
使用Simulink建立的模型具有以下3个特点:
· 仿真结果的可视化;
· 模型的层次性;
· 可封装子系统。
下面通过一个Simulink提供的演示示例来说明上述特点。用户先通过菜单命令Help→MATLAB Help或是“Help”命令打开如图7-14所示的帮助窗口,然后在“Demos”选项卡中选择Simulink→General Applications→Thermodynamic Model of a House,单击右边文本框中有下画线的文字“Open this model”打开如图7-15所示的窗口。用户还可以通过在MATLAB 7.0命令窗口输入“>>thermo”命令打开该窗口。
· 单击“开始”按钮,可以看到如图7-16所示的仿真结果;
· 鼠标左键双击模型图标中的House模块,弹出如图7-17所示House子系统图标。
对于上述的特点,读者在学完后续章节后将会有更加深刻的理解。
图7-14 MATLAB 7.0帮助
图7-15 thermo演示模型
图7-16 仿真结果可视化
图7-17 House子系统图标
7.1.5 Simulink里的数据类型
在计算机编程语言中,数据类型决定了分配给一个数据的存储资源,决定数据表示的精度、动态范围、性能和存储资源。MATLAB语言也是一种编程语言,因此Simulink中也允许用户说明Simulink模型中信号和模块参数的数据类型。
Simulink在开始仿真之前以及仿真过程中会进行一个额外的检查(系统自动进行,不需手动设置),以确认模型的类型安全性。所谓模型的类型安全性,是指保证该模型产生的代码不会出现上溢或下溢,不至于产生不精确的运行结果。使用Simulink默认数据类型(double)的模型都是固有类型安全的。
1.Simulink支持的数据类型
Simulink支持所有的MATLAB内置数据类型,内置数据类型是指MATLAB自己定义的数据类型。表7-7列出了所有的MATLAB内置数据类型。
表7-7 MATLAB 7.0内置数据类型
除了内置数据类型,Simulink还定义了布尔类型,取值为0和1,它们内部的表示是uint8(无符号8位整数)。所有的Simulink模块都默认为double类型的数据,但有些模块需要布尔类型的输入,而另外一些模块支持多数据类型输入,还有些支持复数信号。
关于模块的输入/输出信号支持的数据类型的详细说明,用户可以通过模块参数设置对话框(双击模块图标就会弹出对话框)来查看。如果在一个模块的参数设置对话框中没有说明它支持的数据类型的选项,那就表示它只支持double类型的数据,如图7-18所示。用户还可以选择Simulink模型窗口中的“Help”菜单中的“Block Support Table”子菜单,打开如图7-12所示的帮助窗口,其中总结了所有Simulink库中的模块所支持的数据类型的情况。
选择模型窗口的Format→Port/Signal Displays→Port Data Types可以查看信号的数据类型和模块输入/输出端口的数据类型,如图7-19所示。
图7-18 查看模块支持的数据类型
图7-19 查看信号的数据类型
在设置模块参数时,指定一个值为某一数据类型的方法为type(value)。例如要把常数模块的参数设为1.0单精度表示,则可以在参数对话框输入single(1.0)。如果模块不支持所设置的数据类型,那么就会弹出错误警告,如图7-20所示。
图7-20 设置模块参数的数据类型
在建立模型时,常常需要向模型提供某种特定类型的输入信号数据,把一个具有特定数据类型的信号引入模型具体有以下几种方法。
· 通过根目录import或者From Workspace模块将MATLAB 7.0工作空间中具有指定数据类型的信号数据导入你的模型;
· 建立一个常数模块并设置它的参数为指定的类型;
· 使用DataTypeConversion模块将一个信号转换为指定类型的信号。
2.数据类型的传播
构造模型时会将各种不同类型的模块连接起来,而这些不同类型的模块所支持的数据类型往往不完全相同。如果用直线连接在一起的两个模块所支持的数据类型(注意是指输出/输入信号的数据类型,而不是模块参数的数据类型)有冲突,那么当进行仿真、查看端口数据类型或是更新数据类型时就会弹出一个提示对话框,告诉用户出现冲突的信号和端口,而且有冲突的信号的路径会被加亮显示。这时就可以通过在有冲突的模块之间插入一个DataTypeConversion模块来解决类型冲突。
一个模块的输出一般是模块输入和模块参数的函数。而在实际建模过程中,输入信号的数据类型和模块参数的数据类型往往是不同的,Simulink在计算这种输出时会把参数类型转换到信号的数据类型。但是如果出现下面的这些情形,就要进行不同的处理。
· 当信号的数据类型无法表示参数值时,Simulink将中断仿真,并给出错误信息。
在如图7-21所示的示例模型,两个常数模块的输出信号类型设置为布尔型,而连续信号积分器只接受double类型信号,所以弹出出错提示框。这时可以在示例模型中插入(如果读者不熟悉该操作,参考第7.2.1节的内容)一个DataTypeConversion模块,并将其输出改成double数据类型就不会报错了,如图7-22所示。
图7-21 数据类型示例模型
图7-22 修改后的示例
· 如果信号的数据类型能够表示参数的值,仅仅是损失表示的精度,那么Simulink会继续仿真,并在MATLAB 7.0命令窗口中给出一个警告信息。
在如图7-23所示的图中,常数模块的常数值参数设置为uint8(1),输出数据类型设为“Inherit from Constant value”;增益模块的增益参数设置为double(3.2),输出数据类型设为“Same as input”,参数数据类型设置为“Interit via internal rule”。Simulink会把3.2的整数部分截取,并转换成无符号数,所以最后结果为3。
图7-23 数据精度损失的示例
3.使用复数信号
Simulink中默认的信号值都是实数,但在实际问题中有时需要处理复数信号。在Simulink中通常用下面示例中的两种方法来建立处理复数信号的模型,如图7-24所示。
· 向模型中加入一个Constant模块,将其参数设为复数;
· 分别生成复数的虚部和实部,再用Real-Image to Complex模块把它们联合成一个复数;
· 分别生成复数的幅值和幅角,再用Magnitue-Angle to Complex模块把它们联合成一个复数。
图7-24 引入复数
同样可以在Simulink中利用相关的模块将一个复数分解成虚部和实部或是幅值和幅角,而且Simulink中有许多的模块都接受复数输入并对复数进行运算,请读者自己查阅帮助文件来了解这些模块。
注意:Real-Image to Complex模块和Magnitue-Angle to Complex模块均在Simulink库的Math Operations子库中。
4.标量信号和向量信号
向量信号是多个信号的集合,对应着模块窗口中几条并行连线的合成。Simulink中大多数模块的输出默认情况下为标量信号,当输入为向量信号而模块参数为标量时,Simulink会自动进行匹配。接下来通过介绍两个示例来回答下面两个问题。
· 怎样让模块输出向量信号?
· 当一个模块的输入既有向量又有标量时,Simulink如何计算输出?即标量扩展问题。
【示例1】使模块输出向量信号
在如图7-25所示的左边第一个示例,第一个模型中Constant模块的常数值参数设为[1 3],输出信号的宽度为2,因此Scope有两条直线。第二个模型中Sine Wave模块的幅度设为[1 3],频率设为[1 2],输出一个两位的向量信号,因此Scope中有两条直线。
图7-25 输出向量的模块示例
注意示例中Sine Wave的输出不是4位向量,模块中所有参数都是按向量元素的位置来和信号对应,不存在自由组合的问题。读者在设置向量参数时一定要注意不同参数之间向量大小的匹配问题。上例中若将Frequency设为1,不会出错;但若是设为[1 2 3],就会报错。
【示例2】既有向量又有标量输入的模块
在如图7-26所示的第二个示例中,由于输出信号的宽度设置为2,因此Scope中显示有两条直线。Simulink将Constant的1位标量信号扩展成2位的向量,新扩展位的值与原来的标量信号值相同。但是与上一例相似的是,如果一个信号是3位向量,一个是2位的向量,那么就会报错,因为Simulink无法确定扩展2位向量为3位向量时该以2位向量哪一位的值为标准。模块的参数也存在标量扩展的问题,读者只要多实践就会很容易掌握其中的规律。
图7-26 标量扩展的示例
7.1.6 Simulink里的模块和模块库
用Simulink建模的过程,可以简单地理解为从模块库里选择合适的模块,然后将它们连接在一起,最后进行调试仿真。
模块库的作用就是提供各种基本模块,并将它们按应用领域以及功能进行分类管理以方便用户查找。库浏览器将各种模块库按树状结构进行罗列,以便用户快速地查询所需模块,同时它还提供了按名称查找的功能(如图7-6所示)。库浏览器中模块的多少取决于用户的安装,但至少应该有Simulink库,用户还可以自定义库。
模块是Simulink建模的基本元素,了解各个模块的作用是熟练掌握Simulink的基础。库中各个模块的功能可以在库浏览器中查到,如图7-6所示。下面详细介绍Simulink库中几个常用子库中的常用模块的功能,如表7-8~表7-17所示,完整的介绍见本书附录。
表7-8 Commonly Used Blocks子库
表7-9 Continuous子库
表7-10 Discontinuities子库
表7-11 Discrete子库
表7-12 Logic and Bit Operations子库
表7-13 Math Operations子库
表7-14 Ports & Subsystems子库
表7-15 Sinks子库
表7-16 Sources子库
表7-17 User-Defined Functions子库
除Simulink库之外,MATLAB 7.0还为用户提供了大量不同应用领域的基本模块库。关于这部分内容,请读者通过前面介绍的方法在Simulink模块库浏览器中查看各个模块的功能。
图7-27 信号产生器图形用户界面
图7-28 S-函数编辑器
7.2 模型的创建
7.2.1 Simulink模块的基本操作
模块是建立Simulink模型的基本单元。利用Simulink进行系统建模就是用适当的方式把各种模块连接在一起。下面如表7-18和表7-19所示的这些表格汇总了Simulink里对模块、直线和信号标签进行各种操作的方法,其中有许多操作并不是惟一的,读者自己实践一下就可以摸索出其他的操作方法。
表7-18 对模块进行操作
表7-19 对直线进行操作
图7-29 对连线的操作
Simulink中大部分模块的参数(Parameters)都允许用户进行设置。用户只需双击要设置的模块或用鼠标右键单击模块并在弹出的上下文菜单中选择“<block name>Parameters”或先选中要设置的模块后再选择“Edit→<block name>Parameters”就会弹出“参数设置”对话框,如图7-30所示。是对模块功能的描述,每个模块的参数设置对话框都会有对自身功能描述的部分。图7-30中是一个增益模块,用户可以设置它的增益大小、采样时间和输出数据类型等参数。模块参数还可以通过set_param命令设置,这在后面的章节中再进行介绍。
图7-30 模块参数设置对话框
注意:“<block name>Parameters”中的<block name>是用户所选择的模块的名称。在图7-30的示例中,用户所选择的模块是Gain,所以上下文菜单中要选择的是“Gain Parameters”。
Simulink中的每个模块都有一个内容相同的属性(Properties)设置对话框,用鼠标右键单击模块并在弹出的上下文菜单中选择“Block Properties”或先选中要设置的模块后再选择“Edit→Block Properties”就会弹出属性设置对话框,如图7-31所示。“属性设置”对话框主要包括三项内容。
· “General”页
【说明(Description)】
用于对该模块在模型中的用法进行注释。
【优先级(Priority)】
规定该模块在模型中相对于其他模块执行的优先顺序。优先级的数值必须是整数,如果用户不输入数值,系统就会自动选取合适的优先级。优先级的数值越小(可以是负整数),优先级越高。一般都不需要设置它。
【标记(Tag)】
用户为模块添加的文本格式的标记。
图7-31 模块属性设置对话框
· “Block Annotation”页
用于指定在模块的图标下显示模块的哪个参数及其值,以什么格式显示。属性格式字符串由任意的文本字符串加嵌入式参数名组成。首先设置“General”页的Priority为4,然后在“Block Annotation”页的“Enter text and tokens for annotation”文本框中输入“Priority=%<priority>\n Gain=%<gain>”,最后单击“Apply”,注意观察模块图标的变化,如图7-32所示。
如果参数的值不是字符串或数字,相应位置会显示N/S (not supported) 。如果参数名无效,该位置将显示“???”。
· “Callbacks”页
用于定义当该模块发生某种特殊行为时所要执行的MATLAB表达式,也称回调函数。关于回调函数在后面的章节再进行介绍。
对信号进行标注以及在模型图表上建立描述模型功能的注释文字,是一个好的建模习惯。信号标签和注释如图7-33所示。表7-20和表7-21列出了对标注和注释的具体操作方法。给一个信号添加标签,只需用鼠标左键在直线上双击,然后输入文字即可。建立模型注释与之类似,只要在模型窗口的空白处双击鼠标左键,然后输入注释文字即可。
图7-32 设置“Block Annotation”
图7-33 注释和信号标注示例
表7-20 在连线上反映信息
表7-21 对注释进行处理
和模块类似,每一个模型和每一条连线(代表信号)都有“参数设置”对话框和“属性设置”对话框,如图7-34所示(用鼠标右键单击模型的空白处选择相应的菜单就可以弹出对话框),它们的作用将在后面的章节进行介绍。
图7-34 模型的仿真参数和“属性设置”对话框
7.2.2 创建模型的基本步骤
在本章的前面已向读者展示了一个简单的示例,通过该示例的学习,读者可能觉得使用Simulink建模实在是太简单了,只不过是用鼠标来选择几个模块,然后再把他们用几条线连接起来,最后按一下运行菜单观察结果曲线就可以了!但是当再次遇到实际问题时,读者可能会意识到所给的示例实在是一个太简单太过于理想化的模型,实际工程中要考虑的方面比这些要多得多,而且也要复杂得多,因此读者需要进一步学习和掌握Simulink中更为深层的内容。不过只要掌握了上一节的内容,读者就可以通过在线帮助来解决更为复杂的问题了。
在前面内容的基础上,下面向读者总结出使用Simulink进行系统建模和系统仿真的一般步骤:
· 画出系统草图。将所要仿真的系统根据功能划分成一个个小的子系统,然后用一个个小的模块来搭建每个子系统。这一步骤也体现了用Simulink进行系统建模的层次性特点。当然所选用的模块最好是Simulink的库里现有的模块,这样用户不必进行烦琐的代码编写,当然这要求用户必须熟悉这些库的内容;
· 启动Simulink模块库浏览器,新建一个空白模型;
· 在库中找到所需模块并拖到空白模型窗口中,按系统草图的布局摆放好各模块并连接各模块;
· 如果系统较复杂、模块太多,可以将实现同一功能的模块封装成一个子系统,使系统的模型看起来更简洁(封装的方法在第7.3节介绍);
· 设置各模块的参数以及与仿真有关的各种参数(在后面的相关小节有详细介绍);
· 保存模型,模型文件的后缀名为.mdl。
· 运行仿真,观察结果。如果仿真出错,请按弹出的错误提示框来查看出错的原因,然后进行修改;如果仿真结果与预想的结果不符,首先是要检查模块的连接是否有误、选择的模块是否合适,然后检查模块参数和仿真参数的设置是否合理。
· 调试模型。如果在上一步中没有检查出任何错误,那么就有必要进行调试(调试的方法在第7.9节中介绍),以查看系统在每一个仿真步的运行情况,直至找到出现仿真结果与预想的或实际情况不符的地方,修改后再进行仿真,直至结果符合要求。当然最后还要保存模型。
7.2.3 模型文件格式
前面的示例模型都是通过图形界面来建立的,Simulink还为用户提供了通过命令行建立模型和设置模型参数的方法。一般情况下,用户不需要使用这种方式来建模,因为它要求用户熟悉大量的命令,而且很不直观。这一节只对Simulink的模型文件格式作一个粗略的介绍,用户若在实际建模时遇到相关的问题可以查阅在线帮助。
Simulink将每一个模型(包括库)都保存在一个以.mdl为后缀的文件里,称为模型文件。一个模型文件就是一个结构化的ASCII文件,它包括关键字和各种参数的值。下面以一个示例来介绍如何查看模型文件和模型文件的结构。
· 建立如图7-35所示的模型,并保存为modelfile.mdl;
· 在MATLAB 7.0窗口中通过“File→New→M-File”菜单打开MATLAB Edit;
· 在MATLAB Edit窗口中通过“File→Open”菜单打开刚刚保存的modelfile.mdl文件,如图7-35所示。如果在目录中没有看到该文件,请查看文件打开对话框的文件类型是否为所有文件。
由示例中的模型文件可以看出,模型文件按照模块继承的层次关系描述模型的各个组件。文件的结构如下:
图7-35 模型文件示例
文件分成下面几个部分来描述模型。
· Model部分:用来描述模型参数,包括模型名称、模型版本和仿真参数等;
· BlockDefaults部分:用来描述模块参数的默认设置;
· AnnotationDefaults部分:用来描述模型的注释参数的默认值,这些参数值不能用set_param命令来修改;
· System部分:用来描述模型中每一个系统(包括顶层的系统和各级子系统)的参数。每一个System部分都包括模块、连线和注释等。
7.3 子系统及其封装
7.3.1 创建子系统
1.为何创建子系统
当模型变得越来越大、越来越复杂时,用户很难轻易读懂以前所建的模型。在这种情况下,通过子系统可以把大的模型分割成几个小的模型系统以使整个模型更简洁、可读性更高,而且这种操作也不复杂。建立子系统有以下优点:
· 减少模型窗口中模块的个数,使得模型窗口更加整洁;
· 把一些功能相关的模块集成在一起,还可以实现复用;
· 通过子系统可以实现模型图表的层次化,这样用户既可以采用自上而下的设计方法,也可以采用自下而上的设计方法。
2.如何创建子系统
在Simulink中有两种创建子系统的方法。
· 通过子系统模块来创建子系统:先向模型中添加Subsystem模块,然后打开该模块并向其中添加模块。
· 组合已存在的模块创建子系统:具体建立步骤见下一节的示例。
3.创建子系统示例
下面通过两个示例来介绍上文中提到的两种建立子系统的方法。
【示例1】通过Subsystem模块来创建子系统
具体步骤如下:
· 从Ports&Subsystems中复制Subsystem模块到自己的模型中,如图7-36所示;
· 用鼠标左键双击Subsystem模块图标打开如图7-36所示Subsystem模块编辑窗口;
· 在新的空白窗口创建子系统,然后保存;
· 运行仿真并保存。
图7-36 通过Subsystem模块创建子系统
【示例2】组合已存在的模块创建子系统
具体步骤如下:
· 创建如图7-37所示的系统;
· 选中要创建成子系统的模块,如图7-37所示;
· 选择【Edit->Create Subsystem】菜单,结果如图7-38所示;
· 运行仿真并保存。
图7-37 组合已存在的模块创建子系统
图7-38 创建子系统示例
7.3.2 封装子系统
子系统可以使模型更简洁,但是在设置模型中各模块的参数时仍然很繁琐,此时可以使用封装技术。封装可以使用户创建的子系统表现得与Simulink提供的模块一样拥有自己的图标,并且用鼠标左键双击模块图标时会出现一个用户自定义的“参数设置”对话框,实现在一个对话框中设置子系统中所有模块的参数。
1.为何封装
封装子系统可以为用户带来很多好处。
· 在设置子系统中各个模块的参数时只通过一个参数对话框就可以完成所需设置;
· 为子系统创建一个可以反映子系统功能的图标;
· 可以避免用户在无意中修改子系统中模块的参数。
2.如何封装
用户可以按照如下的步骤来封装一个子系统。
· 选择需要封装的子系统;
· 选择“Edit→Edit mask”菜单,这时会弹出如图7-39所示的封装编辑器,通过它进行各种设置。编辑器中各项参数的含义在下一节的示例中进行介绍;
· 单击“Apply”或“OK”按钮保存设置。
图7-39 封装编辑器
3.封装示例
封装的操作很简单,也比较容易理解,下面通过一个简单的示例来介绍如何进行封装。
· 建立如图7-40所示的含有一子系统的模型,并设置子系统中Gain模块的Gain参数为一变量m;
· 选中模型中的Subsystem子系统,选择“Edit→Edit mask”菜单(或用鼠标右键单击子系统弹出上下文菜单,选择“Edit mask”菜单)打开封装编辑器,如图7-41所示;
· 进行封装设置。按照如图7-41所示设置【Icon页】;
【Icon页】允许用户定义封装子系统的图标,其中各项设置的含义如下:
【Icon options面板】:定义图标的边框是否可见(Frame),系统在图标中自动生成的端口标签等是否可见(Transparency.)等,用户只要试一试就会很快理解掌握。
【Drawing commands文本框】:用MATLAB命令来定义如何绘制模型的图标,这里的绘图命令可以调用【Initialization页】中定义的变量。
【Examples of drawing commands面板】:向用户解释如何使用各种绘制图标的命令,每种命令都对应在右下角有一个示例。用户可以方便地按照“command”选项框中的命令格式和右下角给出的相应示例图标来书写自己的图标绘制命令。
图7-40 封装子系统示例
图7-41 设置图标
· 按照如图7-42所示设置“Parameters”页
“Parameters”页允许用户定义封装子系统的参数对话框的可设置参数,其中各项设置的含义如图7-43所示。
图7-42 设置参数
图7-43 参数设置的含义
· 按照如图7-44所示设置“Initialization”页
“Initialization”页允许用户定义封装子系统的初始化命令。初始化命令可以使用任何有效的MATLAB表达式、函数、运算符和在“Parameters”页定义的变量,但是初始化命令不能访问MATLAB 7.0工作空间的变量。在每一条命令后用分号结束可以避免模型运行时在MATLAB 7.0命令窗口显示运行结果。一般在此定义附加变量、初始化变量或绘制图标等。
图7-44 设置初始化参数
· 按照如图7-45所示设置“Documentation”页
“Documentation”页允许用户定义封装子系统的封装类型、模块描述和模块帮助信息,其中各项设置的含义如图7-46所示。
图7-45 设置“Documentation”页参数
图7-46 “Documentation”设置的含义
单击“Apply”或“OK”按钮。用鼠标左键双击模型中的Subsystem子系统,弹出如图7-47所示封装子系统参数设置对话框。封装子系统的模块对话框中的变量不可在MATLAB工作空间赋值,这与非封装子系统不同。封装子系统有一个独立于MATLAB工作空间的内部存储空间。
图7-47 封装后的子系统的参数对话框
· 运行仿真,用鼠标左键双击模型中的Scope模块,看到如图7-48所示的结果。读者也可以试着改变图7-47中Gain参数的值,然后观察输出是否有所改变,并考虑其原因。
图7-48 示例模型仿真结果
注意:如果在保存上面示例的模型时弹出error提示框,有可能是用户的MATLAB 7.0或simulink在封装技术上不支持中文,这时需要将“Documentation”页中的中文说明改成英文。
7.3.3 定义自己的模块库
1.为何创建自己的模块库
当用户创建了很多封装子系统模块时,用户有必要分门别类地来存储这些模块。另外在进行仿真建模时,为了减少到各种子库中来回查寻所需模块,用户有必要将同一类功能的一组常用模块统一放置在同一模块库中。
2.如何创建自己的模块库
通过选择Simulink用户界面的“File→New→Library”菜单命令来创建模块库。选中该命令后弹出一个空白的库窗口,然后将需要存放在同一模块库中的模块复制到模块库窗口中即可,如图7-49所示。创建好模型后,用户在创建模型时可以不需要打开Simulink模块库浏览器,而只需要在MATLAB 7.0命令窗口输入存放相应模块的模块库的文件名即可。
图7-49 自建模型库
7.4 过零检测
当仿真一个动态系统时,Simulink在每一个时间步使用过零检测技术来检测系统状态变量的间断点。如果Simulink在当前的时间步内检测到了不连续的点,那么它将找到发生不连续的精确时间点,并且会在该时间点的前后增加附加的时间步。本节将向读者介绍过零检测的重要性以及它的工作原理。
1.过零检测的重要性
在动态系统的运行过程中,状态的不连续经常会发生重要的事件,如当一个小球与地面发生碰撞时,它的位置就会产生急剧的变化。不连续常常会导致动态系统的显著变化,因此对不连续点进行精确的仿真非常重要,否则会导致仿真得到错误的系统行为。例如仿真碰撞中的小球,如果小球与地面碰撞的时间点发生在仿真时间步内,模型中的小球会在半空中改变方向,这会使研究者得到与物理学上的规律相违背的结论。
为了避免得到错误的结论,使不连续点发生的时刻成为仿真的一个时间点很重要。对于一个纯粹靠求解器来决定仿真时间的仿真器很难有效地做到上面的要求。
固定步长的求解器在整数倍时间步长的时间点上计算状态变量的值,然而这并不能保证有仿真时间点发生在状态不连续的时间点。当然用户可以通过减小时间步长使状态不连续的时间点成为一个仿真时间点,但是这会减慢仿真速度。
可变步长的求解器可以保证有仿真时间点发生在状态不连续的时间点。它可以动态地改变步长,当状态变量变化慢时增加步长,变化快时减小步长。在不连续点附近,系统状态发生剧烈变化,因此理论上这种求解器可以精确地找到不连续发生的时间点,但是这会增加仿真的时间点从而使仿真速度变慢。
2.过零检测的工作原理
使用过零检测技术,一个模块能够通过Simulink注册一系列过零变量,每一个变量就是一个状态变量(含有不连续点)的函数。当相应的不连续发生时,过零函数从正值或负值传递零值。在每一个仿真步结束时,Simulink通过调用每一个注册了过零变量的模块来更新变量。然后Simulink检测是否有变量的符号发生改变(相对于上一仿真时间点的结果),如果有改变就说明当前时间步有不连续发生。
如果检测到过零点,Simulink就会在每一个发生符号改变的变量的前一时刻值和当前值之间内插入新值以评估过零点的个数,然后逐步增加内插点数目并使其值依次越过每一个过零点。通过该技术,Simulink避免精确地在不连续发生点进行仿真(不连续点处的状态变量的值可能没有定义)。
过零检测使得Simulink可以精确地仿真不连续点而不必通过减小仿真步长增加仿真点来实现,因此仿真速度不会受太大影响。大多数Simulink模块都支持过零检测,表7-22列出了Simulink中支持过零检测的模块。如果用户需要显式定义过零事件,可以使用Discontinuities子库中的Hit Crossing模块来实现。
表7-22 持过零点检测的模块
如果仿真的误差容忍度设置得太大,那么Simulink有可能检测不到过零点。例如,如果在一个时间步内存在过零点,但是在时间步的开始和最终时刻没有检测到符号的改变(如图7-50所示),那么求解器将检测不到过零点。
图7-50 过零点检测
7.5 代数环
1.何为代数环及代数环如何产生
有些Simulink模块的输入端口是支持直接馈入的,这意味着这些模块的输出信号值在不知道输入端口的信号值之前就不能被计算出来。当一个支持直接馈入的输入端口由同一模块的输出直接或间接地通过由其他模块组成的反馈回路的输出驱动时,就会产生一个代数环,如图7-51所示。
图7-51 代数环
从代数的角度来看,图7-51中的模块的解是z=2,但是大多数的代数环是无法直接看出解的。Algebraic Constraint模块为代数方程等式建模及定义其初始猜想值提供了方便,它约束输入信号F(z)等于零并输出代数状态Z,其输出必须能够通过反馈回路影响输入。用户可以为代数环状态提供一个初始猜想值以提高求解代数环的效率。
一个标量代数环代表一个标量等式或是一个形如F(z)=0的约束条件,其中z是环中一个模块的输出,函数F由环路中的另一个反馈回路组成。可将图7-51所示的含有反馈环的模型改写成用Algebraic Constraint模块创建的模型,其仿真结果不变,如图7-52所示。
图7-52 Algebraic Constraint模块创建代数环模块
创建向量代数环也很容易,在如图7-53所示的向量代数环可用下面的代数方程描述:
图7-53 向量代数环
当一个模型包含一个Algebraic Constraint模块时就会产生一个代数环,这种约束可能是系统的物理连接的结果,或是用户试图为一个微分/代数系统(DAE)建模的结果。
2.如何求解代数环及如何消除代数环
为了求解F(z)=0,Simulink环路求解器会采用弱线性搜索的秩为1的牛顿方法更新偏微分Jacobian矩阵。尽管这种方法很有效,但是如果代数状态Z没有一个好的初始估计值,解法器有可能不收敛。此时用户可以为代数环中的某个连线(对应一个信号)定义一个初始值,设置的办法有两个:可以通过Algebraic Constraint模块的参数设置;还可以通过在连线上放置IC模块(初始信号设置模块)。
当一个系统包含有代数环时,Simulink会在每一个时间步进行循环求解。如果有可能,环路求解器会采用迭代的办法来求解,因此仿真速度会比较慢。
当一个模型中含有Atomic Subsystem、Enabled Subsystem或Model模块时,Simulink可以通过模块的参数设置来消除其中一些代数环。对于含Atomic Subsystem和Enabled Subsystem模块的模型,可在模块参数设置对话框中选择“Minimize algebraic loop occurrences”项;对于含Model模块的模型,可在“configuration parameters对话框”的“Model Referencing面板”中选择“inimize algebraic loop occurrences”项。
7.6 回调函数
在前面介绍“模块属性设置”对话框时提到过回调函数(如图7-32所示的“设置模块属性”对话框)。所谓回调函数,是指当用户定义的模型或模块的图标发生某种特殊行为时所要执行的MATLAB表达式(M文件和M文件函数)。
为模型或模块设置回调函数的方法有下面两种:
· 通过模型或模块的属性对话框来设置;
· 通过MATLAB相关的命令来设置。
在如图7-54所示的“模块属性设置”对话框中的Callbacks页列出了可以为模块设置回调函数的参数(每一个参数对应模块的一种行为),表7-23列出了这些参数的含义。可以为模型设置回调函数的参数与可设置的模块参数类似,如表7-24所示。图7-55是“模型属性设置”对话框。
图7-54 为模块设置函数的参数
图7-55 模型属性对话框
表7-23 模块的回调参数
表7-24 模型的回调参数
下面通过一个示例介绍为模型或模块设置回调函数的两种方法的具体实现过程。
【第一种方法】
· 首先建立一个如图7-56所示的模型example;
· 设置模型属性对话框“CallBack”页的Simulation stop function文本为plot(tout,yout);
· 运行仿真,结束时会自动弹出图形窗口。
同样也可以通过设置Outl模块的Callback属性来达到这一目的,如图7-57所示。
图7-56 通过模型属性对话框为模型设置回调函数
图7-57 通过模块属性对话框为模型设置回调函数
【第二种方法】
· 首先建立好如图7-56所示的模型;
· 设置Constant模块参数为变量con,Sine Wave的幅度和频率参数设置为3位向量;
· 在MATLAB 7.0命令窗口输入下面的代码:
· 保存模型之后,新建一个名为ini con的M文件,其内容为con=3;
· 再新建一个名为out_plot的M文件,其内容为plot(tout,yout);
· 运行仿真,结果如图7-58所示。
注意:如果读者在运行示例时出错,请检查你的当前目录是不是你保存模型的目录。如果不是,请将当前目录改成保存模型的目录,再运行上面两条set_param命令,最后运行仿真。
图7-58 通过MATLAB命令为模型设置回调函数
7.7 运行仿真
建好一个模型之后就要运行模型和分析仿真结果,前面也简单地提到过运行仿真,本节将对启动仿真的方法及各种仿真参数的设置进行详尽地讲解。
7.7.1 使用窗口运行仿真
当建立好模型后,可以直接在模型窗口通过菜单或工具栏进行仿真,如图7-59所示。可以通过这些菜单设置仿真的参数、仿真的时间以及选择解法器等,而不需要去记忆MATLAB的各种命令语法。前面第7.1.2节已对模型窗口的菜单和工具栏作了详尽介绍,读者加以实践即可掌握。
图7-59 通过菜单命令或工具栏按钮运行仿真
7.7.2 仿真参数的设置
1.设置仿真参数和选择解法器
可以通过模型窗口的“Simulation→Configuration Parameters”命令打开设置仿真参数的对话框,也可以通过上下文菜单的“Configuration Parameters”项(单击模型窗口中的空白处也可以打开)打开,如图7-60所示。
图7-60 仿真参数对话框
对话框将参数分成不同类型的6组,下面对每一组中各个参数的作用和设置方法进行简单的介绍。
(1)【Solver面板】
该面板主要用于设置仿真开始和结束时间,选择解法器,并设置它的相关参数,如图7-61所示。
图7-61 Solver面板
Simulink支持两类解法器:固定步长和可变步长解法器。两种解法器计算下一个仿真时间的方法都是在当前仿真时间上加一个时间步长。不同的是,固定步长解法器的时间步长是常数,而可变步长解法器的时间步长是根据模型动态特性可变的。当模型的状态变化特别快时,为了保证精度要降低时间步长,反之就增加时间步长。面板中Type用于设置解法器的类型,当选择了不同的类型时,Solver中可选的解法器列表也不同,有关各种求解器的使用范围请读者查阅帮助。
当用户希望通过自建模型生成代码并在实时计算系统中运行这些代码时,用户就应该选择固定步长解法器来仿真模型。这是因为实时计算系统以固定的采样速率运行,若采用可变步长将有可能使仿真发生错误。
当用户并不从模型生成代码时,解法器类型的选择决定于模型的动态特性。当模型的状态变化特别快或是包含有不连续状态时,选择可变步长解法器可以缩短仿真时间。这是因为可变步长相对于固定步长的解法器需要更少的时间步,而两者仿真的精度相当。
关于该面板中其他参数的设置,读者可以查看在线帮助,它们都比较容易理解。
(2)【Data Import/Export面板】
该面板主要用于向MATLAB 7.0工作空间输出模型仿真结果数据,或从MATLAB 7.0工作空间读入数据到模型,如图7-62所示。
【Load from workspace】:从MATLAB 7.0工作空间向模型导入数据,作为输入和系统的初始状态。
【Save to workspace】:向MATLAB 7.0工作空间输出仿真时间、系统状态、系统输出和系统最终状态。
【Save options】:向MATLAB 7.0工作空间输出数据的数据格式、数据量、存储数据的变量名以及生成附加输出信号数据等。
图7-62 Data Import/Export面板
(3)【Optimization面板】
该面板用于设置各种选项来提高仿真性能和由模型生成的代码的性能,如图7-63所示。
图7-63 Optimization面板
“Block reduction optimization”选项:设置用时钟同步模块来代替一组模块,以加速模型的运行。
“Conditional input branch execution”选项:用于优化模型的仿真和代码的生成。
“Inline parameters”选项:选中该选项使得模型的所有参数在仿真过程中不可调,Simulink在仿真时就会将那些输出仅决定于模块参数的模块从仿真环中移出,以加快仿真。如果用户要想使某些变量参数可调,那么可以单击“configure”按钮打开“Model Parameter Configuration”对话框将这些变量设置为全局变量。
“Implement logic signals as boolean data (vs.double)”选项:使得接受布尔值输入的模块只能接受布尔类型,若该项没被选,则接受布尔输入的模型也能接受double类型输入。
(4)【Diagnostics面板】
该面板主要用于设置当模块在编译和仿真遇到突发情况时,Simulink将采用哪种诊断动作,如图7-64所示。该面板还将各种突发情况的出现原因分类列出,各类突发情况的诊断办法的设置在此不作详细介绍。
图7-64 Diagnostics面板
(5)【Hardware Implementation面板】
该面板(如图7-65所示)主要用于定义硬件的特性(包括硬件支持的字长等),这里的硬件是指将来要用来运行模型的物理硬件。这些设置可以帮助用户在模型实际运行目标系统(硬件)之前通过仿真检测到以后在目标系统上运行可能会出现的问题,如溢出问题等。
图7-65 Hardware Implementation面板
(6)【Model Referencing面板】
该面板主要用于生成目标代码、建立仿真以及定义当此模型中包含其他模型或其他模型引用该模型时的一些选项参数值,如图7-66所示。
图7-66 Model Referencing面板
①当前模型中含有其他模型时(Rebuild options for all referenced models其他)的设置。
【Rebuild options】:用于设置是否要在当前模型更新、运行仿真和生成代码之前重建仿真和Real-Time Workshop目标。因为在进行模型更新、运行仿真和生成代码时,有可能其中所包含的其他模型发生了改变,所以需要在这里进行设置。
②其他模型中包含有当前模型时(Options for referencing this model其他)的设置。
【Total number of instances allowed per top model】:用于设置在其他模型中可以引用多少个该模型。
【Model dependencies】:用于定义存放初始化模型参数的命令以及为模型提供数据的文件名(通常是MAT文件或M文件)或文件的路径,定义的方法是将文件名或文件路径的字符串定义成字符串细胞阵列,如{'D:\Work\parameters.mat', '$MDL\mdlvars.mat', …'D:\Work\masks*.m'}。
【Pass scalar root inputs by value】:选中此项后,别的模型在调用该模型时就会通过数值来传递该模型的标量输入,否则就通过参考(如输入的地址)来传递输入。选中此项就会允许模型从速度快的寄存器或局部存储单元读取数据,而不是从它的实际输入位置来读取。如果模型的输入在一个时间步内发生改变,那么选中此项就会导致仿真出错。例如,当模型的输入/输出共享同一个局部存储单元(代数环)并且在一个时间步被调用多次时,模型只有当输入是通过参考传递时才会看到标量输入在同一时间步内发生的改变。
【Minimize algebraic loop occurrences】:选中此项后,Simulink就试图消除模型中的一些代数环。
注意:所有通过仿真参数对话框设置的参数均可以通过sim和simset命令来设置。
2.仿真诊断对话框
如果Simulink在仿真运行过程中遇到错误,那么Simulink将停止仿真,并弹出仿真诊断对话框。通过该对话框,用户可以方便地在模型中找到出错的地方和出错的原因。将第7.6节中图7-58示例的M文件ini_con中的内容改为con=[2 3]后再运行仿真,将弹出如图7-67所示的错误提示对话框。下面就介绍一下该对话框各部分提示的含义。
图7-67 仿真诊断对话框
对话框分为上下两个面板,上面的面板列出了每一个错误的信息,这些信息包括:
· Message:消息类型(模块错误、警告、log等);
· Source:导致错误的模型元素(如模块或连线等)的名称;
· Reported by:报告错误的组件(如simulink、Real-Time Workshop等);
· Summary:错误消息的简写,便于在列表中显示。
下面的面板显示当前所选中的Message的完整内容,包括出错原因和出错的元素。当用户选中某一个Message时,Simulink就会打开模型窗口,并且将产生错误的模型元素用黄色加亮显示。
7.7.3 使用MATLAB命令运行仿真
使用模型窗口直接进行系统仿真时,每一次运行都是针对某一固定的模块参数设置,在运行过程中不能轻易地改变它。MATLAB允许从命令行运行仿真,通过MATLAB命令进行模型的仿真使得用户可以从M文件来运行仿真。这样就允许不断地改变模块参数并运行仿真,也就让用户可以随机地改变参数和循环地运行仿真,用户就可以进行蒙特卡罗分析了。
MATLAB 7.0提供了sim命令运行仿真,该命令完整的语法如下:
或者输入下面的代码:
其中只有model参数是必需的,其他的参量都被允许设置为空矩阵([])。Sim命令中没有设置的或是设为空矩阵的参数的值等于建立模型时通过模块参数对话框设置的值或是系统默认的值;sim命令中设置的参数值会覆盖模型建立时设置的参数值。如果你仿真的模型是连续系统,那么命令中还必须通过simset命令设定solver参数,默认的solver参数是求解离散模型的VariableStepDiscrete。sim中各参量的含义如表7-25所示。
表7-25 sim命令参量
Simset命令用于创建一个options结构,该结构中设定仿真参数和求解器的属性值。该命令的语法如下:
由于一般情况下,用户不会用到该命令,在此不作详细介绍,如果碰到可以查阅在线帮助,相关的命令还有simplot、simget、set_param等。用sim命令仿真第7.6节的示例,代码如下:
· 先在MATLAB 7.0命令窗口执行:
· 然后执行:
使用sim命令运行仿真的结果如图7-68所示。
图7-68 使用sim命令运行仿真
另外还可以通过set_param命令来开始、结束、暂停或者继续仿真,该命令的使用格式如下:
其中,'sys'是要仿真的系统的名称;'cmd'是控制命令,可以取值start、stop、pause、continue或update。类似的命令有get_param,它可用来检查仿真的状态,其使用格式是:
该命令的返回值是stopped、initializing、running、paused、updating、terminating或者external。
7.7.4 改善仿真性能及精度
Simulink的仿真性能和精度受许多因素的影响,包括模型的设计和仿真参数的设置。对于大多数的问题,使用默认的仿真参数和解法器就可以得到满意的仿真结果。但是对于某些模型,适当的调整仿真参数可以得到更好的结果。
1.加速仿真
如果一个模型的仿真速度过慢,可能造成的原因有以下几种。
· 模型中有MATLAB Fcn模块。如果一个模型中含有MATLAB Fcn模块,那么在仿真时,Simulink在每一个仿真时间步都要调用一次MATLAB解释器,所以应该尽可能的使用Simulink的内置Fcn模块或是Math Function模块。
· 模型中有M文件的S-函数。M文件的S-函数也会使每一个仿真步调用MATLAB解释器。这时应该将它转换成一个子系统或是C-MEX文件的S-函数。
· 模型中含存储模块。使用存储模块将使阶数可变的解法器在每个时间步被重置为1阶。
· 仿真的时间步长的值太小。可将它设为默认值。
· 仿真精度设置要求太高。一般情况下,使用默认的0.1%相对误差就可以。如果该值设得太小,那么这会使仿真在接近零状态附近时耗费更多的仿真步。
· 仿真时间设得太长。可适当减小时间间隔。
· 模型所求解的问题是一个stiff问题,而用户选择的是一个非stiff求解器。可以试用ode15s。
· 模型包含有代数环。代数环是通过迭代的方法进行求解的,故仿真速度会比较慢。
· 模型中把一个Random Number模块作为Integrator模块的输入。若用户建立的是一个连续系统,可以使用Sources库中的Band-Limited White Noise模块作为Integrator模块的输入。
· 模型的采样时间彼此之间不是整数倍,求解器会选择足够小的时间步长来确保所有设置的采样点都能取到,因此会导致仿真速度下降。
2.改善仿真的精度
用户可以通过对比在不同的相对误差或绝对误差参数值时的仿真结果来判断解是否收敛。如果仿真的结果变化不大,则说明收敛。用户可以通过设置较小的仿真步长来保证仿真不会错过模型的关键行为。
如果仿真结果看起来不是很精确,那么有可能是下面的原因造成的。
· 模型含有取值接近零的状态。此时,如果绝对误差参数的值设置过大,那么仿真在接近零状态时仿真的时间步就太少。用户可以通过设置较小的绝对误差参数来解决这个问题。
· 如果减小绝对误差的办法还不能提高仿真精度,那么用户就应该减小相对误差参数的值以降低可容忍的误差和减小仿真的步长。
7.8 仿真结果分析
在第7.1.4节中讲过,仿真结果的可视化是Simulink建模的一个特点。不仅如此,Simulink还可以对仿真的结果进行分析。
7.8.1 观看输出结果
在Simulink中有3种方法绘制模型仿真的输出:
· 在模型中将信号输入到Scope模块或是XY Graph模型;
· 将输出写入变量,然后使用MATLAB绘图命令;
· 将输出写入To Workspace模块,然后使用MATLAB绘图命令。
7.8.2 线性化
1.何为线性化
线性化就是将用户所建模型用状态空间矩阵形式A、B、C和D表示的线性方程模型。状态空间矩阵按如下方程描述线性的输入/输出关系:
其中,x,u,y分别表示状态、输入和输出的向量。模型中的输入/输出必须使用Simulink提供的输入(In1)输出(Out1)模块。关于何为状态向量以及如何将一个系统用状态空间矩阵来描述等内容,请读者参考与信号与系统相关的书籍。
2.为何线性化
一旦数据具有状态空间的形式或是被转化成LTI对象,用户就可以使用控制系统工具箱里的函数作进一步的分析。
将状态空间转换为LTI对象:
绘制系统的波特相位幅频图:
求系统的时间响应:
3.如何线性化
用户可以通过下面几个函数对所建模型进行线性化:
linmod用于线性化本身是线性和非线性的模型,dlinmod用于线性化本身是离散系统或者离散和连续的混合系统。以上函数的具体使用方法及其中各个参数的含义,用户可以查询在线帮助。
7.8.3 平衡点的分析
Simulink通过trim命令来决定动态系统的稳定状态点,所谓稳定状态点就是满足用户自定义的输入、输出和状态条件的点。下面通过一个简单的示例来介绍如何使用trim命令求解平衡点。
· 建立如图7-69所示的模型,保存为“exampbalance”;
· 为系统状态和输入定义一个初步的猜测值,并把用户预期的输出值赋给y,代码设置如下:
· 使用索引变量规定模型的输入、输出和状态中哪些可变,哪些不可变,代码设置如下:
· 使用trim命令来求出平衡点,代码设置如下:
· 得到如下结果:
图7-69 求解系统平衡点
注意:并不是所有求解平衡点的问题都有解。如果无解,trim将返回一个离期望状态的偏差最小的一个解。trim命令还有其他的调用格式,请读者查阅在线帮助。
7.9 模型的调试
与许多高级编程语言一样,Simulink 6.0也提供了一个调试器供用户查找和诊断模型中的错误,它允许用户通过单步运行(逐个方法地运行)仿真和显示模块的即时状态、输入和输出来查明错误。在Simulink 6.0中,用户既可以通过图形化的调试界面进行调试,也可以通过命令行进行调试。
7.9.1 Simulink调试器
本小节通过一个示例简单地向读者介绍如何使用调试器。该示例是采取单步运行仿真的方式,用户可以通过这种运行方式来查看在每一个仿真步中各个模块的运行情况,从而可以检查模块功能是否与用户的设想一致。
· 打开第7.3.2节中如图7-41所示的示例。
· 选择Tools→Simulink Debugger菜单打开如图7-70所示的调试器,表7-26对该对话框工具栏各按钮的功能进行了详细介绍。
表7-26 调试器工具栏
调试器窗口界面中的各项设置的含义如下:
“points”页:用于设置断点,即仿真运行到某个模块方法或满足某个条件就停止;
“Simulation Loop”页:包含Method、Breakpoints和ID三列内容。用于显示当前仿真步正在运行的相关信息;
“Outputs”页:用于显示调试结果,包括调试命令提示、当前运行模块的输入、输出和模块的状态。如果是采用命令行调试,这些结果在MATLAB 7.0命令窗口中也会显示。调试命令提示显示当前仿真时间、仿真名和方法的索引号;
“Sorted List”页:用于显示被调试的模块列表,该列表按模块执行的顺序排列;
“Status”页:用于显示调试器各种选项设置的值以及其他状态信息。
· 单击按钮开始调试,在“Simulation Loop”页将显示当前运行的方法的名字,并且该方法也将显示在模块窗口中,如图7-71所示。当调试开始后,MATLAB的命令窗口也会进入调试状态,如图7-72所示。用户可以在命令窗口采取命令行方式进行调试。
· 单击按钮进行仿真,如图7-73所示。在仿真过程中还可以设置断点(非条件中断或条件中断);既可以按模块单步执行,也可以按时间步单步执行,还可以显示模型的信息等设置,用户可以查阅在线帮助,在此不做详细地介绍。
图7-70 调试器窗口
图7-71 开始仿真
图7-72 调试状态下的命令窗口
图7-73 单步仿真
7.9.2 命令行调试
在命令行调试模式下,用户可以在MATLAB 7.0命令窗口中通过相应的命令来控制调试器。由于命令行调试方式需要用户记住许多的命令函数,所以一般用户可以直接通过调试用户界面的相关菜单和工具栏来操作,这里只向读者简单地介绍对于理解命令行调试很关键的几个基本概念,在后面地章节将陆续介绍一些常用的调试命令。
调试器接受缩写的调试命令,关于这些命令请读者查阅帮助文件。用户还可以通过在MATLAB 7.0命令行键入Enter键来重复执行前一命令。许多Simulink命令和消息是通过Method ID和Block ID来引用方法和模块的,Method ID是按方法被调用的顺序从0开始分配的一个整数;Block ID是在仿真的编译阶段分配的,形式为sid:bid,sid是一个用来表示系统的一个整数,bid是模块在系统中的位置。用户可以通过slist命令来查看当前运行模型的每一个模块的ID。
用户可以通过下面两个命令来启动调试器:
其中的vdp是模型名。
7.9.3 设置断点
所谓断点就是指仿真运行到此处会停止仿真的地方,当仿真遇到断点停止时,用户可以使用continue命令跳过当前断点继续运行到下一个断点。调试器允许用户定义两种断点,即无条件断点和有条件断点,所谓无条件断点是指运行到此处就停止,而条件断点是指当仿真过程中满足用户定义的条件时才停止仿真。
如果用户知道自己的程序中某一点或当某一条件满足时就会出错,那么设置断点将很有用。下面向读者介绍两种设置断点的方法。
1.设置无条件断点
有3种方式设置。
· 通过调试器的工具栏
先在模型窗口中选择要设置断点的模块,然后用鼠标左键单击按钮。在如图7-74所示的示例模型中的Scope模块处设置断点,可用“Remove selected point”按钮删除已设置好的断点。
· 通过调试器的Simulation Loop页
选择该页的Breakpoints列中要设置的断点处选择前面的选择框即可。
· 通过在MATLAB 7.0命令窗口运行相关命令
使用break和bafter命令可以分别在一个方法的前面和后面设置断点,使用clear命令清除断点。
break命令的语法,代码如下:
bafter和clear的语法与之类似,在此不作详细介绍,请读者查阅帮助。
图7-74 通过工具栏设置断点
2.设置有条件断点
设置有条件断点可以通过在调试器“Break on conditions”页中设置相应的断点条件来实现,也可以通过以下命令来设置:
7.9.4 显示仿真的有关信息
Simulink调试器提供了许多命令允许用户在模型运行时显示模块的状态、模块的输入/输出和其他的信息。在这里主要介绍如何使用调试器工具条中的按钮来执行相应的信息显示,当然这些按钮也有相应的命令,在此不详细介绍。
按钮用于显示模块的输入/输出信息。首先在模型窗口选中模块,然后用鼠标左键单击该按钮,被选中的模块在当前仿真步的输入、输出和状态信息将显示在调试器窗口的“Outputs”页中,相应的命令有probe和disp。在如图7-75所示的示例模型中进行单步调试(方法按第7.9.1节介绍的方法进行)到下面的时间步
然后就可以看到图中的信息,如图7-75所示。使用相应的probe命令来显示模块信息,probe命令的语法如下:
disp命令可实现相同的功能,其使用语法与probe类似。
图7-75 通过按钮显示模块信息
按钮也是用于显示模块的信息,与
按钮不同的是,如果用户为某一模块设置了断点,那么用户就可以在“Break points”页的Break/Display points面板中选中
列的相应模块的选框,一旦为某一模块设置了该选框,那么仿真在每一次运行到该模块处时就会显示它的相关信息。对应的可以分别使用trace和untrace命令来完成同样的功能设置和撤销设置。atrace命令用于显示代数环的信息,其语法及含义如表7-27所示。
states命令用于在MATLAB 7.0命令窗口中显示系统的当前信息,如对图7-75中的示例运行该命令即可得到:
图7-76 通过probe命令显示模块信息
ishow命令用于锁定积分信息的显示。当它被使能时,那么仿真时间步每前进一次或遇到需要改变仿真步长的状态时,调试器都将显示一个相应的消息。
表7-27 trace命令
7.9.5 显示模型的信息
调试器除了可显示关于仿真的信息外,还可显示有关模型的信息。
slist命令用于显示系统中各模块的索引,模块的索引其实也是按它们执行的顺序来排列的,对图7-75中的示例运行slist命令将看到如下信息:
这与调试器窗口中“Sorted List”页显示的内容一样。
其他用于显示模块信息的命令还有bshow、systems、zclist、ashow、status等,它们的使用方法与前面的命令也非常类似,具体的操作细节和所实现的功能请读者查阅帮助。
7.10 S-函数
S-函数(System-函数)为扩展Simulink的功能提供一个强有力的机制,本小节将向读者解释以下几个问题:
· S-函数是什么?
· 用户为什么要使用S-函数?
· 用户怎样书写自己的S-函数?
7.10.1 什么是S-函数
S-函数是一种描述动态系统的计算机语言,用户可以用MATLAB、C、C++、Ada或Fortran语言书写。C、C++、Ada和Fortran书写的S-函数用mex命令编译成MEX文件,它们就像MATLAB中其他的MEX文件一样可以动态的连接到MATLAB。本文只介绍用MATLAB语言书写的S-函数。
S-函数采用一种特殊的调用语法使得函数可以和Simulink方程解法器进行交互,这种交互与解法器和Simulink系统自身提供的模块间的交互十分类似。S-函数的形式十分通用,用户可以用它描述连续、离散和混合系统。
7.10.2 为何要用S-函数
通过S-函数,用户可以实现以下操作:
· 用户可以通过它用多种语言来创建新的通用性的Simulink模块;
· 只需遵循一系列简单的规则,用户即可将自己的算法用S-函数实现。当用户写好自己的S-函数后,可以在User-Defined Functions模块库中的S-function模块中通过名称来调用编写好的S-函数,用户还可以封装它;
· 用户可以通过S-函数将一个系统描述成一个数学方程;
· 便于使用图形化仿真;
· 可以创建代表硬件驱动的模块。
使用S-函数的主要优点是用户可以通过它创建通用性模块,可以多次调用,而且可以每次使用不同的参数值。
7.10.3 S-函数如何工作
要理解S-函数如何工作,读者应该先理解如何用数学描述一个模块以及Simulink如何仿真一个模型。
1.模块的输入、状态和输出间的数学关系
描述一个Simulink模块需要3个基本元素,即输入向量(u)、状态向量(x)和输出向量(y),输出是输入向量和采样时间的函数:
Simulink在仿真时把上面的这些方程对应为不同的仿真阶段,它们分别是计算模块的输出、更新模块的离散状态和计算连续状态的微分。在仿真的开始和结束,还包括初始化和结束任务两个阶段。在每一个阶段,Simulink都重复地对模型进行调用。
2.Simulink运行仿真的过程
仿真按照如图7-77所示的流程进行,由图可知仿真是分阶段进行的。在初始化阶段,Simulink将库中的模块并入到用户自建模型中,确定模块端口的数据宽度、数据类型和采样时间,评估模块参数,决定模块运行的优先级,定位存储地址;然后进入仿真循环,每一次的仿真循环称为一个仿真步。在每一个仿真步中的不同仿真阶段,Simulink按优先级运行模型中的每一个模块。如果在积分时对仿真的时间步长有要求,则此时需要将时间步细化;完成一个仿真循环(也即一个仿真步)后,就进入下一个循环仿真步,如此循环直至仿真结束。含有S-函数模块的模型的仿真过程与此类似。
图7-77 仿真执行流程图
3.S-函数的回调方法
一个S-函数是由一系列S-函数回调的方法组成,在每次仿真循环中的每一个仿真阶段由Simulink调用相应的S-函数回调方法来执行相应的任务。至于S-函数有哪些回调方法,以及Simulink如何确定在某一个仿真阶段调用哪一个回调方法,将在下一小节介绍。
与一般模型的仿真类似,S-函数回调方法用以完成以下任务:
· 初始化:在进入第一个仿真循环之前,Simulink初始化S-函数。在此阶段,Simulink主要完成初始化SimStruct(SimStruct包含S-函数信息的数据结构),确定输入输出端口的数目和大小,确定模块的采样时间,分配内存和Sizes数组的工作。
· 计算下一个采样点。如果模型使用变步长解法器,那么就需要在当前仿真步确定下一个采样点的时刻,即下一个仿真步的大小。
· 计算当前主仿真步的输出。当这次回调完成后,模块的所有输出端口的值对当前仿真时间步有效,即模块的输出被更新后才能作为其他模块的有效输入去影响那些模块的行为。
· 更新当前主时间步的离散状态。在此仿真阶段,所有的模块都要为当前时间的仿真循环更新离散状态。
· 积分。只有当模块具有连续状态或者非采样过零点时,Simulink才会有这一仿真阶段。对于S-函数,在该仿真阶段Simulink按最小时间步来调用S-函数的输出和微分S-函数方法。如果S-函数具有非采样过零点,Simulink按最小时间步来调用S-函数中的输出和过零点部分,以便Simulink确定过零点的位置。
7.10.4 怎样书写S-函数
下面将使用MATLAB语言来书写S-函数称为M文件S-函数,每一个M文件S-函数包含一个如下形式的M函数:
表7-28列出了上式中各参数的含义。在这类S-函数中的S-函数回调方法是用M文件子函数的形式来实现的。
表7-28 函数各参数的含义
在模型仿真过程中,Simulink重复地调用f,并根据Simulink所处的仿真阶段为flag参量传递不同的值,同时为sys变量指定不同的角色(不同的角色对应不同的返回值)。flag用来标示f函数要执行的任务,以便Simulink调用相应的子函数(也即S-函数的回调方法)。
因此,用户在编写M文件S-函数时只需用MATLAB语言来为每个flag值对应的S-函数方法编写代码即可。表7-29列出了在各个仿真阶段对应要执行的S-函数回调方法以及相应的flag参数值。
表7-29 各个仿真阶段对应要执行的S-函数方法
用户可以通过在MATLAB 7.0命令窗口输入“<<sfundemos”命令来查看S-函数示例,如图7-78所示。其中提供了一个“M-file S-function Template”示例,它是为用户书写S-函数提供的一个模板。使用模板编写S-函数时,用户可将S-函数名换成期望的函数名,若需要额外的输入参数量,还需要在输入参数列表的后面增加这些参数。用户剩下的任务就是根据所编S-函数要达到的目的,用相应的代码去代替模板里各个子函数的代码。
图7-78 S-函数示例
“M-file S-function Template”中的“M-file S-function”模块的文件代码如下(删掉了其中的解释性文字):
其中mdlInitializeSizes方法中的sizes是一个结构,它是S-函数信息的载体,其各个字段的意义如表7-30所示。模板中simsizes函数的作用与用法可查阅帮助。
表7-30 sizes各字段的意义
S-函数模块还可实现直接馈入、输入信号宽度动态可变以及多种采样时间的设置,S-函数还可以用其他计算机高级语言书写,但其基本原理是一样的,鉴于篇幅有限,这些内容请读者自己查阅帮助。
7.10.5 S-函数应用示例
本小节只介绍如何利用“User-Defined Functions”,库中的S-Function模块创建由MATLAB语言书写的M文件S-函数。对于如何使用其他语言和方法来书写,请读者查阅帮助。
用S-函数实现一个传输函数为[(S+1)(S+2)]-1的模块,如图7-79所示。
图7-79 S函数模块
其中Zero-Pole模块和S-function模块实现的功能一样,目的是检验所写的S-函数模块是否正确。S-function Example模块是为了方便打开M-文件S-函数书写的模板,通过模板书写好的S-函数文件保存为myfilter.m。S-function模块的S-函数名参数设为myfilter,scope模块的输入坐标轴数目设为2,其他模块的参数采用默认值。关于如何将传输函数转换成状态方程,请查阅有关信号与系统的书籍。
S-函数文件内容如下:
仿真结果如图7-80所示,上下两个模块的输出结果一样,这就证明所写S-函数功能正确。读者可以试着书写自己的S-函数模块。
图7-80 S-函数模型仿真结果
注意:S-函数保存的文件名和函数名要一致,保存M-文件S-函数的目录要包含在MATLAB 7.0的搜索路径文件之中。
7.11 综合实例——PLL中的非线性电荷泵和滤波器
在结束本章之前,将通过创建一个较为复杂的模型向读者总结如何利用Simulink来创建自己的模型并进行仿真。通过本小节的学习,读者将会对前面的内容有一个更为深刻的理解,对Simulink建模有一个较为全面的认识。
下面创建锁相环中电荷泵和滤波器部分的模型,系统示意图如图7-81所示。
图7-81 电荷泵和滤波器
下面按第7.2.2节介绍的建模步骤进行该系统的建模。
· 系统分析
创建该模块后,当up为高电平时电流I对电容充电,当down为高电平时电流I对电容放电,up和down不会同时为高电平。C1、C2和R组成的部分实现的是一个滤波器的功能,可以用一个Transfer Fcn模块来实现,其实现的传输函数是:
其中R、C1和C2可设为变量,并将该模块进行封装。
本模型难以实现的是电荷泵部分。当up为高电平时,电流I以正阶跃信号的形式输入滤波器模块;当down为高电平时,电流I以负阶跃信号的形式输入滤波器模块,但是Simulink库中Sources子库提供的Step模块的阶跃产生时间参数难以设置成随up或down信号高电平到达时间而变。在此采用User-Defined Functions子库中的Embedded MATLAB Funtion模块实现一个电流阶跃的产生时间随up或down信号的到达时间而变的电荷泵。
· 启动Simulink模块库浏览器,创建如图7-82所示的电荷泵和滤波器模型。
图7-82 电荷泵和滤波器模型
Embedded MATLAB Function模块中的文件如下:
Embedded MATLAB Function1模块中的文件如下:
滤波器的功能由Ports&Subsystem子库中的使能子系统来实现,两个使能子系统模块的内部结构完全一样,如图7-83所示。
图7-83 滤波器子系统
其中Transfer Fcn模块的参数设置如图7-84所示。Enable模块的“States when enabling”参数设为reset,若设为held,那么滤波器(Transfer Fcn模块)不会将输入电流的跳变当成一个阶跃信号来处理。这样每一次使能信号有效后,Transfer Fcn模块的状态就会重置成初始状态,体现在输出上就是在每一次Enable信号有效时输出都是从0开始变化。这也是在系统模型中用两个滤波器来分别处理输入的正阶跃和负阶跃电流的原因。系统的最终输出是两个滤波器输出的和,因为up和down不会同时为高电平,所以这样做可以保证每一时刻的输出都能反映前面所有时间的输入对系统状态的积累效果。如果要考虑有up和down同时为高电平的情况,那么可以在up输入和down输入与Embedded MATLAB Function模块的输入端口之间加一模块,使得在此种情况下进入Embedded MATLAB Function模块down端口和Embedded MATLAB Function1模块up端口的信号值都为0,即没有电流输入到滤波器,这与实际相吻合。
Enable模块还有另外一个作用是保证滤波器只对使能信号上升边沿的阶跃信号进行处理,即只接收Idown从0→-25和Iup从0→25的阶跃信号,而不接收Idown从-25→0和Iup从25→0的阶跃信号。读者还可以试着将子系统中的Enable模块换成Trigger模块,观察会出现什么问题。
如果读者对上面这些有关信号处理的知识不了解的话,那么你也可以不必知道为什么要这样设置,而只需学习模型创建的过程即可。
图7-84 Transfer Fcn模块的参数设置
· 封装子系统
对由使能子系统构造的滤波器模块进行封装(方法参见第7.3.2节),其中封装的设置情况如图7-85所示。用鼠标左键双击封装好的使能子系统图标将会弹出如图7-86所示参数设置对话框,用户可在此对话框中设置子系统的参数。
· 设置参数
在第二步中已对各主要模块的参数设置都进行了说明,下面主要设置与仿真有关的设置。主要需要设置的是仿真开始和结束的时间、解法器的类型和解法器、最大和最小仿真步长以及相对和绝对的仿真误差容忍度等,具体设置如图7-87所示。读者可以对其中的设置进行修改,然后进行仿真,观察输出因设置的不同而相应发生了哪些变化。
图7-85 使能子系统的封装参数设置
图7-86 封装使能子系统的参数设置对话框
图7-87 仿真参数设置
· 保存模型
为了仿真方便,读者可以将模型中的up和down输入模块用一信号源模块(如Pulse Generator、Sine Wave等)代替,这样就不用通过MATLAB命令来为模型添加输入信号。如果仿真结果不够理想,那么可以调整模块参数和仿真参数的设置,直至仿真结果吻合与建模用户预想的情况相符。仿真结果如图7-88和、图7-89和图7-90所示,相关模块的参数设置如下:
滤波器子系统模块中R=31.8e3,C1=62.2e-12,C2=6e-12;输入信号为脉冲信号,周期为2e-6、幅度为1、占空比50%,up和down相位相差180°;仿真参数的设置如图7-87所示。
图7-88 Iup和Idown仿真结果
图7-89 Vc_Down、Vc和Vc_Up的仿真结果
由图7-89可以看出滤波器只对Iup的上升跳变和Idown的下降跳变有效,而且每当滤波器的使能信号有效时,它的输出都是从0开始变化。
若将模型中上面的一个滤波器子系统中Enable模块的“States when enabling”参数设为held,那么仿真结果将如图7-90所示。对比图7-89和图7-90,可以证明第二步中所述分析是正确的。改为held后,只有开始的一个电流跳变被当作阶跃信号来处理,其余的均当作常量来处理的,因为对应处的Vc_Down是线性变化的。
图7-90 改变Enable模块的参数后的仿真结果
· 调试
有时用户对所建模型的输出结果并没有一个预想的值,因此只是简单的通过观察结果并不能证明所建模型的正确性,这时就需要进行调试(方法参见第7.9节),以观察系统的每一个模块在每一个时间步的运行情况。对于上面的模型,可能会因为读者的操作系统和MATLAB 7.0的安装情况不同而有所不同,在此不作详细的解释。
本小节通过创建一个较为复杂的模型向读者展示了在实际的建模过程中,用户会经常碰到的某些问题。示例中遇到的最大问题是当Simulink库中没有完全满足用户要求的现成模块时,用户该如何去利用已有模块来构造需要的模块,以及如何验证模型的正确性。当然只通过一个示例不足以展示所有建模的细节问题,但是通过对本章内容的全面学习,相信读者将会知道如何去解决实际操作中碰到的各种具体问题。