电子设计大赛PID算法总结

工程链接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(pidcalcms<pid.Tsam) return ;  //设定的pid计算周期,没有达到要求则返回
	
	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);  //调整占空比
   
    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(pidcalcms<pid.Tsam) return ;  //pid计算器是否到达计算周期
	
	pid.Dout=pid.P*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);  //调整占空比
   
    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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值