S-Function的使用

S-Function的使用

前言

为了兼顾代码和模型的优势,在Simulink的模型中嵌入m文件来对一个系统进行仿真,主要的数学模型放在m文件中,可以将数学语言直接转换成代码,不需要为一堆模块进行“连连看”,更适合状态空间的复现。

先导知识

基本知识

使用范例

实现流程

获取模板(Level1形式)

  • 2022版,之前的版本

    edit sfuntmpl
    

    在这里插入图片描述

  • 2022版,之后的版本

    edit sfundsc2
    

    在这里插入图片描述

  • 或者直接网上找一个现成的模板再改

修改模板

  1. 修改模板函数名(例如改成sfun1),将文件另存到当前工作空间,同时修改文件名(直接重命名就行),使文件名和函数名一致

    function [sys,x0,str,ts,simStateCompliance] = sfun1(t,x,u,flag)
    
  2. 修改初始化函数,以下是常用的一些含义

    function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
    %初始化回调子函数
    %提供状态、输入、输出、采样时间数目和初始状态的值
    %初始化阶段,标志变量flag首先被置为0,S-function首次被调用时
    %该子函数首先被调用,且为S-function模块提供下面信息
    %该子函数必须存在
    sizes = simsizes;             %生成sizes数据结构,信息被包含在其中
    
    sizes.NumContStates  = 3;     %连续状态数,所有状态字母的种类,例如x,y,z共3种
    sizes.NumDiscStates  = 0;     %离散状态数,默认为0,注意判断有没有
    
    sizes.NumOutputs     = 3;     %输出个数,3个输出则为3,没有输出则默认为0
    sizes.NumInputs      = 0;     %输入个数,1个输如则为1,没有输如则默认为0
    
    %当out=f(u)时,存在直馈通道;而当out=f(u,u',...)时,不存在直馈通道
    sizes.DirFeedthrough = 0;     %是否存在直馈通道,1表示存在,0表示不存在
    sizes.NumSampleTimes = 1;     %采样时间个数,至少是一个
    sys = simsizes(sizes);        %返回size数据结构所包含的信息
    x0  = [10.01;20;30];
    %初始化内部变量状态,|*|注意:长度必须与NumContStates中一致|*|
    str = [];                     %保留变量矩阵,一般置空
    ts  = [0 0];                  %设置采样时间,[a b]表示从第b秒起,每间隔a秒采集一次
    simStateCompliance = 'UnknownSimState';
    
  3. 添加求导环节(如果需要的话)

    3.1. 先在switch flag中添加求导环节

    switch flag,
      case 0,
          [sys,x0,str,ts,simStateCompliance]=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
        DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
    end
    

    3.2. 添加求导函数

    function sys=mdlDerivatives(t,x,u)
    %计算导数回调子函数
    %给定t,x,u计算连续状态的导数,可以在此给出系统的连续状态方程
    %该子函数可以不存在
    %sys表示状态导数,即dx;
    % sys = u;								%sys中所有变量的导数等于输入u
    % sys = [];								%不进行导数运算
    % 以洛伦兹系统为例
    rho = 28;
    beta = 8/3;
    sys(1) = sigma*(x(2) - x(1));           %dx=σ(y-x)
    sys(2) = rho*x(1) - x(2) - x(1)*x(3);   %dy=ρx-y-xz
    sys(3) = x(1)*x(2) - beta*x(3);         %dz=xy-βz
    
  4. 修改输出环节

    function sys=mdlOutputs(t,x,u)
    %计算输出回调函数(时间,中间变量,输入)
    %给定t,x,u计算输出,可以在此描述系统的输出方程
    %该子函数必须存在,支持单独修改/整合修改
    % sys(1) = x(1);
    % sys(2) = x(2);
    % sys(3) = x(3);
    sys = x;                            %sys表示输出,即y;x为系统变量
    

连接Simulink

  1. 打开库浏览器,添加S-Function模块

    在这里插入图片描述

  2. 连接m函数,将函数名字改成上文已经修改的函数名

在这里插入图片描述

  1. 点击运行

进阶使用

导出数据

可以将Simulink仿真生成的数据导出到工作区,以便与其他指令交互

  1. 找到To Workspace这个模块

    在这里插入图片描述

  2. 连接到需要输出的端口

    在这里插入图片描述

  3. 双击选择To Workspace的导出形式

    在这里插入图片描述

  4. 重新运行,导出数据到工作区

    在这里插入图片描述

  5. 双击打开可以看到导出数据

    在这里插入图片描述

    • “sc2out”为导出的具体数据
    • “tout”则为时间序列

    在这里插入图片描述

  6. 此时就可以在命令行中使用导出的数据进行操作;例如,调取第一列数据为

    out.sc2out(:,1)
    

在对话框中设置参数

可以实现在不修改代码的情况下,直接调整参数,类似于自带的模块

  1. 修改m文件,加入待选参数(例如gain这个参数)

    • 函数名称处 在这里插入图片描述

    • switch调用处

      在这里插入图片描述

    • 函数原型处

      在这里插入图片描述

  2. 在Simulink处写入具体参数(例如gain这个参数)

    在这里插入图片描述

  3. 点击运行

注意:参数是为泛指,即可以是一个参数,也可以是一组参数;若sizes.NumOutputs有多个,可以使用Demux模块拆分信号(直接输出是叠加的)

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值