PID:比例积分微分-难点在于控制器参数的设定
https://www.arduino.cn/thread-12813-1-1.html(通俗的解释)
采样周期:采样周期越小,越能反映模拟量的变化情况,但是过小会增加CPU的运算工作量,而且相邻的两次采样差值机会没有变化;
阶跃响应:在某个时间点发送突变;
1.比例控制 (有偏差的时候使用)
闭环系统中调节困难的主要原因是系统的延迟作用,比例系数过小是的调节速度太慢,比例系数过大的话会使得震荡次数增加,调调节时间增加,动态性变差,造成闭环系统不稳定;
数字化的表示:
2.积分控制(稳定后有误差的时候使用)
目的:消除静态误差(稳态误差:系统达到稳定后还是存在一定的误差),提高控制精度
积分项和当前的误差值和过去的历次误差值的累加值值成正比,因此积分作用本身具有严重的滞后特性;
3.微分控制(监控变化趋势,超前调节)
误差的微分就是误差的变化率,误差变化越快,微分绝对值越大,控制器输出量的微分部分与误差的微分成正比,反映了被控制量变化的趋势;
数字量:
直流电机为例子分析:rin(t)是电机转速的预定值,rout(t)是电机转速的实际值
偏差:Kp*err(k)=rin(k)-rout(k) T是采样间隔
积分环节:(加和的形式)err(k)+err(k+1).......
微分环节:(斜率的形式)[err(k)-err(k-1)]/T
PID实现算法:位置型;(参考资料来源:https://wenku.baidu.com/view/827c5423647d27284a735105.html)
struct pid{
float SetSpeed;
float ActualSpeed;
float err;
float err_last;
float Kp,Ki,Kd;
float voltage;
float intergral;
}pid;
void PID_init(){
printf("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.intergral=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
printf("PID_init end\n");
}
float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
pid.intergral+=pid.err;//积分就是求和
//关键的公式体现:位置式
pid.voltage=pid.Kp*pid.err+pid.Ki*pid.intergral+pid.Kd*(pid.err-pid.err_last);
//增量式
//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_last=pid.err;
pid.ActualSpeed=pid.voltage*1.0;//?????什么意思
return pid.ActualSpeed;
}
int main(){
printf("system begin \n");
PID_init();
init_count=0;
while(count<1000)
{
float speed=PID_realize(200.0);
printf("%f\n",speed);
count++;
}
}
积分分离的控制算法
为什么要积分分离??答:普通PID中,引入积分环节的目的是为了消除静态误差,提高控制的精度。但是在启动,结束或大幅度增减设定的时候,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,导致控制量超过执行机构可能允许的最大动作范围对应极限控制量,从而引起较大的超调甚至震荡;因为这个原因,引入积分分离的概念。
基本思路:当被控量与设定的值偏差较大时,取消积分的作用,当被控制量接近给定的值时,引入积分控制,以消除静态差,提高精度。
关键部分代码如下:
if(abs(pid.err)>200)
{
index=0;
}
else{
index=1;
pid.integral+=pid.err;
}
pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);//index是关键