打印

PID调试出了问题?

[复制链接]
2471|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zjucsd|  楼主 | 2010-11-22 11:10 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本人在对仪器进行调试的过程中,发现六个工位中的PID调节第一个出现了错误。在距离设定值还有20℃之间时,PID调节中占空比总会出现两、三个错误的数据。比如设定值为150℃时,当到达148.1℃时,其余工位的PWM为70左右,而第一工位的占空比却出现了几次200。等到温度到达设定值进行调节乃至稳定的过程中,PWM又不会出现任何错误。
      请各位老大帮忙分析分析!(附程序代码)

void Adjust(uchar temp)
{
   uint setpoint,nextpoint;
   uint com;
   setpoint = 0;
   nextpoint = 0;
   com = 0;
//设定值整数部分
//   setpoint = (Para[2*temp] >> 4) * 100 + (Para[2*temp] & 0x0f) * 10 + (Para[2*temp+1] >> 4);
//   setpoint = setpoint * 10;
   setpoint  = (Para[2*temp] >> 4) * 1000;
   setpoint += (Para[2*temp] & 0x0f) * 100;
   setpoint += (Para[2*temp+1] >> 4) * 10;
   setpoint += (Para[2*temp+1] & 0x0f);
//当前温度值整数部分
//   nextpoint = (Results[2*temp] >> 4) *100 + (Results[2*temp] & 0x0f) *10 +(Results[(2*temp)+1] >> 4);
//   nextpoint = nextpoint * 10;
   nextpoint  = (Results[2*temp] >> 4) *1000;
   nextpoint += (Results[2*temp] & 0x0f) *100;
   nextpoint += (Results[(2*temp)+1] >> 4) * 10;
   nextpoint += (Results[(2*temp)+1] & 0x0f);

   if(setpoint > nextpoint)
   {
      com = setpoint - nextpoint;
   if(com > 200)
   {
   PWM[temp] = 200;
   }
   else
   {
   PWM[temp] = PIDCalc(setpoint,nextpoint,temp);
      }
   }
   else      
   {
      com = nextpoint - setpoint;
   if(com > 200)
   {
      PWM[temp] = 0;
   }
   else
   {
         PWM[temp] = PIDCalc(setpoint,nextpoint,temp);
   }
   }
}
/*-----------------------------------------------------------------------
【名称】 uchar PIDCalc(uint setpoint,uint nextpoint,uchar temp)
-----------------------------------------------------------------------*/
uchar PIDCalc(uint setpoint,uint nextpoint,uchar temp)
{
   static int  idata Error = 0;
   static int  idata dError = 0;
   int  idata freecont = 15000;
   uchar idata com = 0;
   uchar idata i;
//pid算法部分
   if(setpoint < 1300)      i = 0;
   else if(setpoint < 1650) i = 1;
   else if(setpoint < 1900) i = 2;
   else if(setpoint < 2050) i = 3;
   else                     i = 4;
   
   Error = (int)(setpoint - nextpoint) ;
   SumError[temp] = (int)(SumError[temp] + Error);
   dError = (int)(lasrError[temp] - PrevError[temp]);
   PrevError[temp] = lasrError[temp];
   lasrError[temp] = Error;
   freecont += (int)(Error * KPConst[i]);
   
   freecont += (int)(SumError[temp] * KIConst[i]);
   freecont += (int)(dError * KDConst[i]);
   if(freecont <= 15000)
   {
      com = 0;
   }
   else if(freecont > 15200)
   {
      com = 200;
   }
   else
   {
      com = (freecont - 15000) & 0xff;
   }
   return (com);
}

相关帖子

沙发
zjucsd|  楼主 | 2010-11-22 13:59 | 只看该作者
附PWM图片。
图二中粉红色线是正确的PWM线,图一中粉红色线条出现了一两处错误,但不影响调节结果。
图一中的蓝色线条是第一工位的PWM线,虽出现了多处的错误,但调节过程中并不过冲。但是在图二中,蓝色线条就出现了问题,使得温度过冲了3℃以上。
说明:图一是调节至150℃,图二是调节至200℃。

图片1.jpg (18.62 KB )

图片1.jpg

图片2.jpg (19.31 KB )

图片2.jpg

使用特权

评论回复
板凳
chunyang| | 2010-11-22 14:04 | 只看该作者
你的算法有问题,PID不是那么简单的可用如此少的代码来正确表达。

使用特权

评论回复
地板
zjucsd|  楼主 | 2010-11-22 14:05 | 只看该作者
春阳大哥,能不能说明白一点!

使用特权

评论回复
5
chunyang| | 2010-11-22 14:26 | 只看该作者
不可能去读你的代码,我只能说你的代码不可能正确,即使能工作,也不是PID,建议你还是先搞清楚PID算法原理及其量化表达方法,比例、微分、积分环节的参数设定也要合理,温控系统往往带有大滞后,算法整定是很讲究工艺的。

使用特权

评论回复
6
jianghehupo| | 2010-11-29 08:59 | 只看该作者
chunyang能给出一个简单的例子吗

使用特权

评论回复
7
zhaoyu2005| | 2010-11-29 09:18 | 只看该作者
而第一工位的占空比却出现了几次200。
占空比还能出现200?

使用特权

评论回复
8
mmax| | 2010-11-29 11:21 | 只看该作者
既然是PID
你的P是多少?
你的I是多少?
你的D是多少?

不子自整定的话,这几个参数都是要调出来的。

不能随手设一个就让温控快速准确。

使用特权

评论回复
9
mmax| | 2010-11-29 11:25 | 只看该作者
本帖最后由 mmax 于 2010-11-29 11:27 编辑

呵呵,送你一个武林秘籍的口诀:
参数整定找最佳,从小到大顺序查
先是比例后积分,最后再把微分加
曲线振荡很频繁,比例度盘要放大
曲线漂浮绕大湾,比例度盘往小扳
曲线偏离回复慢,积分时间往下降
曲线波动周期长,积分时间再加长
曲线振荡频率快,先把微分降下来
动差大来波动慢。微分时间应加长
理想曲线两个波,前高后低4 比1
一看二调多分析,调节质量不会低

使用特权

评论回复
10
xusnwise| | 2010-11-29 15:41 | 只看该作者
春阳老师。PID到底该怎么表达啊。
我做的PID也是就一句代码啊
我也贴上来大家拍我, 很拍,我的就一句话。 看来我还不懂PID
typedef        struct
{
        int kp;  
        int ki;
        int kd;
        int      errV;
        int      curV;
        int      lastV;       
        uint32_t PIDMax;
        uint32_t PIDMin;
} Motor_PID;

uint32_t        Calc_PIDOut(void)
{
        int        pid_out;       
       
        pid_out     = v_pid.kp*(SetV - v_pid.curV) + v_pid.ki*( SetV - v_pid.curV) +\
                                  v_pid.kd*(v_pid.curV-v_pid.lastV);

        v_pid.lastV  = v_pid.curV;
   
               return  pid_out
}

到底什么才是真正的PID呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

100

主题

351

帖子

3

粉丝