控制系统设计与仿真实验指导书 下载本文

4.6 实验十 S函数的编写及应用

一、实验目的

1、学习S函数的编写方法。

2、利用S函数在Simulink环境中实现复杂模块。

二、相关知识

Simulink是提供了一个十分易用的仿真平台,但在使用过程中会发现有些过程或对象用现成的Simulink模块不易搭建,远不如m文件和函数灵活和强大。事实上,Simulink也提供了一个解决方案——S函数,类似于普通函数的功能,这大大扩展了Simulink的仿真能力。

1、 用MATLAB语句编写S函数

S函数还可以用C、C++、Fortran等语言编写。用MATLAB语句编写S函数引导语句为:

function [sys,x0,str,ts]=funname(t,x,u,flag,p1,p2,?)

其中funname 为函数名,t、x、u分别为时间、状态和输入信号,flag为标志位,这四个参数是固定的,后面几个参数为输入参数。flag的值为0、1、2、3、4和9,分别对应一个内部过程,其关系如下表所示: Flag取值 0 1 2 3 4 9 在仿真过程中,flag=0(初始化过程)仅出现一次,其他值(过程)在每个采样周期循环出现,在每个过程中要完成一些功能,只要在这个过程中写上适当的程序代码即可。函数主程序通常如下(参见Simulink自带文件sfuntmpl.mdl):

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);

过程 初始化 连续状态计算 离散状态计算 输出信号计算 调用函数名 mdlInitializeSizes mdlDerivatives mdlUpdate mdlOutputs 返回参数 sys为初始化参数,x0, str, ts如其定义 sys返回连续状态 sys返回离散状态 sys返回系统输出 下一步仿真时刻 mdlGetTimeOfNextVarHit sys返回下一步仿真的时间 终止仿真设定 mdlTerminate 无 33

case 4,

sys=mdlGetTimeOfNextVarHit(t,x,u); case 9,

sys=mdlTerminate(t,x,u); otherwise

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

调用的各函数写在主程序之后,函数名是Simulin推荐的函数名,不是强制性的,我们也可以用其他函数名,更简单地,不用函数,把过程直接写在主程序中。其中flag为0和3的过程必须编写程序,其他过程根据实际需要可忽略。初始化过程的编写有一定的规范,如下所示:

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

sizes = simsizes;

sizes.NumContStates = 1; sizes.NumDiscStates = 0; sizes.NumOutputs = 1; sizes.NumInputs = 2; sizes.DirFeedthrough = 1;

sys = simsizes(sizes);

x0 = []; str = [];

初始化需提供S函数的一些特定信息,包括输入/输出变量和状态的个数等,这通过一个结构变量实现。第一句sizes = simsizes通过simsizes函数定义一个结构变量,该变量有6个结构元素,如上所示,按具体要求设置完成后,通过sys = simsizes(sizes)语句赋给sys参数。除了sys外,还应设置系统的初始状态变量x0、说明变量str和采样周期变量ts,其中ts为双列矩阵,每一行对应一个采样周期。对连续系统和有单个采样周期的系统来说,该变量为[t1,t2],其中t1为采样周期,t1=-1则将继承输入信号的采样周期,t2为偏移量,一般取0。

2、S函数的调用

建立Simulink仿真框图时,选择S-Function模块(MATLAB6.5/Simulink5在User-Defined Function模块库),双击S-Function模块,会弹出一个参数设置对话框,如下图所示,在S-Function name栏内填写S函数文件名,就可以建立起该模块和我们编写的S函数

%初始化状态

%说明字符串变量,通常为空串 %采样周期初始化

%连续状态的个数 %离散状态的个数 %输出变量个数 %输入变量个数

%输入是否直接至输出端,通常为1

%采样周期个数,通常为1。S函数支持多采样周期系统

sizes.NumSampleTimes = 1;

ts = [-1 0];

34

文件之间的联系,在S-Function parameters栏内给出S函数的输入参数,参数可以是常数,也可以是变量名,如果是变量名,仿真前须在命令窗口中赋值。

三、实验内容

1.编写S函数,实现下图死区非线性模块功能

编写S函数如下:

function [sys,x0,str,ts] = sqnl(t,x,u,flag,s1) %死区非线性

y h -s-h -s s -h s+h x 35

% s1为死区环值

switch flag, case 0,

[sys,x0,str,ts]=mdlInitializeSizes; case 1 sys=x; case 3,

sys=mdlOutputs(t,x,u,s1); case {1,2,4,9} sys=[]; otherwise

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

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

sizes = simsizes;

sizes.NumContStates = 0; sizes.NumDiscStates = 0; sizes.NumOutputs = 1; sizes.NumInputs = 1; sizes.DirFeedthrough = 1;

sizes.NumSampleTimes = 1; % at least one sample time is needed sys = simsizes(sizes); x0=[]; str=[]; ts=[-1 0];

function sys=mdlOutputs(t,x,u,s1) if abs(u)>=s1,

if u>0,sys=u-s1; else sys=u+s1; end

else sys=0; end

按上面介绍的方法,建立Simulink模块,运行验证。

2.编写S函数,实现积分分离PID控制功能

36