补充:为什么积分器是积分
位置型
pid. h
#ifndef _pid_
#define _pid_
#include "stm32f10x_conf.h"
typedef struct
{
float Sv;//用户设定值
float Pv;
float Kp;
float T; //PID计算周期--采样周期
float Ti;
float Td;
float Ek; //本次偏差
float Ek_1;//上次偏差
float SEk; //历史偏差之和
float Iout;
float Pout;
float Dout;
float OUT0;
float OUT;
u16 C10ms;
u16 pwmcycle;//pwm周期
}PID;
extern PID pid; //存放PID算法所需要的数据
void PID_Calc(void); //pid计算
#endif
pid. c
#include "pid.h"
PID pid; //存放PID算法所需要的数据void PID_Calc() //pid计算
{
float DelEk;
float ti,ki;
// float Iout;
// float Pout;
// float Dout;
float td;
float kd;
float out;
if(pid.C10ms<(pid.T)) //计算周期未到
{ return ; }
pid.Ek=pid.Sv-pid.Pv; //得到当前的偏差值
pid.Pout=pid.Kp*pid.Ek; //比例输出
pid.SEk+=pid.Ek; //历史偏差总和
DelEk=pid.Ek-pid.Ek_1; //最近两次偏差之差
ti=pid.T/pid.Ti;
ki=ti*pid.Kp; pid.Iout=ki*pid.SEk*pid.Kp; //积分输出 td=pid.Td/pid.T;
kd=pid.Kp*td;
pid.Dout=kd*DelEk; //微分输出
out= pid.Pout+ pid.Iout+ pid.Dout; // if(out>pid.pwmcycle) { pid.OUT=pid.pwmcycle; }
else if(out<0) { pid.OUT=pid.OUT0; }
else { pid.OUT=out; } //pid.OUT+=; //本次的计算结果
pid.Ek_1=pid.Ek; //更新偏差 pid.C10ms=0;}
void PID_Calc_overshoot() //pid计算-过冲处理
{ float DelEk; float ti,ki;
// float Iout;
// float Pout;
// float Dout;
float td;
float kd;
float out;
float SvSave; if(pid.C10ms<(pid.T)) //计算周期未到
{ return ; } //判断Sv
SvSave=pid.Sv; if(pid.Pv<(SvSave*0.55))//温度达到计数开始 66度
{ pid.times=0; } if(pid.times<=60)//3分钟 72度 100s
{ pid.Sv=SvSave*0.6; } if((pid.times>60)&&(pid.times<=100))//3分钟 96度 100s
{ pid.Sv=SvSave*0.8; } if((pid.times>100)&&(pid.times<=200))//2分钟 102度 100s
{ pid.Sv=SvSave*0.85; } if((pid.times>200)&&(pid.times<=300))//2分钟 108度 100s
{
pid.Sv=SvSave*0.9;
}
if((pid.times>300)&&(pid.times<=400))//2分钟 114度 100s
{
pid.Sv=SvSave*0.95;
}
if(pid.times>400) {
pid.Sv=SvSave;
}
// pid.Ek=pid.Sv-pid.Pv; //得到当前的偏差值
pid.Pout=pid.Kp*pid.Ek; //比例输出
pid.SEk+=pid.Ek; //历史偏差总和
DelEk=pid.Ek-pid.Ek_1; //最近两次偏差之差
ti=pid.T/pid.Ti;
ki=ti*pid.Kp; pid.Iout=ki*pid.SEk*pid.Kp; //积分输出 td=pid.Td/pid.T;
kd=pid.Kp*td;
pid.Dout=kd*DelEk; //微分输出
out= pid.Pout+ pid.Iout+ pid.Dout; // if(out>pid.pwmcycle) { pid.OUT=pid.pwmcycle;
}
else if(out<0) {
pid.OUT=pid.OUT0;
} else {
pid.OUT=out;
} //pid.OUT+=; //本次的计算结果
pid.Ek_1=pid.Ek; //更新偏差 pid.C10ms=0;
pid.Sv=SvSave;
}
增量型
pid. h
#ifndef _pid_
#define _pid_
#include "stm32f10x_conf.h"
typedef struct
{
float curr; //当前温度
float set; //设定温度
// float pid_P; //P
// float pid_I; //I
// float pid_D; //D
// short Ek;//
// short Ek_1;//
// short Ek_2;//
//int PID_OUT;//
float En;
float En_1;
float En_2;
float Kp; //比例系数
float Tsam; //采样周期---控制周期,每隔Tsam控制器输出一次PID运算结果
float Ti;//积分时间常数
float Td;//微分时间常数
float Dout;//增量PID计算本次应该输出的增量值--本次计算的结果
u16 calc_cycle;
short currpwm; //当前的pwm宽度
u16 pwm_cycle;//pwm的周期
}PID;
extern u8 STATUS;
extern PID pid;
void PIDParament_Init(void); //
void pid_calc(void); //pid??
#endif
pid. c
#include "pid.h"
PID pid;extern u16 pidcalcms;void PIDParament_Init() //
{ pid.set =100;
pid.currpwm=0;
pid.pwm_cycle=100; pid.pid_P=8;
// pid.pid_I=4;
// pid.pid_D=5;
pid.calc_cycle=100;
pid.Td=2000;
pid.Ti=4000;
pid.Kp=5;
pid.Tsam=500;
}
/*void pid_calc() //pid??
{ //int dk; s
hort PID_out; if(pidcalcms<pid.calc_cycle) return ; pid.Ek=pid.set-pid.curr;//????(????-????)
PID_out=((pid.pid_P)*((pid.Ek)-(pid.Ek_1)))+ \
((pid.pid_I)*(pid.Ek))+ \ ((pid.pid_D)*((pid.Ek)-(2*(pid.Ek_1))+(pid.Ek_2))); //?????? pid.currpwm+=PID_out; pid.Ek_2=pid.Ek_1; //??????? pid.Ek_1=pid.Ek; //?????? if(pid.currpwm>pid.pwm_cycle) //1000 //1s??PWM??
{
pid.currpwm=pid.pwm_cycle; //????????1000???????
}
if(pid.currpwm<=0) //??????0??0??(????)
{
pid.currpwm=0;//
} //PID????
pidcalcms=0;
} */
void pid_calc() //pid
{ float dk1;float dk2;
float t1,t2,t3; //short PID_out; if(pidcalcms<pid.Tsam) return ; // pid.En=pid.set-pid.curr; //本次误差 dk1=pid.En-pid.En_1; //本次偏差与上次偏差之差
dk2=pid.En-2*pid.En_1+pid.En_2; t1=pid.Kp*dk1;
t2=(pid.Kp*pid.Tsam)/pid.Ti; t2=t2*pid.En;
t3=(pid.Kp*pid.Td)/pid.Tsam;
t3=t3*dk2;
pid.Dout=t1+t2+t3; //本次应该输出的增量
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;
pidcalcms=0;
}