PID调节是有方法、有规律可循的,不过在此之前先深入理解其公式。
别怕,先看认真看PID本体:
其中:
u(t) -------------输出曲线,pid输出值随时间的变化曲线
Kp --------------比例系数
e(t)------------- 偏差曲线,设定值与实际值的偏差随时间的变化曲线
Ti--------------- 积分时间
Td--------------微分时间
先来慢慢看上面的式子,我们发现式子中有一个Kp(比例系数)在括号外,我们把它乘进去:
这就是位置式PID的模拟表达式,此外还有一种增量式PID,两则区别是:
位置式PID算的是当前控制系统应该输出的值,增量式PID算的是当前控制系统该输出值的变化值。
比如,当前输出是40,位置式PID算出48,那么输出就变为48,增量式PID算出8,拿输出就是40+8=48。
比例P,积分I,微分D就是我们要找到的参数。如果调节周期是定的,那么上方的比例P,积分I,微分D就是定值,
接着我们要做的事情就是这三个参数找出来。
如果你学过高数且上课没有睡觉,就很容易知道:
是求时间0到时间t,偏差曲线e(t)与X轴围起来的面积值的代数和,
求偏差曲线e(t)的斜率,
结合上面的我们可以得到:
结合调解曲线来看,
偏差=设定值-实际值,因此偏差曲线e(t)=SET-实际值曲线,也就是实际值曲线的x轴向上平移SET便是误差曲线e(t)。
根据高等数学的知识我们可以知道,在曲线SET下围成的面积为正的,在上面围成的面积为负的,即:面积A和面积C符号为正面积B符号为负,假设P、I、D都不为零,且都大于零。
比例项 积分项 微分项 输出 被调量结果
当0<t<T1时: 偏差>0, 正大 ,斜率绝对值变大,且>0, 慢慢变大 快速靠近设定值
当T1<t<T2时: 偏差<0, 减小 ,斜率绝对值变小,且>0,
当T2<t<T3时: 偏差<0, 减小 ,斜率绝对值变大,且<0,
可以发现:
比例项是纠正偏差的主力,越远离偏差绝对值就越大,快速把偏差纠正回来。
积分项和以往的状态有关,面积的绝对值越大它的绝对值就越大,它的作用是消除累计偏差。
微分项跟斜率有关,比较难解释,总的来说它的作用是:当目标靠近设定值时加速它靠近,当目标远离设定值时阻止它远离。因此微分可以增加系统稳定性,因为到达目的之后,离开会受到阻碍。
PID公式离散化
因为实际应用中我们用到的都是离散的数据,因此对PID进行编程之前我们得先把模拟公式转换成离散公式。
其实就是把积分求面积、微分求斜率的方法换成离散的求面积和斜率的方法,离散转换后:
其中:
u(t) -------------输出曲线,pid输出值随时间的变化曲线
Kp --------------比例系数
e(t)------------- 偏差曲线,设定值与实际值的偏差随时间的变化曲线
Ti--------------- 积分时间
Td--------------微分时间
T----------------调节周期
转换后我们发现我们需要整定的三个参数变为:
多了个调节周期T,
因此需要注意的是:必须使T为定值,或者变化小到可以忽略
这样P、I、D才是固定常数,才可能调节
PID编程
网上有很多编程代码,只要理解了pid公式各个参数的意义,就可以理解别人的程序。这里直接给出我的程序:
/*******************************************************************
位置式pid
********************************************************************/
double PID(double Actual,double SET)
{
static double E_sum,Error_last; //上一次误差
double kp=20.767,ki=1.867,kd=115.55;
double pid_out;
double Error_now; //当前误差
Error_now = SET-Actual; //当前误差
// if(Error_now>-0.9&&Error_now<0.9) //防静态误差
// {
// Error_now=0;
// Error_last=0;
// }
E_sum += Error_now; //误差累计
// if(E_sum>484)E_sum=484; //积分限幅度,防止积分饱和
// if(E_sum<-484)E_sum=-484;
pid_out= kp * Error_now + ki * E_sum + kd * (Error_now-Error_last); //pid计算公式
Error_last=Error_now;
// if(pid>900) pid=900; //输出限幅
// if(pid<-900)pid=-900;
return -pid_out;
}
增量式PID有点难理解,等后面了解了再补充