PID算法是一种具有预见性的控制算法,其核心思想是:
1>. PID算法不但考虑控制对象的当前状态值(现在状态),而且还考虑控制对象过去一段时间的状态值(历史状态)和最近一段时间的状态值变化(预期),由这3方面共同决定当前的输出控制信号;
2>.PID控制算法的运算结果是一个数,利用这个数来控制被控对象在多种工作状态(比如加热器的多种功率,阀门的多种开度等)工作,一般输出形式为PWM,基本上满足了按需输出控制信号,根据情况随时改变输出的目的。
比例控制是一种最简单的控制方式。其控制器的输出与输入误差信号成比例关系。当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
设某控制系统:用户设定值为SV(也就是希望通过PID控制算法使被控制对象的状态值保持在SV的附件)。
1>从系统投入运行开始,控制算法每隔一段时间对被控制对象的状态值进行采样。由此,可得到开机以来由各个采样时间点被控制对象的状态值所形成的数据序列:
X1,X2, X3, X4, … Xk-2,Xk-1,Xk
说明:
X1:开机以来的第一次采样值
Xk: 目前的采样值(最近一次的采样值)
2>从这个采样值序列中提取出三方面信息:
①当前采样值Xk与用户设定值SV之间的差值:Ek
Ek =Sk-Xk
分析Ek:
Ek>0:说明当前状态值未达标
Ek=0:说明当前控制状态值正好满足要求
Ek<0:说明当前状态值已经超标
结论:Ek反应了控制对象当前值与设定值的偏差程度,可以根据Ek的大小对输出信号OUT进行调整:偏差程度大OUT增大,偏差程度小OUT减小。即输出信号的强弱与当前偏差程度的大小成比例,所以根据Ek的大小来给出控制信号OUT的当前值的算法称为比例控制(Proportion)。用数学模型可以表示为:
POUT=(Kp*Ek)+Out0
Kp:一般称之为比例系数,可以理解为硬件上的放大器(或衰减器),适当选取Kp将当前误差值Ek
按一定的增益放大或缩小,以提高控制算法的相应速度。
Out0:是一个常数,目的是为了当Ek为0时,确保输出信号不为0,以不至于在当前值与设定值相等时控制器输出信号OUT为0,系统处于无控制信号的失控状态。
PID控制器中的积分对应于图1中误差曲线 与坐标轴包围的面积(图中的灰色部分)。PID控制程序是周期性执行的,执行的周期称为采样周期。计算机的程序用图1中各矩形面积之和来近似精确的积分,图中的TS就是采样周期。
Sk=E1+E2+E3+…+Ek-2+Ek-1+Ek
分析Sk:
Sk>0:过去大多数时候未达标
Sk=0:过去控制效果较理想
Sk<0:过去大多数时候已经超标
结论:1.通过对Sk的分析,可以对控制算法过去的控制效果进行综合评估。体现了控制算法按照原来的方式输出的控制信号导致了现在的控制结果,所以应该利用这个值来对当前要输出的控制信号OUT进行修正,以确保控制对象会在将来的一小段时间尽快达到用户设定的值。
2.Sk实际上是过去每个时间点的误差相加,与数学上的定积分运算类似,因此根据Sk对输出信号进行调节的算法称积分(integral)算法。所以积分控制的数学模型为:
IOUT = Kp*Sk+Out0
Kp是一常数,其目的类似硬件上的放大器,用于将Sk放大或衰减;
Out0是一常数,为了在历史积分偏差值为0时确保系统有一个输出值,避免失控;
误差的微分就是误差的变化速率,误差变化越快,其微分绝对值越大。误差增大时,其微分为正;误差减小时,其微分为负。控制器输出量的微分部分与误差的微分成正比,反映了被控量变化的趋势。
有经验的操作人员在温度上升过快,但是尚未达到设定值时,根据温度变化的趋势,预感到温度将会超过设定值,出现超调。于是调节电位器的转角,提前减小加热的电流。这相当于士兵射击远方的移动目标时,考虑到子弹运动的时间,需要一定的提前量一样。
Dk=Ek-Ek-1
说明:
Ek:当前的偏差
Ek-1: 基于当前的前一个采样时刻的偏差值(即上一次的偏差值);
分析Dk:
Dk>0:说明从上一采样时刻到当前误差有增大趋势
Dk=0:说明从上一采样时刻到当前误差平稳
Dk<0:说明从上一采样时刻到当前误差有减小趋势
Dk>0 Dk=0 Dk<0
结论:
IOUT = Kp*Dk+Out0
Kp:为一常数,可理解为硬件上的放大器或衰减器,用于对输出信号OUT的增益进行调整;
Out0:为一常数,为了在Dk为0时确保OUT都有一个稳定的控制值,避免失控。
PIDOUT = POUT + IOUT + DOUT0
PIDOUT = Kp(Ek+Sk+Dk)+OUT0
注:上面是基本思想
二、模拟PID控制原理
这里的 Et、St、Dt是上面的Ek、Sk、Dk
这个是连续的公式,转换成离散的模型是:
实际使用的也是离散化的模型
由于模拟的微积分运算对应计算机来说是不太好写代码的,所以要利用采样将数据离散化
PIDout(t) -------------输出曲线,pid输出值随时间的变化曲线
Kp --------------比例系数
E(t)------------- 偏差曲线,设定值与实际值的偏差随时间的变化曲线
Ti--------------- 积分时间
Td--------------微分时间
T--------------计算周期
整合一下为:
这个就是实际使用需要调整的参数
/**************************************************************************
函数功能:位置式PID控制器
入口参数:编码器测量位置信息,目标位置
返回 值:电机PWM
根据位置式离散PID公式
pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
e(k)代表本次偏差
e(k-1)代表上一次的偏差
∑e(k)代表e(k)以及之前的偏差的累积和;其中k为1,2,,k;
pwm代表输出
**************************************************************************/
int Position_PID (int position,int target)
{
static float Bias,Pwm,Integral_bias,Last_Bias;
Bias=target-position; //计算偏差
Integral_bias+=Bias; //求出偏差的积分
if(Integral_bias>3000)Integral_bias=3000;
if(Integral_bias<-3000)Integral_bias=-3000;
Pwm=Position_KP*Bias+Position_KI*Integral_bias+Position_KD*(Bias-Last_Bias); //位置式PID控制器
Last_Bias=Bias; //保存上一次偏差
return Pwm; //增量输出
}
/**************************************************************************
函数功能:增量PI控制器
入口参数:编码器测量值,目标速度
返回 值:电机PWM
根据增量式离散PID公式
pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)]
e(k)代表本次偏差
e(k-1)代表上一次的偏差 以此类推
pwm代表增量输出
****************************************************************************/
struct {
float set_speed;//设定速度
float actual_speed;//实际速度
float error;//偏差
float error_next;//上一个偏差
float error_last;//上上一个偏差
float kp,ki,kd;//定义比例,积分,微分参数
}pid;
void pid_init()
{
pid.set_speed = 0.0;
pid.actual_speed = 0.0;
pid.error = 0.0;
pid.error_next = 0.0;
pid.error_last = 0.0;
//可调节PID 参数。使跟踪曲线慢慢接近阶跃函数200.0 //
pid.kp = 0.2;
pid.ki = 0.01;
pid.kd = 0.2;
}
float pid_realise(float speed)//实现pid
{
pid.set_speed = speed;//设置目标速度
pid.error = pid.set_speed - pid.actual_speed;
float increment_speed;//增量
increment_speed = pid.kp*(pid.error-pid.error_next)+pid.ki*pid.error+\
pid.kd*(pid.error-2*pid.error_next+pid.error_last);//增量计算公式
pid.actual_speed+= increment_speed;
pid.error_last = pid.error_next;//下一次迭代
pid.error_next = pid.error;
return pid.actual_speed;
}
下一篇文章实现平衡小车的直立环、速度环、转向环