写点什么

MATLAB 实战 | S 函数的设计与应用

作者:TiAmo
  • 2023-12-02
    青海
  • 本文字数:2423 字

    阅读完需:约 8 分钟

MATLAB实战 | S函数的设计与应用

S 函数用于开发新的 Simulink 通用功能模块,是一种对模块库进行扩展的工具。S 函数可以采用 MATLAB 语言、C、C++、FORTRAN、Ada 等语言编写。在 S 函数中使用文本方式输入公式、方程,非常适合复杂动态系统的数学描述,并且在仿真过程中可以对仿真进行更精确的控制。

S 函数称为系统函数(System Function),采用非图形化的方式描述功能块。MATLAB 语言编写的 S 函数可以充分利用 MATLAB 所提供的丰富资源,方便地调用各种工具箱函数和图形函数; 使用 C 语言编写的 S 函数可以实现对操作系统的访问,如实现与其他进程的通信和同步等。非 MATLAB 语言编写的 S 函数需要用编译器生成 MEX 文件。本文介绍用 MATLAB 语言设计 S 函数的方法,并通过例子介绍 S 函数的应用。


01、用 MATLAB 语言编写 S 函数


S 函数有固定的程序格式,可以从 Simulink 提供的 S 函数模板程序开始构建自己的 S 函数。


1. 主程序


S 函数主程序的引导语句如下:


其中,fname 是 S 函数的函数名,t、x、u、flag 分别为仿真时间、状态向量、输入向量和子程序调用标志。flag 控制在仿真的各阶段调用 S 函数的哪一个子程序,其含义和有关信息如表 1 所示。Simulink 每次调用 S 函数时,必须给出这 4 个参数。sys、x0、str 和 ts 是 S 函数的返回参数。sys 是一个返回参数的通用符号,它得到何种参数,取决于 flag 值。例如,flag = 3 时,sys 得到的是 S 函数的输出向量值。x0 是初始状态值,如果系统中没有状态变量,x0 将得到一个空阵。str 仅用于系统模型同 S 函数 API(应用程序编程接口)的一致性校验。对于 M 文件 S 函数,它将被置成一个空阵。ts 是一个两列矩阵,一列是 S 函数中各状态变量的采样周期,另一列是相应的采样时间的偏移量。采样周期按递增顺序排列,ts 中的一行对应一个采样周期。对于连续系统,采样周期和偏移量都应置成 0。如果取采样周期为-1,则将继承输入信号的采样周期。

■ 表 1 flag 参数的含义

此外,在主程序输入参数中还可以包括用户自定义参数表: p1、p2、…、pn,这也就是希望赋给 S 函数的可选变量,其值通过相应 S 函数的参数对话框设置,也可以在命令行窗口赋值。于是 S 函数主程序的引导语句可以写成:

主程序采用 switch 语句,引导 Simulink 到正确的子程序。


2. 子程序


S 函数 M 文件共有 6 个子程序,供 Simulink 在仿真的不同阶段调用,这些子程序的前缀为 mdl。每一次调用 S 函数时,都要给出一个 flag 值,实际执行 S 函数中与该 flag 值对应的那个子程序。Simulink 在仿真的不同阶段,需要调用 S 函数中不同的子程序。

(1) 初始化子程序 mdlInitializeSizes。子程序 mdlInitializeSizes 定义 S 函数参数,如采样时间、输入量、输出量、状态变量的个数以及其他特征。为了向 Simulink 提供这些信息,在子程序 mdlInitializeSizes 的开始处应调用 simsizes 函数,这个函数返回一个 sizes 结构,结构的成员 sizes.NumContStates、sizes.NumDiscStates、sizes.NumOutputs 和 sizes.NumInputs 分别表示连续状态变量的个数、离散状态变量的个数、输出的个数和输入的个数。这 4 个值可以置为-1,使其大小动态改变。成员 sizes.DirFeedthrough 是直通标志,即输入信号是否直接在输出端出现的标志,是否设定为直通,取决于输出是否为输入的函数,或者是取样时间是否为输入的函数。1 表示 yes,0 表示 no。成员 sizes.NumSampleTimes 是模块采样周期的个数,一般取 1。

