s-function搭建变参数PMSM模型

S-function

一、什么是s-function

img

(1)非图形化地实现一个动态系统

(2)支持多种语言编写

(3)s-function是以现代控制理论的状态方程为基础的

image-20210522151522232

二、如何编写一个自己的s-function

(1)介绍

img

支持m函数语言、C语言、C++语言、和Fortran

img

img

img

模板函数是s-function的框架,以下会介绍

img

S-function的参数有三个,基本只用到第一个“name”

img

(2)模板函数

只需要掌握(1)~(4)函数即可,(2)(3)分别用于连续和离散,一般都用离散的

t时间
x状态变量
u输入
flags-function执行的标志,不用管
sys输出
x0状态变量初始值

第一部分:s-fucntion函数名为sfuntmpl

function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)
switch flag,
  case 0,   
[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;  	%1)初始化函数,这个函数必须有

  case 1,
    sys=mdlDerivatives(t,x,u);                              %2)连续下的微分输出,即dx
 
  case 2,
    sys=mdlUpdate(t,x,u);                                   %3)离散下的微分输出,即x(k+1)
 
  case 3,
    sys=mdlOutputs(t,x,u);                                  %4)输出sys
 
  case 4,
    sys=mdlGetTimeOfNextVarHit(t,x,u);						%5)变 采样时间才会用到
 
  case 9,
    sys=mdlTerminate(t,x,u);
 
  otherwise
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
 
end

第二部分:初始化函数

初始化主要完成:

(1) 离散变量,输入输出个数的确定

(2) 状态变量的初始值

(3) 采样时间

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

sizes = simsizes;
 
sizes.NumContStates  = 0;           %连续状态变量的个数
sizes.NumDiscStates  = 0;           %离散状态变量的个数
sizes.NumOutputs     = 0;           %输出个数,
sizes.NumInputs      = 0;           %输入个数,

sizes.DirFeedthrough = 1;  			% 直馈通道,指输入在输出中直接显示出来

sizes.NumSampleTimes = 1;   		% at least one sample time is needed

sys = simsizes(sizes);

% initialize the initial conditions
%
x0  = [];               %状态变量的初始值
 
%
% str is always an empty matrix
%
str = [];
 
%
% initialize the array of sample times
%
ts  = [0 0];            %采样时间,ts = [Ts 0]

% Specify the block simStateCompliance. The allowed values are:
%    'UnknownSimState', < The default setting; warn and assume DefaultSimState
%    'DefaultSimState', < Same sim state as a built-in block
%    'HasNoSimState',   < No sim state
%    'DisallowSimState' < Error out when saving or restoring the model sim state
simStateCompliance = 'UnknownSimState';			% 不用管是什么

第三部分:连续微分函数

function sys=mdlDerivatives(t,x,u)
 
sys = [];

第四部分:离散差分函数

function sys=mdlUpdate(t,x,u)
 
sys = [];

第五部分:输出函数

function sys=mdlOutputs(t,x,u)
 
sys = [];

三、案例一:s-function来表示直流电压的动态模型

(1)Simulink中的直流电机的模型

image-20210522153054253

这里为什么要加一个breaker,下面会讲到!

