返回列表 发帖

[原创] PID算法原理、调试经验以及代码

前言:下班前收到网友的短信,和我说正在做PID的程序,感觉有些困难。我刚好曾经做过PID算法,故将自己以前的论文和代码做了整理,写了这篇文章,希望能够对用到PID调节器的朋友们有所帮助。也希望更多的朋友能够分享你们的经验,因为我们相信成功源于共享。



1。PID原理





2.流程图

3

评分人数

3。PID代码

//定义变量
float Kp;                       //PI调节的比例常数
float Ti;                       //PI调节的积分常数
float T;                        //采样周期
float Ki;
float ek;                       //偏差e[k]
float ek1;                      //偏差e[k-1]
float ek2;                      //偏差e[k-2]
float uk;                       //u[k]
signed int uk1;                 //对u[k]四舍五入取整
signed int adjust;              //调节器输出调整量

//变量初始化
    Kp=4;
    Ti=0。005;
    T=0.001;
// Ki=KpT/Ti=0.8,微分系数Kd=KpTd/T=0.8,Td=0.0002,根据实验调得的结果确定这些参数
    ek=0;
    ek1=0;
    ek2=0;
    uk=0;
    uk1=0;
    adjust=0;

int piadjust(float ek)  //PI调节算法
{
    if( gabs(ek)<0.1 )
    {
       adjust=0;
    }
    else
    {     
       uk=Kp*(ek-ek1)+Ki*ek;  //计算控制增量
       ek1=ek;
      
       uk1=(signed int)uk;
       if(uk>0)
       {
          if(uk-uk1>=0.5)
          {
             uk1=uk1+1;
          }
       }
       if(uk<0)
       {
          if(uk1-uk>=0.5)
          {
             uk1=uk1-1;
          }
       }
       adjust=uk1;   
    }        
   
   
    return adjust;
}

下面是在AD中断程序中调用的代码。
      
       。。。。。。。。。。。
       else //退出软启动后,PID调节,20ms调节一次
           {
              EvaRegs.CMPR3=EvaRegs.CMPR3+piadjust(ek);//误差较小PID调节稳住
              if(EvaRegs.CMPR3>=890)
              {
                 EvaRegs.CMPR3=890; //限制PWM占空比
              }        
           }
        。。。。。。。。。。。。。。。。

4。PID调节经验总结


PID控制器参数选择的方法很多,例如试凑法、临界比例度法、扩充临界比例度法等。但是,对于PID控制而言,参数的选择始终是一件非常烦杂的工作,需要经过不断的调整才能得到较为满意的控制效果。依据经验,一般PID参数确定的步骤如下[42]:
(1)        确定比例系数Kp
确定比例系数Kp时,首先去掉PID的积分项和微分项,可以令Ti=0、Td=0,使之成为
纯比例调节。输入设定为系统允许输出最大值的60%~70%,比例系数Kp由0开始逐渐增大,直至系统出现振荡;再反过来,从此时的比例系数Kp逐渐减小,直至系统振荡消失。记录此时的比例系数Kp,设定PID的比例系数Kp为当前值的60%~70%。
(2)        确定积分时间常数Ti
比例系数Kp确定之后,设定一个较大的积分时间常数Ti,然后逐渐减小Ti,直至系统出现振荡,然后再反过来,逐渐增大Ti,直至系统振荡消失。记录此时的Ti,设定PID的积分时间常数Ti为当前值的150%~180%。
(3)        确定微分时间常数Td
微分时间常数Td一般不用设定,为0即可,此时PID调节转换为PI调节。如果需要设定,则与确定Kp的方法相同,取不振荡时其值的30%。
(4)        系统空载、带载联调
对PID参数进行微调,直到满足性能要求。

