加载中…
个人资料
ParkerWu
ParkerWu
  • 博客等级:
  • 博客积分:0
  • 博客访问:28,065
  • 关注人气:44
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
正文 字体大小:

对PLC的PID算法进行仿真2(Matlab)

(2015-12-02 16:46:21)
标签:

pid

仿真

matlab

simulink

      在上一篇文章 对PLC的PID算法进行仿真1(Matlab)  中介绍了Simulink+M函数仿真PID算法的方法,本文将介绍使用Simulink+S函数进行仿真的形式。
      上一篇文章介绍了使用M函数时,会存在一个缺点:即M函数不能被多处调用,而本文将通过使用S函数的形式实现多处调用的目的。
      S函数相对于M函数而言,它有着严格的形式,我们在PID的算法中用到了很多来自上一次的变量结果,考虑到这一点,在S函数中,我们采用离散的形式来编程,其特点就是上一次的状态变量可以迭代到本次使用,这些状态变量都保存在名称为x的矩阵中,先上代码,注释比较详尽:
function [sys,x0,str,ts] = PID_PosExpSFun(t,x,u,flag)
switch flag,
case 0           % initializations
    [sys,x0,str,ts] = mdlInitializeSizes;
case 2           % discrete states updates
    sys = mdlUpdates(x,u);
case 3           % computation of control signal
   sys = mdlOutputs(t,x,u,kp,ki,kd,MTab);
    sys=mdlOutputs(t,x,u);
case {1, 4, 9}   % unused flag values
    sys = [];
otherwise        % error handling
    error(['Unhandled flag = ',num2str(flag)]);

end

%=============================================================================
%初始化参数
function [sys,x0,str,ts]=mdlInitializeSizes

sizes = simsizes;
sizes.NumContStates  = 0;
sizes.NumDiscStates  = 5;%状态变量的数量ek1/integral/lastMV/lastUd/lastPV
sizes.NumOutputs     = 1;%输出数量
sizes.NumInputs      = 3;%输入变量数量
sizes.DirFeedthrough = 1;%输入直接传递到输出
sizes.NumSampleTimes = 1;   % 采样时间数量
sys = simsizes(sizes);

%
% 初始化状态变量
%
x0  = [0; 0; 0;0;0];

str = [];

ts  = [-1 0];  %与输入信号为同样的采样周期

%=============================================================================
%离散状态的更新,表示下一个离散状态,譬如x(k+1)
function sys=mdlUpdates(x,u)
SP=u(1);PV=u(2);%获取输入值
%获取上一次的状态值
ek1=x(1);integral=x(2);lastMV=x(3);lastUd=x(4);lastPV=x(5);
IsHSPID=0; %是否使用不完全微分
IsDSpeed=0; %是否使用变速积分(=1,使用)
IsDGama=0;  %是否使用微分先行算法(=1,采用)
MVH=100;    %输出上限
MVL=-100;      %输出下限
Deadband=0.001;     %死区
Ts=1;         %采样周期
Tf=0.01;         %不完全微分滤波系数(a=Tf/(Ts+Tf))
IUse=60;     %积分分离法中确定偏差值在所属范围内启用积分项
IVar=60;     %变积分控制参数
DGama=10000;    %微分先行系数
switch u(3) %选择调节参数,针对不同波形
       case 1,
            Kp=1;       %比例系数
            Ti=30;     %积分实现
            Td=50;         %微分时间
       case 2,
            Kp=1.5;Ti=280;Td=50;
            
        case 3,
            Kp=1.5;       %比例系数
            Ti=220;     %积分实现
            Td=50;         %微分时间
        case 4,
            Kp=0.6;       %比例系数
            Ti=120;     %积分实现
            Td=60;         %微分时间
        
end
 ek=SP-PV; %当前偏差
    if ek < -Deadband   %死区
          ek = ek + Deadband ;
    elseif ek > Deadband
          ek = ek - Deadband ;
    else
          ek = 0.0 ;  
    end
    %计算比例项
     pterm=Kp*ek;
     %计算积分项               
      if abs(ek)
           %抗积分饱和:当上一次的输出达到饱和后,且偏差朝反方向变化,则可累加积分
            IsISum=(lastMVMVL+0.01)...
                 ||(lastMV>=MVH-0.01 && ek<=0.0)...
                 ||(lastMV<=MVL+0.01 && ek>=0.0);
            if IsISum %抗积分饱和
                 if IsDSpeed  %使用变速积分
                     integral=integral+Kp*Ts*ek*(1-abs(ek)/IVar)/Ti;
                 else
                     integral=integral+Kp*Ts*ek/Ti;
                 end
            end
       else
             integral=0.0;
      end 
       %微分项
     if IsHSPID  %使用不完全微分
          dterm =(ek-ek1)*Kp*Td/(Ts+Tf)+Tf*lastUd/(Ts+Tf);
     elseif IsDGama %采用微分先行算法
         dterm=lastUd*DGama*Td/(DGama*Td+Ts)+PV*(Td+Ts)/(DGama*Td+Ts)...
                        -lastPV*Td/(DGama*Td+Ts);
     else
          dterm=(ek-ek1)*Kp*Td/Ts;
     end
      %计算输出值
     MV=pterm+integral+dterm;
     if MV>MVH  %限幅
           MV=MVH;
     elseif  MV           MV=MVL;
     end
      ek1=ek;  %记录上一次的偏差
      lastMV=MV;%记录上一次的输出值
      lastUd=dterm;%储存上一次的微分项值
      lastPV=PV;%记录上一次的测量值
sys = [ek1;integral;lastMV;lastUd;lastPV];  %将本次的状态变量保存到x矩阵中

%=============================================================================
%输出结果
function sys=mdlOutputs(t,x,u)
sys = x(3); %取出lastMV的值作为输出

然后我们再来配置Simulink,如下图:
对PLC的PID算法进行仿真2(Matlab)

上图有两个Scope输出,这是为了测试S函数被多处调用,是否会造成彼此的影响,经过测试Scope和Scope1输出的波形彼此完全独立,没有互相影响,至于Simulink中的参数设置和前一篇博文中的设置一致,这里仅把S函数的参数设置截图列出来:
对PLC的PID算法进行仿真2(Matlab)

如上图,只是设置了S函数的名称而已。

最后提出一个疑问:前一篇文章介绍的M函数和本文介绍的S函数在PID的控制逻辑和参数设置上一样,但他们的P/I/D三个参数却不同,换言至,两函数如果使用同一P/I/D参数,则他们输出的波形是不同的,也就是说这两个函数是不等价的,这点请高手来分析一下。
      为了验证究竟是S函数与其他方式更接近还是M函数的方式更接近,这里用内置的连续微积分块构造基本的PID,并设置他们的输入波形均为相同的正玄波,在S函数中的Kp/Ti/Td/Ts分别为1/30/50/1,则对应的基本PID的参数为1/0.0333/50,其Simulink配置图如下:
对PLC的PID算法进行仿真2(Matlab)
它们都在同一个模型空间,也即仿真参数也完全一样,最后查看波形,两者生成的波形完全一致,因此暂时认为S函数的PID仿真方式更准确一些。




0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有