(2)用simulink搭建的直流电机模型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Emg383XF-1621671565942)(file:///Z:/Users/Jia/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]

image-20210522153142636

电气元件都可以用电压/电流源的形式来表达

img

img

(3)s-function编写的直流电机模型

image-20210522153247012

image-20210522153254581

注意电流源的方向
U = E a + R i a + L d i a d t U=E_a+Ri_a+L\frac{di_a}{dt} UEa+Ria+Ldtdia
写成微分形式,
d i a d t = ( u − K e ω − R i a ) / L \frac{di_a}{dt}=\left( u-K_e\omega -Ri_a \right) /L dtdia=(uKeωRia)/L

T e – T L = J d ω d t T_e–T_L=J\frac{d\omega}{dt} TeTL=Jdtdω

J d ω d t = K t i a – T L J\frac{d\omega}{dt}=K_ti_a–T_L Jdtdω=KtiaTL

根据状态方程,
x ˙ = A x + B u y = C x + D u \dot{x}=Ax+Bu \\ y=Cx+Du x˙=Ax+Buy=Cx+Du

输入端电压 u,负载转矩Tl
状态(可测量的,带微分的项)转速w,和电枢电流ia
输出也可以是转速w,和电枢电流ia

则,
x ˙ = A x + B u \dot{x}=Ax+Bu x˙=Ax+Bu

x ˙ = [ − R L − K e L K t J 0 ] [ i a w ] + [ 1 L 0 0 − 1 L ] [ u T l ] \dot{x}=\left[ \begin{matrix} -\frac{R}{L}& -K\frac{e}{L}\\ K\frac{t}{J}& 0\\ \end{matrix} \right] \left[ \begin{array}{c} ia\\ w\\ \end{array} \right] +\left[ \begin{matrix} \frac{1}{L}& 0\\ 0& -\frac{1}{L}\\ \end{matrix} \right] \left[ \begin{array}{c} u\\ Tl\\ \end{array} \right] x˙=[LRKJtKLe0][iaw]+[L100L1][uTl]

y = C x y=Cx y=Cx

y = x = [ i a w ] y=x=\left[ \begin{array}{c} ia\\ w\\ \end{array} \right] y=x=[iaw]

用差分方程表示,
x ( k + 1 ) = x ( k ) + T s ∗ ( A x + B u ) x\left( k+1 \right) =x\left( k \right) +Ts*(Ax+Bu) x(k+1)=x(k)+Ts(Ax+Bu)
于是s-function为,

function [sys,x0,str,ts,simStateCompliance] = sfun_dc(t,x,u,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
 
%====================================================================

function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
 
sizes = simsizes;
 
sizes.NumContStates  = 0;
sizes.NumDiscStates  = 2;
sizes.NumOutputs     = 2;
sizes.NumInputs      = 3;		%另外加了一个可变电阻,所以是三个输入变量
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;   % at least one sample time is needed
 
sys = simsizes(sizes);
 
%
% initialize the initial conditions
%
x0  = [0];
 
%
% str is always an empty matrix
%
str = [];
 
%
% initialize the array of sample times
%
Ts = 0.0001;
ts  = [Ts 0];
 
simStateCompliance = 'UnknownSimState';
 
%====================================================================

function sys=mdlDerivatives(t,x,u)
 
sys = [];
 
%====================================================================
function sys=mdlUpdate(t,x,u)
Ts=0.0001;				%这里要重新定义一次,变量不是全局的
 
 
Ke = 1.8*30/pi;
R = u(3);		%可变电阻
L = 0.02;
J = 10;
Kt = 17.2;
 
A = [-R/L -Ke/L; Kt/J 0];
B = [1/L 0; 0 -1/J];
 
sys = x+(A*x+B*[u(1);u(2)])*Ts;			% 此处的u要改成这个,不然维度不对
 
%====================================================================
function sys=mdlOutputs(t,x,u)
 
sys = x;
 
%====================================================================

function sys=mdlGetTimeOfNextVarHit(t,x,u)
 
sampleTime = 1;    %  Example, set the next hit to be one second later.
sys = t + sampleTime;
 
%====================================================================
function sys=mdlTerminate(t,x,u)
 
sys = [];
 
% end mdlTerminate

(4)仿真结果

image-20210522154418447

原始模型不加breaker(在0s处合上),不加的话,在0时刻以前就是电流值,所以下图的电流初始为5A。这是由于Laplace零时刻初始导致的。加上breaker后,变成了零状态,也就完全吻合了。

image-20210522154430149

四、案例二:用s-function编写可变参数的PMSM模型

目的:

(1)电机参数不可在线动态修改

(2)simulink自带模型的坐标变换与常规逻辑不同

SIMULINK 中集成 PMSM 模块定义的坐标变换角与国内常规定义不同[4],如图 1 所示。常规定义中 θ 为 d 轴与 α 轴的夹角,而 SIMULINK 中则定义成 q 轴与 α 轴的夹角,记为图中的 γ,显然,θ = γ -90°,这导致了在常规的调速系统中反馈回路需要对θ 做一次变换。

image-20210522154512957

需求分析:

永磁同步电机的数学模型

(1)电气方程

image-20210522154541241

显然,电气方程中的状态变量为id和iq,输入变量为ud和uq。但转速呢?在矩阵中,这算是输入还是状态?把它当作是输入量,但并不在u中体现。再增加一个输出为电磁转矩Te

function [sys,x0,str,ts,simStateCompliance] = Electrical_equation_signal_continus(t,x,u,flag)

switch flag,

  %%%%%%%%%%%%%%%%%%
  % Initialization %
  %%%%%%%%%%%%%%%%%%
  case 0,   
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;  %这个函数必须有

  %%%%%%%%%%%%%%%
  % Derivatives %
  %%%%%%%%%%%%%%%
  case 1,
    sys=mdlDerivatives(t,x,u);                              %这个函数可以有

  %%%%%%%%%%
  % Update %
  %%%%%%%%%%
  case 2,
    sys=mdlUpdate(t,x,u);                                   %这个函数可以有

  %%%%%%%%%%%
  % Outputs %
  %%%%%%%%%%%
  case 3,
    sys=mdlOutputs(t,x,u);                                  %这个函数必须有

  %%%%%%%%%%%%%%%%%%%%%%%
  % GetTimeOfNextVarHit %
  %%%%%%%%%%%%%%%%%%%%%%%
  case 4,
    sys=mdlGetTimeOfNextVarHit(t,x,u);

  %%%%%%%%%%%%%
  % Terminate %
  %%%%%%%%%%%%%
  case 9,
    sys=mdlTerminate(t,x,u);

  %%%%%%%%%%%%%%%%%%%%
  % Unexpected flags %
  %%%%%%%%%%%%%%%%%%%%
  otherwise
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));

