对于PID的认识
PID控制器实际上是对偏差的控制
连续状态的公式:
将其离散化,离散化具体就是用求和代替积分,用向后差分来代替微分
- T————为采样周期
- k————为采样序号,k=0,1,2….
偏差err(K)=rin(K)-rout(K);
积分环节用加和的形式表示,即err(K)+err(K+1)+……;
微分环节用斜率的形式表示,即[err(K)-err(K-1)]/T;
位置式PID
Kp是比例系数
Ki是积分系数
Kd是微分系数.
比例:给误差e一个系数,这个系数就是比例系数。如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。
优点:加快系统的响应速度,提高系统的调节精度。
缺点:导致超调
积分:稳态误差是指输出稳定后与目标值有一个差值,加入误差积分项可以消除稳态误差,积分系数是误差积分项的系数。积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。
优点:消除稳态误差
缺点:导致积分饱和现象
微分:在临近目标值的时候可能会有微小的震荡,加入变化率可以做到慢慢调的目的,微分技术是误差微分即变化率前的系数。微分信号则反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。
优点:改善系统的动态性能
缺点:延长系统的调节时间,但其抗干扰性差
位置式PID的优缺点
优点:位置式 PID 是一种非递推式算法,可直接控制执行机构(如平衡小车),u(k) 的值和执行机构的实际位置(如小车当前角度)是一>一对应的,因此在执行机构不带积分部件的对象中可以很好应用;
缺点:每次输出均与过去的状态有关,计算时要对 e(k) 进行累加,运算工作量大。
增量式PID
增量式算法的优缺点
优点:
- 误动作时影响小,必要时可用逻辑判断的方法去掉出错数据。
- 手动/自动切换时冲击小,便于实现无扰动切换。
- 算式中不需要累加。控制增量 Δu(k) 的确定仅与最近 3 次的采样值有关。在速度闭环控制中有很好的实时性。
缺点:1. 积分截断效应大,有稳态误差;- 溢出的影响大。有的被控对象用增量式则不太好;
c++实现
位置式PID
#include <iostream>
using namespace std;
void PID_init();
float PID_realize(float speed);
struct _pid{
float SetSpeed;//定义设定值
float ActualSpeed;//定义实际值
float err;//定义偏差值
float err_last;//定义上一个偏差值
float Kp,Ki,Kd;//定义比例、积分、微分系数
float voltage;//定义电压值(控制执行器的变量)
float integral;//定义积分值
}pid;
int main()
{
cout<<"System begin \n";
PID_init();
int count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
cout<<"第 "<<count<<" 次的速度为: "<<speed<<endl;
count++;
}
return 0;
}
void PID_init(){
cout<<"PID_init begin \n";
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
cout<<"PID_init end \n";
}
float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
pid.integral+=pid.err;
pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
pid.err_last=pid.err;
pid.ActualSpeed=pid.voltage*1.0;
return pid.ActualSpeed;
}
增量式PID
#include <iostream>
using namespace std;
void PID_init();
float PID_realize(float speed);
struct _pid{
float SetSpeed;//定义设定值
float ActualSpeed;//定义实际值
float err;//定义偏差值
float err_next;//定义下一个偏差值
float err_last;//定义上一个偏差值
float Kp,Ki,Kd;//定义比例、积分、微分系数
float voltage;//定义电压值(控制执行器的变量)
float integral;//定义积分值
}pid;
int main()
{
cout<<"System begin \n";
PID_init();
int count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
cout<<"第 "<<count<<" 次的速度为: "<<speed<<endl;
count++;
}
return 0;
}
void PID_init(){
cout<<"PID_init begin \n";
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_next=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
cout<<"PID_init end \n";
}
float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
float
incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last);
pid.ActualSpeed+=incrementSpeed;
pid.err_last=pid.err_next;
pid.err_next=pid.err;
return pid.ActualSpeed;
}
调参的顺序:先调P,再调D,最后调I
调P,让曲线震荡起来
调D,阻止曲线的震荡,让曲线平滑
调I,把曲线整体调整到目标值