典型的Simulink模块双击时会弹出对话框,在对话框中可以设置模块参数,如:双击正弦波模块(SineWave),可以设置正弦波幅值和频率;双击增益模块(Gain),可以设置增益值;双击PID控制器模块(PID Controller),可以设置PID参数值;双击传递函数模块(Transfer Fcn),可以设置传递函数的分子和分母系数。
但很多时候,需要在 Simulink仿真过程中修改模块的对话框参数 (称为在线修改或动态修改模块参数),如:希望在仿真过程中改变正弦波的频率,实现扫频信号;希望在仿真过程中改变增益模块增益值,实现变增益;希望在仿真过程中改变PID控制器增益,实现自适应的PID控制;希望在仿真过程中改变传递函数的分子或分母系数,实现时变的传递函数。
本文详细介绍Simulink如何在线修改(动态修改)模块参数的方法,并提供原创的DynamicChange Parameter模块(简称DCP模块),可以轻松解决在线修改(动态修改)模块参数问题,提供详细帮助文件和大量例程,简单易用。
1. 方法
Simulink中的对话框参数有三种类型:Tunable(可调);Nontunable(不可调);SimOnlyTunable(不可动态调整)。需要动态调整的参数,必须为可调(Tunable)类型。
郑志波《Simulink 模块参数在线修改方法的研究》中提到了两种在线更新参数的方法:1. 使用全局变量,在m文件中动态修改全局变量的值,进而达到修改参数的目的;2. 使用set_param函数,在m文件中动态设置对话框参数。
经测试,第一种方法不可行。如图2所示,Modify_c函数中对全局变量进行动态更新,使c的取值由0每隔1s增加至11,Simulink运行完成后全局变量的c更新为11,模型对全局变量的更新是成功的,但对话框参数并未随全局变量的改变而改变,增益c仍然为0。原因是:simulink模块对变量的读入只在模型初始化(或开始运行)的回调函数中执行,在仿真进行的过程中,尽管对话框参数的变量值改变了,但是系统并不会读取更新后的参数值,仿真中使用的参数值仍是变量的初始值0。
第二种方法是可行的,该方法可用S函数来实现,将模块名和参数名都作为S函数的参数,需要改变的参数值作为S函数的输入,在S函数的状态更新(Updata)回调函数中,使用set_param函数对对话框参数进行动态更新。
本人采用Level-2的S函数实现了上述第二种方法,并将其封装为模块形式(下文中称此模块为DCP模块),方便在其它模型中调用。
3. DCP模块
DCP模块经封装后,与Simulink自带模块完全相同,有两个输入端口,双击模块会弹出属性对话框,可以在对话框中设置需要动态改变的模块参数信息。
输入接口:
接口1 [var] : 需要设定的参数值;
接口2[flag] : flag=0时忽略接口1的输入,不对参数进行更新;flag~=0时更新参数。
对话框参数:
模块名[block_name] :格式为“mdl文件名/子模型名/模块名(tag)”,字符串形式;
参数名[par_name] : 需要动态修改的参数变量名,字符串形式,如需要修改增益模块的增益值,则输入“Gain”。一般来说,手动输入模块名、参数名比较复杂而且容易出错,模块中采用函数自动提取模块名和变量名,用户只需在所提供的GUI中作出选择即可。
重置[Reset] : 此复选框选中时,弹出选择模块和参数设置GUI,如图4所示。
图4 模块和参数设置GUI
采样模式: 1×2矩阵;设置模块的采样方式(与S函数中的采样方式定义相同)。
[0 offset] : 连续采样时间,offset给定时间偏置;
[ts offset] : 离散采样时间,ts为采样时间;
[-1, 0] : 继承采样时间,取决于上一模块的采样方式和时间;
参数维数: 1×2矩阵([行数 列数]),表示需要修改参数的维数(即接口1中输入数据的维数),使用本模块必须保证参数的维数不变。
4.使用
DCP模块配套文件有:
使用步骤如下:
1)将DCP文件夹放置在Matlab工作目录下;
2)运行1次AddFilePath.m文件(仅首次使用DCP模块时需要执行此步骤);
3)两种方式将DCP模块加入到Simulink中:方法一,打开Simulink Library Browser -> User Defined Block模块组 -> DCP模块 -> 将DCP模块拖入Simulink模型中;方法二,复制例程中的DCP模块至需要的Simulink模型中。
4)双击DCP模块,弹出属性设置对话框,点击Reset复选框,弹出模块和参数设置GUI,选择需要在线修改的模块和参数,设置采样时间和参数维度,点击“OK”确定;
5)将需要修改的参数值接入DCP模块的输入接口1,输入接口2用于进行时序控制,如不需要进行时序控制,输入接口2可以接入常数1。
5. 例程
5.1 DCP模块实现可变增益
模型 :DCP_Test01_stairGain.slx
功能描述 :通过动态改变增益值,实现阶梯上升曲线;
改变参数的条件 :通过设置DCP 为离散定步长采样方式,并给定固定采样时间0.1s,来实现每隔0.1s 改变一次增益值。
结果 :
说明 :实际设定的参数比期望设定的要滞后一拍,这说明参数的更新需要在下一个步长起作用,0~0.1s内设定的参数值2为Gain模块的初始值。
5.2 DCP模块实现正弦扫频信号
模型 :DCP_Test02_sweep.mdl
功能描述 :通过动态改变正弦波模块的频率,实现扫频曲线。频率间隔为1Hz,每个频率保持时间为1s;
改变参数的条件 :通过输入接口1 中参数par_val 的输入波形来控制,接口1 中输入的参数为阶梯波(可在Scope__Frequence 中查看),DCP 模块中的set_param 函数只会在阶梯波发生突变的时间执行,其它时间DCP 模块会执行,但其中的set_param 函数不会执行,这不会占用太多的资源。
结果 :
说明:在整数秒时刻(1、2、3 …)频率突变。
5.3 DCP模块实现时变传递函数
模型 :DCP_Test03_variGs.mdl
功能描述 :通过动态改变传递函数模块的分母向量实现时变的传递函数,在仿真时间为5s 时,传递函数分母由[1 2 50]突变为[1 4 100];
参数改变的条件 :在仿真时间等于5s 时,使DCP 模块的接口2 的flag 值从0 突变到1(这里通过一个阶跃来实现这个突变)。DCP 模块中的set_param 函数前5s 由于flag=0 不会执行;阶跃后flag=1,set_param 函数执行一次;之后又由于接口1 中的输入保持恒定,set_param 函数也不会再执行。
结果 :
5.4 DCP模块实现积分分离PID控制算法
模型 :DCP_Test04_int_separatePID.mdl
功能描述 :通过动态改变PID 控制器积分增益的值(由0 变为0.01),来控制积分环节的投入与分离,对一个纯滞后的一阶系统进行控制;仿真表明:积分分离式PID 可无超调收敛到给定值,常规PID 有超调,不投入积分时,又会存在稳态误差。
参数改变的条件 :当偏差信号(指令信号减去给定信号)的绝对值小于阈值(这里取0.3)时,积分增益由0 突变为0.01,之后保持不变。本例与前述例子的不同之处在于,使用一个布尔条件作为DCP 模块接口2 的flag 值。
注意 :由于DCP 模块中的第二个接口定义的是double 类型的数据,所以判断条件的结构(为布尔量)不能直接接入,需通过一个数据类型转换(Data Type Conversion)模块进行数据类型转换之后再输入到DCP 模块的接口2。数据类型转换模块的路径为:Simulink –> Signal Attributes -> Data Type Conversion。
结果 :
6. 适用范围
使用set_param修改模块参数耗时较长,如将set_param循环10000次消耗4.9s,过于频繁的调用DCP模块会使模型仿真速度很慢。为了尽量减少set_param不必要的执行,DCP模块中采用了以下方法:
1)当输入接口1中输入的变量值与上一采样时间相等,即var(k) = var(k-1)时,set_param不执行;
2)当输入接口2中输入0值,即flag=0时,set_param不执行;
下面情况请慎用本模块:需要设定的参数连续变化,即在求解器的每个时间(步长)内都要执行set_param,这将严重影响仿真效率。此时建议使用“转换”的思想,将对话框参数变成输入接口。
DCP 模块的功能通俗的讲,就是将模块的“对话框参数”变成一个“输入接口”,通过在这个接口中引入动态信号(simulink 中连线传递的都是动态信号),来达到动态改变参数的目的。 DCP模块带来方便的同时,频繁执行set_param会降低Simulink运行速度,因此参数连续变化时需要一种效率更高的解决办法。
变参数的问题稍作变化可以得到解决,如例程1 中的变增益问题:如下所示,可直接使用乘法模块,将信号增益转换成信号乘法,从而实现将“对话框参数”转换成“输入参数”。
当然这只是一个简单的例子,对于复杂的问题道理也是相同的,即:使用恰当的模块,将“对话框参数”转变为“输入接口”。往后有机会的话,我将向大家介绍几种实现时变传递函数的方法。
7. 不足之处
1)由于S 函数中未定义RTW 相关回调函数,使用了DCP 模块的simulink 模型不能编译。
2)set_param 是在S 函数中的Updata 回调函数中,simulink 的运行模式是先执行Output回调函数,再执行Updata 回调函数,所以DCP 模块中设置的参数只能在下一步长中生效,当前步长的计算中仍使用的旧参数,即使用本模块有一拍的固有延时(延时时间为一个仿真步长)。观察Test01 的结果,0-0.1s 内,输出为Gain 的初始值,0.1-0.2s 内,输出为0(0 是在0.1s 时由DCP 设置的),0.2-0.3s 内为0.1 …… 一般来说,当simulink 的仿真步长足够小时,上述的延时可以忽略不计。