搜索
bottom↓
回复: 31

浅谈-非线性预测式负反馈控制(温控)

  [复制链接]

出0入0汤圆

发表于 2012-10-12 19:25:57 | 显示全部楼层 |阅读模式
本帖最后由 coleyao 于 2012-10-12 19:29 编辑

  以前我曾经在论坛上讨论过预测式负反馈控制,那时的看法是线性预测各方面都优于非线性预测,似乎非线性预测没有必要使用。前一阵子折腾了一阵,作了一个改进型预测式负反馈控制算法的效果仿真(使用非线性预测),结果却意外的发现,在系统参数相同的情况下,经过精心调整的非线性预测负反馈系统的稳态精度要高于线性预测负反馈系统,差不多稳态精度能提高一倍的样子,如图所示(两种算法针对环境温度波动的干扰都已作了最大优化),这另一方面似乎也说明了PID控制中的D分量不是可有可无的!
  另外说一句,之前好像有人提到我写的建议温控算法仿真软件在WIN7下不能使用,看起来不是这样,我的附图就是在Win7Home 普通版下截取的!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-12-9 20:06:23 | 显示全部楼层
一值注意楼主的这个理论,“非线性预测”它的相应的公式吗?或是算法,谢谢!

出0入0汤圆

发表于 2012-12-9 20:08:12 | 显示全部楼层
Pref_adv能给个算法参考试下吗?

出0入0汤圆

发表于 2012-12-9 20:13:15 | 显示全部楼层
期待下文呢

出0入0汤圆

 楼主| 发表于 2012-12-10 06:04:56 | 显示全部楼层
本帖最后由 coleyao 于 2012-12-10 11:21 编辑
YOU1 发表于 2012-12-9 20:13
期待下文呢


呵呵,线性预测的公式是 ERRTadj=FdK*(ERRT+PreK*vT);也就是对ERRT作了一定程度的预测,预测深度是PreK;
   非线性预测的公式是ERRTadj=FdK*(ERRT+PreK*vTadj); 也就是说不光根据ERRT的速度vT来调整,同时对vT作一定程度的预测,预测深度为PreK',根据预测后的vT对预测的ERRT进行修正,也即双重预测。
其实非线性预测不是所有时候都优于线性预测的,只是某些场合,它确实效果要优于线性预测,原因是它对速度vT作了一定的修正(本来vT就不是常量,所以理论上修正过的vT更合理)。
当然了,具体的效果有心的网友可以自己验证一下,我就不再举例了!

出0入0汤圆

 楼主| 发表于 2012-12-10 06:28:50 | 显示全部楼层
个人觉得预测式负反馈才是原先的所谓PID算法的精髓所在,因此原先写过一篇名为“让PID成为历史”的帖子,点击量那是刚刚的啊,可是最终还是觉得有点太张扬了,把帖子名字改掉了

出0入0汤圆

 楼主| 发表于 2012-12-10 08:18:40 | 显示全部楼层
呵呵,控制如人生啊!预测得少了,容易振荡,总是与目标插肩而过,抓不住目标;预测得多了,事事都考虑到了,又会导致增速缓慢,达到目标的时间太长了!

出0入0汤圆

发表于 2012-12-10 11:22:34 | 显示全部楼层

呵呵,控制如人生啊!预测得少了,容易振荡,总是与目标插肩而过,抓不住目标;预测得多了,事事都考虑到了,又会导致增速缓慢,达到目标的时间太长了!
//---------------------------------------------------------

经典

出0入0汤圆

发表于 2012-12-10 11:41:56 | 显示全部楼层
非线性预测的公式是ERRTadj=FdK*(ERRT+PreK*vTadj); 其中vTadj=vT+PreK' *aT,也就是说不光根据ERRT的速度vT来调整,同时对vT作一定程度的预测,预测深度为PreK',根据预测后的vT对预测的ERRT进行修正,也即双重预测
//--------------------------------------------------------------------------------------------------


受益非浅!

出0入0汤圆

 楼主| 发表于 2012-12-10 11:51:31 | 显示全部楼层