按照要求设置好的结构 sizes 用 sys = simsizes(sizes)语句赋给 sys 参数。除了 sys 外,还应该设置系统的初始状态变量 x0、说明变量 str 和采样周期变量 ts。

(2) 其他子程序。状态的动态更新使用 mdlDerivatives 和 mdlUpdate 两个子程序,前者用于连续模块的状态更新,后者用于离散状态的更新。这些函数的输出值,即相应的状态,均由 sys 变量返回。对于同时含有连续状态和离散状态的混合系统,则需要同时写出这两个函数来分别描述连续状态和离散状态。

模块输出信号的计算使用 mdlOutputs 子程序,系统的输出仍由 sys 变量返回。

一般应用中很少使用 flag 为 4 和 9 的情况,mdlGetTimeOfNextVarHit 和 mdlTerminate 两个子程序较少使用。


02、S 函数的应用


下面来看用 M 文件编写 S 函数的例子。

【例 1】采用 S 函数实现 y=k(1+x),即把一个输入信号加 1 后放大 k 倍。

(1) 编写 S 函数,程序如下:

S函数 timek.m,其输出是输入加1的k倍function[sys,x0,str,ts]= timek(t,x,uflag,k)switch flag,case 0[sys,x0,str,ts]= mdlInitializeSizes;//初始化case 3sys = mdlOutputs(t,x,u,k);//计算输出量case{1,2,4,9)sys =[];otherwiseerror(num2str(flag));//出错处理end//mdlInitializeSizes:当 flag 为0时进行整个系统的初始化functionsys,x0,str,ts]= mdlInitializeSizes()//调用函数 simsizes 以创建结构 sizessizes = simsizes;//用初始化信息填充结构 sizessizes.NumContStates = 0;//无连续状态sizes.NumDiscStates = 0://无离散状态sizes.NumOutputs = 1;//有一个输出量sizes.NumInputs = 1;//有一个输入量sizes.DirFeedthrough = 1;//有一个输入量sizes.NumSampleTimes =1;//输出量中含有输入量//根据上面的设置设定系统初始化参数sys = simsizes(sizes);//给其他返回参数赋值x0[];//设置初始状态为零状str=[];ts=[-1,0];//将 str 变量设置为空字符串%假定继承输入信号的采样周期//mdlOutputs当 flag 值为3 时,计算输出量function sys = mdlOutputs(t,x,u,k)sys=k*(1+u)
复制代码

将该程序以文件名 timek.m 存盘。编好 S 函数后,就可以对该模块进行测试了。

(2) S 函数模块的测试。建立 S-Function 模块和编写的 S 函数文件之间的联系。新建一个模型,向模型编辑窗口中添加 User-Defined Functions 模块库中的 S-Function 模块,还有 Sine Wave 模块和 Scope 模块,构建如图 1 所示的仿真模型。


■ 图 1 S 函数仿真模型

在模型编辑窗口中双击 S-Function 模块,打开其参数对话框,在“S-function 名称”框中填入 S 函数名 timek,在“S-function 参数”框中填入外部参数 k,如图 2 所示。如果有多个外部参数,参数之间用逗号分隔。k 可以在 MATLAB 工作区用命令定义。当输入 k 的值为 5 时,运行得到的仿真结果如图 3 所示。


■ 图 2 S 函数参数对话框



■ 图 3 S 函数的仿真结果


发布于: 刚刚阅读数: 3
用户头像

TiAmo

关注

有能力爱自己,有余力爱别人! 2022-06-16 加入

CSDN全栈领域优质创作者,万粉博主;阿里云专家博主、星级博主、技术博主、阿里云问答官,阿里云MVP;华为云享专家;华为Iot专家;

评论

发布
暂无评论
MATLAB实战 | S函数的设计与应用_matlab_TiAmo_InfoQ写作社区