上面的实际是PI调节的代码,现附上PID的。
  1. //声明变量

  2. //定义变量
  3. float Kp;                       //PID调节的比例常数
  4. float Ti;                       //PID调节的积分常数
  5. float T;                        //采样周期
  6. float Td;                       //PID调节的微分时间常数
  7. float a0;
  8. float a1;
  9. float a2;

  10. float ek;                       //偏差e[k]
  11. float ek1;                      //偏差e[k-1]
  12. float ek2;                      //偏差e[k-2]
  13. float uk;                       //u[k]
  14. int uk1;                      //对uk四舍五入求整
  15. int adjust;                   //最终输出的调整量

  16. //变量初始化,根据实际情况初始化
  17.     Kp=;
  18.     Ti=;
  19.     T=;
  20.         Td=;   

  21.         a0=Kp*(1+T/Ti+Td/T);
  22.         a1=-Kp*(1+2*Td/T);
  23.         a2=Kp*Td/T;
  24. // Ki=KpT/Ti=0.8,微分系数Kd=KpTd/T=0.8,Td=0.0002,根据实验调得的结果确定这些参数
  25.     ek=0;
  26.     ek1=0;
  27.     ek2=0;
  28.     uk=0;
  29.         uk1=0;
  30.         adjust=0;


  31. int pid(float ek)
  32. {
  33.     if(gabs(ek)<ee) //ee 为误差的阀值,小于这个数值的时候,不做PID调整,避免误差较小时频繁调节引起震荡。ee的值可自己设
  34.         {
  35.                 adjust=0;
  36.         }
  37.     else
  38.         {
  39.                 uk=a0*ek+a1*ek1+a2*ek2;
  40.                 ek2=ek1;
  41.                 ek1=ek;
  42.             uk1=(int)uk;
  43.        
  44.             if(uk>0)
  45.                 {
  46.            if(uk-uk1>=0.5)
  47.                    {
  48.               uk1=uk1+1;
  49.                    }
  50.                 }
  51.        if(uk<0)
  52.            {
  53.           if(uk1-uk>=0.5)
  54.                   {
  55.              uk1=uk1-1;
  56.                   }
  57.            }
  58.          
  59.            adjust=uk1;   
  60.     }
  61.         return adjust;
  62.    
  63. }

  64. float gabs(float ek)
  65. {
  66.         if(ek<0)
  67.         {
  68.                 ek=0-ek;
  69.         }
  70.         return ek;
  71. }
复制代码
1

评分人数

TOP

楼主真是大大大大大大的好人啊!!!!真的是超级感谢你啊!

这篇文章我收下了!!!

不过在下还有一个不情之请,不知道楼主能不能吧PID的程序上传一下撒!

如果不方便的话,也没有关系!我会努力,会加油的!真的是再次谢谢你了!!!

还有其他问题的时候,还要麻烦楼主啊!!!

TOP

PID并不复杂,程序代码我已经写出来了,因为这是整个程序里面的一小段,所以也不好全贴出来了。PID的关键我觉得在于参数的调试,需要不断的做实验,分析,再调整,再做实验,最终选择一组适合自己项目的参数。我自己写过一个PID的仿真软件,不过是用于开关电源中BUCK电路的PID仿真软件,最近整理之后,拿出来给大家,有需要的朋友敬请期待哦,呵呵。
也希望您能够多多支持我们HELLODSP,陪伴我们一起成长!尽自己的力量去帮助更多需要帮助的朋友们

TOP

呵呵,谢谢,版主!
我们期待这你的成果,希望像你这样好心的前辈能有取得更大的成绩,帮助我们。
我会尽自己的努力的,会继续支持HELLODSP的!

TOP

"不过是用于开关电源中BUCK电路的PID仿真软件"

"不过是用于开关电源中BUCK电路的PID仿真软件"
我期待着这个地出现,谢谢楼主

TOP

谢谢分享你的成果
致敬!

TOP

PID仿真软件已经发布了,需要的朋友点击下面的页面去看看吧:

==PID控制器仿真软件【基于BUCK电路】==

TOP

一定仔细研究,谢谢哈

TOP

好帖子,谢谢楼主!!!

TOP

原创!好东东,收藏!

TOP

喜欢经验之谈
!!!!!!!!!!!

TOP

喜欢经验之谈

TOP

感谢楼主,好贴,收藏!

TOP

回复 6# 的帖子

谢谢,得好好研读一下

TOP

好文章,谢谢楼主分享经验。

TOP

支持开源,倡导开源,

TOP

xxxxxxxxxxxxxxxxxx

TOP

呵呵

呵呵,看过,谢了,想起了很久用汇编写了个PI算法,写得老长。

TOP

不够清楚呀。。。。。。。

TOP

太感谢楼主了,这么好的贴了,要拼了老命的顶啊

TOP

赞!希望楼主贴代码(*^__^*) 嘻嘻……

TOP

顶一个,很感谢版主的分享

TOP

感谢楼主
!!!!

TOP

TOP

感谢楼主 正在思考PID的问题

TOP

if(uk>0)
       {
          if(uk-uk1>=0.5)
          {
             uk1=uk1+1;
          }
       }
       if(uk<0)
       {
          if(uk1-uk>=0.5)
          {
             uk1=uk1-1;
          }
       }

这段代码什么意思???请教!!!

TOP

很详细的资料,谢谢。。。

TOP

haohaohaohaohao

TOP

楼主伐的东西真实太好了

TOP

返回列表