end

% end sfuntmpl

%
%=============================================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the S-function.
%=============================================================================
%
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes

%
% call simsizes for a sizes structure, fill it in and convert it to a
% sizes array.
%
% Note that in this example, the values are hard coded.  This is not a
% recommended practice as the characteristics of the block are typically
% defined by the S-function parameters.
%
sizes = simsizes;

sizes.NumContStates  = 2;           %连续变量的个数,配置成连续
sizes.NumDiscStates  = 0;           %离散变量的个数
sizes.NumOutputs     = 2;           %输出个数,
sizes.NumInputs      = 8;           %输入个数,
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;   % at least one sample time is needed

sys = simsizes(sizes);

%
% initialize the initial conditions
%
x0  = [0 0];               %状态变量的初始值

%
% str is always an empty matrix
%
str = [];

%
% initialize the array of sample times
%
ts  = [0 0];            



% Specify the block simStateCompliance. The allowed values are:
%    'UnknownSimState', < The default setting; warn and assume DefaultSimState
%    'DefaultSimState', < Same sim state as a built-in block
%    'HasNoSimState',   < No sim state
%    'DisallowSimState' < Error out when saving or restoring the model sim state
simStateCompliance = 'UnknownSimState';

% end mdlInitializeSizes

%
%=============================================================================
% mdlDerivatives
% Return the derivatives for the continuous states.
%=============================================================================
%
function sys=mdlDerivatives(t,x,u)
                    % R = 2.875;
                    % Ld = 8.5e-3;
                    % Lq = 8.5e-3;
                    % Flux = 0.175;
we = u(3);
R = u(4);
Ld = u(5);
Lq = u(6);
Flux = u(7);

A = [   -R/Ld   we*Lq/Ld;
    -we*Ld/Lq   -R/Lq];
B = [    1/Ld    0;
            0 1/Lq];
