电子设计大赛PID算法总结

2019-04-14 19:36发布

工程链接https://download.csdn.net/download/shenlong1356/10820782

pid核心算法如下:

pid.En=pid.setdianya-pid.currdianya; //求本次误差 pid.Dout=pid.Kp*pid.En-pid.I*pid.En_1+pid.D*pid.En_2; //求输出增量 pid.currpwm+=pid.Dout; //本次应该输出的PWM // 计算输出量 if(pid.currpwm>pid.pwm_cycle) //输出量不能超限 { pid.currpwm=pid.pwm_cycle; } if(pid.currpwm<0) { pid.currpwm=0; } pid.En_2=pid.En_1; //误差更新 pid.En_1=pid.En; PWM(pid.currpwm); //调整占空比

但是光用上面的算法有时候不能达到很好的稳定要求,从大赛设计效果看,P系数最为重要,所以应该合理分段调节P系数和计算周期,感觉I系数和D系数作用不是特别明显

void pid_calc() { float set=0; set=pid.setdianya; pid.En=pid.setdianya-pid.currdianya+0.1; //本次电压误差 if(set>1) { if(pid.En>1||pid.En<-1) { pid.Tsam=10; pid.Kp=18; } else if(pid.En>0.7||pid.En<-0.7) { pid.Tsam=30; pid.Kp=17.5; } else if(pid.En>0.5||pid.En<-0.5) { pid.Tsam=60; pid.Kp=17; } else if(pid.En>0.3||pid.En<-0.3) { pid.Tsam=100; pid.Kp=16.5; } else if(pid.En>0.1||pid.En<-0.1) { pid.Tsam=120; pid.Kp=16; } else if(pid.En>0.05||pid.En<-0.05) { pid.Tsam=140; pid.Kp=15.5; } else if(pid.En>0.02||pid.En<-0.02) { pid.Tsam=160; pid.Kp=14; } else { pid.Tsam=200; pid.Kp=13; } } else { if(pid.En>0.5||pid.En<-0.5) { // pid.Tsam=10; pid.Kp=13; } else if(pid.En>0.3||pid.En<-0.3) { // pid.Tsam=30; pid.Kp=12; } else if(pid.En>0.2||pid.En<-0.2) { // pid.Tsam=60; pid.Kp=11; } else if(pid.En>0.1||pid.En<-0.1) { // pid.Tsam=100; pid.Kp=10; } else if(pid.En>0.07||pid.En<-0.07) { // pid.Tsam=120; pid.Kp=9; } else if(pid.En>0.05||pid.En<-0.05) { // pid.Tsam=140; pid.Kp=8; } else if(pid.En>0.02||pid.En<-0.02) { // pid.Tsam=160; pid.Kp=7; } } if(pidcalcmspid.pwm_cycle) { pid.currpwm=pid.pwm_cycle; } if(pid.currpwm<0) { pid.currpwm=0; } pid.En_2=pid.En_1; pid.En_1=pid.En; PWM(pid.currpwm); //调整占空比 pidcalcms=0; }

整体代码如下:

#include "pid.h" #include "timer.h" #include "usart.h" #include "usb_lib.h" #include "hw_config.h" #include "usb_pwr.h" #include "led.h" float yuan=44.4; PID pid; extern u8 dianliuset; extern u16 pidcalcms; extern u8 PIDFLAG; void PIDParament_Init() // { pid.setdianya =0; //初始值设定 pid.setdianliu=0; pid.currpwm=0; //当前占空比 pid.pwm_cycle=500; // pid.En_1=0; pid.En_2=0; pid.I=1; pid.D=0; pid.P=16; //比例系数 pid.Tsam=200; //200 ms计算一次 pid周期值 } void pid_calc() { float set=0; set=pid.setdianya; pid.En=pid.setdianya-pid.currdianya+0.1; //本次电压误差 if(set>1) { if(pid.En>1||pid.En<-1) { pid.Tsam=10; pid.P=18; } else if(pid.En>0.7||pid.En<-0.7) { pid.Tsam=30; pid.P=17.5; } else if(pid.En>0.5||pid.En<-0.5) { pid.Tsam=60; pid.P=17; } else if(pid.En>0.3||pid.En<-0.3) { pid.Tsam=100; pid.P=16.5; } else if(pid.En>0.1||pid.En<-0.1) { pid.Tsam=120; pid.P=16; } else if(pid.En>0.05||pid.En<-0.05) { pid.Tsam=140; pid.P=15.5; } else if(pid.En>0.02||pid.En<-0.02) { pid.Tsam=160; pid.P=14; } else { pid.Tsam=200; pid.P=13; } } else { if(pid.En>0.5||pid.En<-0.5) { // pid.Tsam=10; pid.P=13; } else if(pid.En>0.3||pid.En<-0.3) { // pid.Tsam=30; pid.P=12; } else if(pid.En>0.2||pid.En<-0.2) { // pid.Tsam=60; pid.P=11; } else if(pid.En>0.1||pid.En<-0.1) { // pid.Tsam=100; pid.P=10; } else if(pid.En>0.07||pid.En<-0.07) { // pid.Tsam=120; pid.P=9; } else if(pid.En>0.05||pid.En<-0.05) { // pid.Tsam=140; pid.P=8; } else if(pid.En>0.02||pid.En<-0.02) { // pid.Tsam=160; pid.P=7; } } if(pidcalcmspid.pwm_cycle) { pid.currpwm=pid.pwm_cycle; } if(pid.currpwm<0) { pid.currpwm=0; } pid.En_2=pid.En_1; pid.En_1=pid.En; PWM(pid.currpwm); //调整占空比 pidcalcms=0; //对pid计数器值清零,该值在定时器中断服务函数里自加 } /**Pid.h文件**/ #ifndef _PID_H #define _PID_H #include "stm32f10x_conf.h" typedef struct { float currdianliu; //当电流值 float currdianya; //当前电压值 float setdianya; //设定值 float setdianliu; float P; //比例系数 float I; //I系数 float D; //D float En; float En_1; float En_2; float Tsam; //采样周期---控制周期,每隔Tsam控制器输出一次PID运算结果 float Dout;//增量PID计算本次应该输出的增量值--本次计算的结果 short currpwm; //当前的pwm宽度 u16 pwm_cycle;//pwm的周期 }PID; extern u8 STATUS; extern PID pid; void PIDParament_Init(void); // void pid_calc(void); //pid?? #endif

工程链接https://download.csdn.net/download/shenlong1356/10820782