工程链接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