C = [        0;
    -we*Flux/Lq];


sys = A*x + B*[u(1);u(2)] + C;


% end mdlDerivatives

%
%=============================================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time step
% requirements.
%=============================================================================
%
function sys=mdlUpdate(t,x,u)

sys = [];
% end mdlUpdate

%
%=============================================================================
% mdlOutputs
% Return the block outputs.
%=============================================================================
%
function sys=mdlOutputs(t,x,u)

sys = [x];

% end mdlOutputs

%
%=============================================================================
% mdlGetTimeOfNextVarHit
% Return the time of the next hit for this block.  Note that the result is
% absolute time.  Note that this function is only used when you specify a
% variable discrete-time sample time [-2 0] in the sample time array in
% mdlInitializeSizes.
%=============================================================================
%
function sys=mdlGetTimeOfNextVarHit(t,x,u)

sampleTime = 1;    %  Example, set the next hit to be one second later.
sys = t + sampleTime;

% end mdlGetTimeOfNextVarHit

%
%=============================================================================
% mdlTerminate
% Perform any end of simulation tasks.
%=============================================================================
%
function sys=mdlTerminate(t,x,u)

sys = [];

% end mdlTerminate

(2)机械方程

image-20210522155019421

function [sys,x0,str,ts,simStateCompliance] = Mechanical_equation_signal_continus(t,x,u,flag)

switch flag,

  %%%%%%%%%%%%%%%%%%
  % Initialization %
  %%%%%%%%%%%%%%%%%%
  case 0,   
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;  %这个函数必须有

  %%%%%%%%%%%%%%%
  % Derivatives %
  %%%%%%%%%%%%%%%
  case 1,
    sys=mdlDerivatives(t,x,u);                              %这个函数可以有

  %%%%%%%%%%
  % Update %
  %%%%%%%%%%
  case 2,
    sys=mdlUpdate(t,x,u);                                   %这个函数可以有

  %%%%%%%%%%%
  % Outputs %
  %%%%%%%%%%%
  case 3,
    sys=mdlOutputs(t,x,u);                                  %这个函数必须有

  %%%%%%%%%%%%%%%%%%%%%%%
  % GetTimeOfNextVarHit %
  %%%%%%%%%%%%%%%%%%%%%%%
  case 4,
    sys=mdlGetTimeOfNextVarHit(t,x,u);

  %%%%%%%%%%%%%
  % Terminate %
  %%%%%%%%%%%%%
  case 9,
    sys=mdlTerminate(t,x,u);

  %%%%%%%%%%%%%%%%%%%%
  % Unexpected flags %
  %%%%%%%%%%%%%%%%%%%%
  otherwise
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));

end

% end sfuntmpl

%
%=============================================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the S-function.
%=============================================================================
%
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes

%
% call simsizes for a sizes structure, fill it in and convert it to a
% sizes array.
%
% Note that in this example, the values are hard coded.  This is not a
% recommended practice as the characteristics of the block are typically
% defined by the S-function parameters.
%
sizes = simsizes;

sizes.NumContStates  = 1;           %连续变量的个数,配置成连续
sizes.NumDiscStates  = 0;           %离散变量的个数
sizes.NumOutputs     = 1;           %输出个数,
sizes.NumInputs      = 4;           %输入个数,
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;   % at least one sample time is needed

sys = simsizes(sizes);

%
% initialize the initial conditions
%
x0  = [0];               %状态变量的初始值

%
% str is always an empty matrix
%
str = [];

%
% initialize the array of sample times
%
ts  = [0 0];            %采样时间,ts = [Ts 0]

% Specify the block simStateCompliance. The allowed values are:
%    'UnknownSimState', < The default setting; warn and assume DefaultSimState
%    'DefaultSimState', < Same sim state as a built-in block
%    'HasNoSimState',   < No sim state
%    'DisallowSimState' < Error out when saving or restoring the model sim state
simStateCompliance = 'UnknownSimState';

% end mdlInitializeSizes

