文章目录
- 什么是pid
- 比例(p)控制
- 积分(I)控制
- 微分(D)控制
- PID使用
- 增量式PID
- C语言实现pid算法
什么是pid
PID算法是一种可预见的控制算法,其核心思想是: 1>. PID算法不仅考虑控制对象的当前状态值(当前状态),还考虑控制对象过去状态值(历史状态)和最近状态值的变化(预期),共同决定当前输出控制信号; 2>.PID控制算法的操作结果是一个数字,用来控制被控对象在各种工作状态下工作(如加热器的多种功率、阀门的多种开度等。),一般输出形式是PWM,基本满足按需输出控制信号,根据情况随时改变输出的目的。
比例(p)控制
比例控制是最简单的控制方法。控制器的输出与输入误差信号成比例。当只有比例控制时,系统输出就会出现稳态误差(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,系统处于无控信号失控状态。
积分(I)控制
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时有输出值,避免失控;
微分(D)控制
误差的微分是误差的变化率。误差变化越快,微分的绝对值越大。当误差增加时,微分为正;当误差减小时,微分为负。控制器输出的微分与误差的微分成正比,反映了被控量变化的趋势。 经验丰富的操作人员在温度上升过快,但尚未达到设定值时,根据温度变化的趋势,预测温度将超过设定值并超调。因此,调整电位器的角度,提前减少加热电流。这相当于士兵在射击远处的移动目标时,考虑到子弹运动的时间,需要一定的提前量。
Dk=Ek-Ek-1 说明: Ek:当前的偏差 Ek-1: 基于前一个采样时刻的偏差值(即上一个偏差值); 分析Dk: Dk>0:说明从上一次采样到现在的误差都有增长趋势 Dk=0:说明从上一次采样到当前误差稳定 Dk<0:说明从上一次采样到当前误差都有减少趋势 Dk>0 Dk=0 Dk<0
结论:
- Dk可以说明从上次采样到当前采样期间被控对象的状态变化趋势,这种变化趋势很可能会延续到下一个采样时间点,因此可以根据这一变化趋势进行(Dk值)输出信号OUT调整,达到提前控制的目的。
- Dk数学上的微分运算反映了控制对象在一段时间内的变化趋势和变化,因此使用了它Dk调整控制器输出信号的算法称为微分(differential)算法
IOUT = Kp*Dk Out0 Kp:对于输出信号,可以理解为硬件上的放大器或衰减器OUT调整增益; Out0:为常数,为Dk为0时确保OUT都有稳定的控制值,避免失控。
PIDOUT = Kp(Ek+Sk+Dk)+OUT0
PID使用
上图的通俗表示:
二、模拟PID控制原理
这里的 Et、St、Dt是上面的Ek、Sk、Dk
这个是连续的公式,转换成离散的模型是:
实际使用的也是离散化的模型 由于模拟的微积分运算对应计算机来说是不太好写代码的,所以要利用采样将数据离散化
PIDout(t) -------------输出曲线,pid输出值随时间的变化曲线
Kp --------------比例系数
E(t)------------- 偏差曲线,设定值与实际值的偏差随时间的变化曲线
Ti--------------- 积分时间
Td--------------微分时间
T--------------计算周期
整合一下为:
其中:
这个就是实际使用需要调整的参数
增量式PID
C语言实现pid算法
/************************************************************************** 函数功能:位置式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;
}
下一篇文章实现平衡小车的直立环、速度环、转向环