eddia2012 发表于 2012-12-10 11:41
非线性预测的公式是ERRTadj=FdK*(ERRT+PreK*vTadj); 其中vTadj=vT+PreK' *aT,也就是说不光根据ERRT的速 ...

其实vTadj=vT+PreK' *aT可以根据需要来简化处理,简化之后变成了vTadj=(m+1)*vT-m*vT_Last。
  呵呵,很有趣的公式,未来=现在-过去  

出0入0汤圆

发表于 2012-12-10 12:12:39 | 显示全部楼层
这个是精确温度控制,可惜没有实例程序!!!

出0入0汤圆

 楼主| 发表于 2012-12-10 12:27:01 | 显示全部楼层
liudaolunhui 发表于 2012-12-10 12:12
这个是精确温度控制,可惜没有实例程序!!!

不仅是精确温度控制,而且应该是个很容易掌握的控制方式,我现在已经基本上可以做到参数自整定了,不过只是用仿真软件进行了验证,没有严格上产品验证!

出0入0汤圆

发表于 2012-12-10 12:29:54 | 显示全部楼层
恩!!!!!

出0入0汤圆

发表于 2012-12-10 14:54:51 | 显示全部楼层
能写出这么好的东西很不错了,希望好贴顶起来!

阿莫老大能否给Cool  !

出0入0汤圆

发表于 2012-12-10 14:56:26 | 显示全部楼层
楼主要是有一个实例就好了,呵呵

出0入0汤圆

 楼主| 发表于 2012-12-10 18:35:51 | 显示全部楼层
