#include <stdio.h> #include <stdlib.h> #include <string.h> /*********************************************************************** 所谓的积分饱和现象是指如果系统存在一个方向的偏差, PID 控制器的输 出由于积分作用的不断累加而加大, 从而导致执行机构达到极限位置, 若控制器 输出 U(k)继续增大, 执行器开度不可能再增大, 此时计算机输出控制量超出了 正常运行范围而进入饱和区。 一旦系统出现反向偏差, u(k)逐渐从饱和区退出。 进入饱和区越深则退出饱和区时间越长。 在这段时间里, 执行机构仍然停留在极 限位置而不随偏差反向而立即做出相应的改变, 这时系统就像失控一样, 造成控 制性能恶化, 这种现象称为积分饱和现象或积分失控现象。 防止积分饱和的方法之一就是抗积分饱和法, 该方法的思路是在计算 u(k)时, 首先判断上一时刻的控制量 u(k-1)是否已经超出了极限范围: 如果 u(k-1)>umax, 则只累加负偏差; 如果 u(k-1)<umin, 则只累加正偏差。 从而避 免控制量长时间停留在饱和区。 直接贴出代码, 不懂的看看前面几节的介绍。 ****************************************************************************/ struct _pid { float SetSpeed; //定义设定值 float ActualSpeed; //定义实际值 float err; //定义偏差值 float err_last; //定义上一个偏差值 float Kp,Ki,Kd; //定义比例、 积分、 微分系数 float voltage; //定义电压值( 控制执行器的变量) float integral; //定义积分值 float umax; float umin; } 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.integral=0.0; pid.Kp=0.2; pid.Ki=0.1; //注意, 和上几次相比, 这里加大了积分环节的值 pid.Kd=0.2; pid.umax=400; pid.umin=-200; printf("PID_init end \n"); } float PID_realize(float speed) { int index; pid.SetSpeed=speed; pid.err=pid.SetSpeed-pid.ActualSpeed; if(pid.ActualSpeed>pid.umax) //灰色底色表示抗积分饱和的实现 { if(abs(pid.err)>200) //蓝色标注为积分分离过程 { index=0; } else { index=1; if(pid.err<0) { pid.integral+=pid.err; } } } else if(pid.ActualSpeed<pid.umin) { if(abs(pid.err)>200) //积分分离过程 { index=0; } else { index=1; if(pid.err>0) { pid.integral+=pid.err; } } } else { 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); pid.err_last=pid.err; pid.ActualSpeed=pid.voltage*1.0; return pid.ActualSpeed; } int main() { PID_init(); int count=0; while(count<1000) { float speed=PID_realize(200.0); printf("%f\n",speed); count++; } return 0; }
时间: 2024-10-29 10:45:53