%
%=============================================================================
% mdlDerivatives
% Return the derivatives for the continuous states.
%=============================================================================
%
function sys=mdlDerivatives(t,x,u) 
Te = u(1);
TL = u(2);
J = u(3);
B = u(4);
% J = 0.001;
% B = 0.0008;

sys = (Te - TL - B*x)/J;


% end mdlDerivatives

%
%=============================================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time step
% requirements.
%=============================================================================
%
function sys=mdlUpdate(t,x,u)

sys = [];
% end mdlUpdate

%
%=============================================================================
% mdlOutputs
% Return the block outputs.
%=============================================================================
%
function sys=mdlOutputs(t,x,u)

sys = x;

% end mdlOutputs

%
%=============================================================================
% mdlGetTimeOfNextVarHit
% Return the time of the next hit for this block.  Note that the result is
% absolute time.  Note that this function is only used when you specify a
% variable discrete-time sample time [-2 0] in the sample time array in
% mdlInitializeSizes.
%=============================================================================
%
function sys=mdlGetTimeOfNextVarHit(t,x,u)

sampleTime = 1;    %  Example, set the next hit to be one second later.
sys = t + sampleTime;

% end mdlGetTimeOfNextVarHit

%
%=============================================================================
% mdlTerminate
% Perform any end of simulation tasks.
%=============================================================================
%
function sys=mdlTerminate(t,x,u)

sys = [];

% end mdlTerminate

(3)用两个方程搭建信号模型

image-20210522155324237

image-20210522155347901

两个s-function分别见,

Electrical_equation_signal_continus.m

Mechanical_equation_signal_continus.m

注意以下几个点:

第一个坑:

做多参数输入的时候,电气方程不要输出转矩,会出现以下错误,维度没有错,但就是查不出原因。只能另外求

image-20210522155509197

大概的原因是因为分母为零之类的。比如当我的J,B为0时,得到的错误信息是,

image-20210522155520117

就是除了零导致的,但报的错误仍然是向量长度的问题。

网上的帖子:

image-20210522155532693

输出Te后发现,果然是这个问题,计算结果出现NaN,一般有这样几种情况:0/0,Inf/Inf,Inf-Inf,Inf*0,这几种情况都会导致结果不确定,所以会得到NaN。

image-20210522155546749

第二个坑:

因为反馈线id,iq搞反了,原本稳定的变乱了,查了一晚上,没结果,很影响心情。要及时备份,数据要检查,整理好。

(4)电路模型

image-20210522160018964

在信号模型的基础上,再封装一层即可。

image-20210522155954871

第一个坑:

img
由于自定义的 PMSM 模型属于信号模型,省去了功率部分,故可由正弦信号直接驱动,这就意味着连SVPWM和逆变器都不需要了。但是这好像不合理呀。配合适当的信号增益可表示功率大小。当控制信号采用 SPWM算法时,调制函数为正弦波,可以直接驱动电机模型。对于 SVPWM 算法,相电压的调制信号是马鞍形波[5],不可直接引入电机模型,由于其线电压调制函数是正弦波,故可利用线电压信号驱动自定义模型. ,此时坐标变换[1]需改写成

image-20210522160037413

image-20210522160050061


[1] 参考文献《SIMULINK中PMSM模型的改进及在参数辨识中的应用_王莉娜》

第二个坑:

我们所搭建的pmsm模型是其数学模型,并不是电路模型,其端口电压是通过测量后再输入的。如何人为地将其进行再加工,转换成电路模型呢?

答:用受控电流源将信号模型变为电路模型

image-20210522160107877

电路模型验证:

仿真文件见,Result04_closeloop_inverter_svpwm.slx

image-20210522161103611

image-20210522161211711

image-20210522161243947

image-20210522161308615

声明:案例一使用了B站UP主陈诚电气部分,如有侵权,请及时联系
仿真文件获取:https://download.csdn.net/download/weixin_42362056/18970461

  • 23
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值