//实例,三路预测式负反馈控温,1片89S52,注释没那么详细,大家就将就看吧
//-------------------定时中断5,使用定时器2-----------------------
void int_time_st(void) interrupt 5   using 1       // 31.25ms timer
{
          CountT++;
          if(CountT>159) { CountT=0;   }
          TF2=0;
}  
void HeatControlPre(void)
  {
           static unsigned int CountHeat,MaxCounHeat,pPhPWM=9000;     //以5秒为周期的计数器及计数最大值,当前pwm指针
           static uint idata Last_temPT[5],vPT,ErrorPT,EPT_adj;       //前5秒内记忆的温度数据(每一秒一个数据),温升速率,温度偏差,调整后的温度偏差
           static uchar plvPT,plErrorPT,plEPT_adj,kP_Pre=0;           //温升速率正负,温度偏差正负,调整后的温度偏差正负,预测k系数
           static uint idata pHhPWM=100,Last_temHT[5],vHT,ErrorHT,EHT_adj;
           static uchar plvHT,plErrorHT,plEHT_adj,kH_Pre=0;
           static uint idata pKhPWM=100,Last_temKT[5],vKT,ErrorKT,EKT_adj;
           static uchar plvKT,plErrorKT,plEKT_adj,kK_Pre=0;
           if(PHToDeal)   
                   {
          PHToDeal=0;  SetPT&=0xfff0;   SetPT|=0x08;
                       if((CountHeat>1000)&&((CountT>>5)==4))  { MaxCounHeat=CountHeat;  CountHeat=0; }
          if(temPT>SetPT) { ErrorPT=temPT-SetPT; plErrorPT=1; }  else {ErrorPT=SetPT-temPT; plErrorPT=0;}
          if(temPT>Last_temPT[CountT>>5]) { vPT=temPT-Last_temPT[CountT>>5]; plvPT=1; } else { vPT=Last_temPT[CountT>>5]-temPT; plvPT=0;}
                     if(plErrorPT)  
                            {
                                     if(plvPT) {  EPT_adj=kP_Pre*vPT+ErrorPT; plEPT_adj=1; }
                                       else   {  
                                                       if(ErrorPT>(kP_Pre*vPT))   { EPT_adj=ErrorPT-kP_Pre*vPT; plEPT_adj=1; }   
                                                               else  {   EPT_adj=kP_Pre*vPT-ErrorPT; plEPT_adj=0;       }  
                                                    }
                            }
              else
                     {
                                     if(plvPT==0) {  EPT_adj=kP_Pre*vPT+ErrorPT; plEPT_adj=0; }
                                       else   {  
                                                       if(ErrorPT>(kP_Pre*vPT))   { EPT_adj=ErrorPT-kP_Pre*vPT; plEPT_adj=0; }   
                                                               else  {   EPT_adj=kP_Pre*vPT-ErrorPT; plEPT_adj=1;       }  
                                                    }  
                     }
                                  
              if(plEPT_adj)  //re
                       {
                                        if((pPhPWM+(EPT_adj>>2))<MaxCounHeat)   pPhPWM+=((EPT_adj>>2));
                       }
                       else      
                               {
                                  if(pPhPWM>((EPT_adj>>2))) pPhPWM-=((EPT_adj>>2));
                               }
              Last_temPT[CountT>>5]=temPT;
              if(80>(EPT_adj>>2))  kP_Pre=82-(EPT_adj>>2);
                   }
           if(HHToDeal)   
                   {
          HHToDeal=0;   SetHT&=0xfff0;   SetHT|=0x08;
                     //  if(CountT==1)  { MaxCounHeat=CountHeat;  CountHeat=0; }
          if(temHT>SetHT) { ErrorHT=temHT-SetHT; plErrorHT=1; }  else {ErrorHT=SetHT-temHT; plErrorHT=0;}
          if(temHT>Last_temHT[CountT>>5]) { vHT=temHT-Last_temHT[CountT>>5]; plvHT=1; } else { vHT=Last_temHT[CountT>>5]-temHT; plvHT=0;}
                     if(plErrorHT)  
                            {
                                     if(plvHT) {  EHT_adj=kH_Pre*vHT+ErrorHT; plEHT_adj=1; }
                                       else   {  
                                                       if(ErrorHT>(kH_Pre*vHT))   { EHT_adj=ErrorHT-kH_Pre*vHT; plEHT_adj=1; }   
                                                               else  {   EHT_adj=kH_Pre*vHT-ErrorHT; plEHT_adj=0;       }  
                                                    }
                            }
              else
                     {
                                     if(plvHT==0) {  EHT_adj=kH_Pre*vHT+ErrorHT; plEHT_adj=0; }
                                       else   {  
                                                       if(ErrorHT>(kH_Pre*vHT))   { EHT_adj=ErrorHT-kH_Pre*vHT; plEHT_adj=0; }   
                                                               else  {   EHT_adj=kH_Pre*vHT-ErrorHT; plEHT_adj=1;       }  
                                                    }  
                     }
                                  
              if(plEHT_adj)  //re
                       {
                                        if((pHhPWM+(EHT_adj>>1))<MaxCounHeat)   pHhPWM+=((EHT_adj>>1));
                       }
                       else      
                               {
                                  if(pHhPWM>((EHT_adj>>1))) pHhPWM-=((EHT_adj>>1));
                               }
              Last_temHT[CountT>>5]=temHT;
              if(40>(EHT_adj>>3))  kH_Pre=50-(EHT_adj>>3);
                   }
           if(KHToDeal)   
                   {
          KHToDeal=0;  SetKT&=0xfff0;   SetKT|=0x08;
                    //   if(CountT==1)  { MaxCounHeat=CountHeat;  CountHeat=0; }
          if(temKT>SetKT) { ErrorKT=temKT-SetKT; plErrorKT=1; }  else {ErrorKT=SetKT-temKT; plErrorKT=0;}
          if(temKT>Last_temKT[CountT>>5]) { vKT=temKT-Last_temKT[CountT>>5]; plvKT=1; } else { vKT=Last_temKT[CountT>>5]-temKT; plvKT=0;}
                     if(plErrorKT)  
                            {
                                     if(plvKT) {  EKT_adj=kK_Pre*vKT+ErrorKT; plEKT_adj=1; }
                                       else   {  
                                                       if(ErrorKT>(kK_Pre*vKT))   { EKT_adj=ErrorKT-kK_Pre*vKT; plEKT_adj=1; }   
                                                               else  {   EKT_adj=kK_Pre*vKT-ErrorKT; plEKT_adj=0;       }  
                                                    }
                            }
              else
                     {
                                     if(plvKT==0) {  EKT_adj=kK_Pre*vKT+ErrorKT; plEKT_adj=0; }
                                       else   {  
                                                       if(ErrorKT>(kK_Pre*vKT))   { EKT_adj=ErrorKT-kK_Pre*vKT; plEKT_adj=0; }   
                                                               else  {   EKT_adj=kK_Pre*vKT-ErrorKT; plEKT_adj=1;       }  
                                                    }  
                     }
                                  
              if(plEKT_adj)  //re
                       {
                                        if((pKhPWM+(EKT_adj)>>1)<MaxCounHeat)   pKhPWM+=((EKT_adj)>>1);
                       }
                       else      
                               {
                                  if(pKhPWM>((EKT_adj)>>1)) pKhPWM-=((EKT_adj)>>1);
                               }
              Last_temKT[CountT>>5]=temKT;
              if(40>(EKT_adj)>>3)  kK_Pre=(40-(EKT_adj>>3));
                   }
                  
           if((CountHeat>pPhPWM)&&(temPT<0x5D0)) PHeaterOn;
                    else if(CountHeat<pPhPWM) PHeaterOff;
           if((CountHeat>pHhPWM)&&(temHT<0x5D0)) HHeaterOn;
                    else if(CountHeat<pHhPWM) HHeaterOff;
           if((CountHeat>pKhPWM)&&(temKT<0x5D0)) KHeaterOn;
                    else if(CountHeat<pKhPWM) KHeaterOff;
     CountHeat++;  
  }

