理解的PID控制

在这里插入图片描述
补充:为什么积分器是积分
在这里插入图片描述

位置型
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;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值