main()
{
    uchar idata temk;
           SP=0x4F;
           InitSys();
           while(1)
             {
                     if(setitem==0)
                             {
                         Ttick=CountT;
                        temk=GetKey();
                         switch(temk)
                          {
                                  case    NoKeyPressed:          nop;                                          break;
                                  case    KeySetPressed:       { setitem=1;                              }     break;
                                  case    KeyHeatPressed:      { if(Heating)  Heating=0; else Heating=1; }     break;
                            case    KeyUpPressed:        { PassWordCnt++; }                              break;                                    
                                  case    KeyDnPressed:        { PwDeal();      }                              break;
                                  case    KeySetLasted:        { setitem=4;                              }     break;
                            case    KeyHeatLasted:         nop;                                          break;
                                  case    KeyUpLasted:         { setitem=6;                              }     break;                                              
                                  case    KeyDnLasted:         { setitem=5;                              }     break;       
                                             case    KeyRollPressed:      { TankSel++;   if(TankSel>2)  TankSel=0;  }     break;
                                  case    KeyMultiPressed:       nop;                                          break;                                              
                                  default  :   nop;     break;                       
                          }
                         SetMenuDeal();         
                         RefreshSegLed();
                  if(TankSel==0) { ShowT(temPT);  BLedPiaoOff=0; BLedHongOff=1; BLedKaoOff=1; }
                              if(TankSel==1) { ShowT(temKT);  BLedPiaoOff=1; BLedHongOff=0; BLedKaoOff=1; }
                              if(TankSel==2) { ShowT(temHT);  BLedPiaoOff=1; BLedHongOff=1; BLedKaoOff=0; }
                  Ttick_cmp=Ttick;
          }
         else BLedTestOff=1;
         if((setitem>0)&&(setitem<4))   SetMenuDeal();       
         if(setitem==4)          ShowVerMenu();               
         if(setitem==5)          RuntimeMenu();       
         if(setitem==6)                 ErrorRocMenu();
         HeatDeal();
                ErrorDeal();
             }
    nop;
}

出0入0汤圆

发表于 2012-12-10 20:02:25 | 显示全部楼层
cool呵!

出0入0汤圆

发表于 2012-12-10 20:06:01 | 显示全部楼层
非常难得的资料,像这样的有实例有理论的东西,
请莫老大给条裤子!!!

出0入0汤圆

发表于 2012-12-10 20:10:29 | 显示全部楼层
coleyao 发表于 2012-12-10 06:28
个人觉得预测式负反馈才是原先的所谓PID算法的精髓所在,因此原先写过一篇名为“让PID成为历史”的帖子,点 ...

现在有那个帖子的链接吗,想瞧瞧

出0入12汤圆

发表于 2012-12-10 20:20:10 | 显示全部楼层
ding

出0入0汤圆

 楼主| 发表于 2012-12-10 20:45:31 | 显示全部楼层
YOU1 发表于 2012-12-10 20:10
现在有那个帖子的链接吗,想瞧瞧

在论坛左侧把鼠标停留在要查看资料的作者图标上,点开那个小图标“详细资料”,然后查看主题,就可以看到所有该作者发的帖子了!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-12-11 01:02:48 | 显示全部楼层
谢谢ColeYao的无私奉献!
参数自整定和最大温升速率相关之间很难整,没有找到最合适的关系. 10度/M---1度/6S,时间已知,功率已知,那么上升1度的热能就知道了,但将热能和温度拉上关系会很麻烦,因为要涉及到比热. 通过仿真软件的学习,以及楼主提供的资料, 温差和功率之间存在着不明不白的关系(是指超调后)!我觉得超过设置线,仿真软件似乎是按时间值回调功率值的?!如果按温差,e(t)>0后,变化0.1或1度,如何知道该回调多少功率呢?!   
有些场合,往往要求第一次必须超调(融化的快些) 楼主提供的代码或许有答案(太晚了,明天看).  

出0入0汤圆

 楼主| 发表于 2012-12-11 07:48:12 来自手机 | 显示全部楼层
Qhjh 发表于 2012-12-11 01:02
谢谢ColeYao的无私奉献!
参数自整定和最大温升速率相关之间很难整,没有找到最合适的关系. 10度/M---1度/6S, ...

—般不采用超调的方式,通常设—个预热期,预热温度会比设定温度略高,时间可单独设置,采用超调方式有点难兼故每—个指标的。

出0入0汤圆

发表于 2012-12-12 14:12:19 | 显示全部楼层
coleyao 发表于 2012-12-10 20:45
在论坛左侧把鼠标停留在要查看资料的作者图标上,点开那个小图标“详细资料”,然后查看主题,就可以看到 ...

找到了谢谢 ,菜鸟学习一下

出0入0汤圆

发表于 2012-12-18 08:49:35 | 显示全部楼层
谢谢ColeYao的无私奉献!
不知您的代码中两个系数PreK等是怎么测出来的?

出0入0汤圆

发表于 2014-2-10 09:29:22 | 显示全部楼层
coleyao
谢谢了 正在做一个温控的东西 可以尝试用pid的方式

出0入0汤圆

发表于 2015-8-21 01:14:30 | 显示全部楼层
收藏,最近在做温控系统,滞后很严重。希望能用楼主的算法成功。

出0入0汤圆

发表于 2015-12-17 12:48:12 | 显示全部楼层
最近正在学习电机控制恒速, 讲解很直观. 多谢分享

出0入0汤圆

发表于 2020-3-27 09:40:07 | 显示全部楼层
coleyao 发表于 2012-12-10 06:04
呵呵,线性预测的公式是 ERRTadj=FdK*(ERRT+PreK*vT);也就是对ERRT作了一定程度的预测,预测深度是PreK; ...

自整定的控制算法能指教一下嘛?

出0入0汤圆

发表于 2020-3-27 22:29:07 | 显示全部楼层
学习学习啊 学习啊学习啊

出0入0汤圆

发表于 2020-3-28 20:22:30 | 显示全部楼层
chinaboy25 发表于 2020-3-27 09:40
自整定的控制算法能指教一下嘛?

真的很难找啊!这个自整定PID。

出0入0汤圆

发表于 2020-5-7 14:15:21 | 显示全部楼层
学习一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-30 01:05

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表