资讯详情

比较通俗易懂的PID理解

分享一个通俗易懂的分享PID理解

在 APM 菜单中有一个参数设置 PID设置,没有接触过 PID对人来说,那完全是一头雾水,一堆摸不着头脑的数字。鉴于此,本文力争以通俗的语言讲解 PID每个意思。 PID 控制是一种广泛应用于自动化控制领域的控制方法,P 代表比例,I 代表积分,D 从这些名词中可以看出代表微分,PID 控制是基于数学的一个重要分支:基于微积分学的数字自动控制模式,以传感器收集的数据作为输入源,并根据预定的数据 PID 输出控制按特定公式计算。

例如,一列即将到达车站的火车将在即将到达车站时切断输出功率,使其以惯性滑到月台。假如设置火车 100km/h 站前的速度 1km 切断动力并开始滑行的地方,所以这个 100 比1 就是比例 P的含义,P 站前滑行越大,速度越快。滑行初始速度快的好处是进站快,但初始滑行速度过快会导致火车在惯性的作用下冲过月台,所以火车不得不倒车,但因为 P 如果设置过大,倒车后的滑行也会使火车倒过头,从而形成反复向前后退的震荡局面。而 P 如果设置小,进站速度会变得很慢,进站时间会延长。所以设置一个合适的 P 值是 PID 调整的首要任务。由于 P 这是一个固定的值。如果火车的速度和平台之间的距离用坐标图理想化地显示出来,则不考虑惯性和外力的作用。 P 调整的结果将是直斜线。斜线越陡,进站时间越短 在这里插入图片描述

上图的 P 调整结果只是为了便于理解,实际上是不可能的,PID计算的结果也不是这样子。无论如何,如果只有 P 调整,火车要么设置相对较低的 P 以非常缓慢的速度到达目标月台,或过度冲洗,很难在速度和准确性之间设置平衡。所以下一步应该是解释 D 该微分了。根据上述例子,如果 P 等于 100 当火车只能滑到月台时,所需的时间是 10 分钟。但对于自稳定性能要求高的自动化系统,这是 10 分钟太长,能加快吗?是的,我们把 P 加大到 120让火车司机在站前开火车 1km 的地方以 120km/h 速度开始减速滑行,然后站在前面 500 踩下刹车,将速度降低到米 80km/h,站前 300 米再踩一下刹车让速度降为 50km/h,站前 再踩刹车100米,让速度降到 20km/h,站前 10 米让火车在短时间内滑到月台的准确位置,这样进站速度会大大加快,原本需要 10 分钟可能只需要几分钟 5 分钟就行了。 这就是 D作用,我们权并把 D理解为刹车,如果仍然表达坐标图 D对 P 调整的影响是 D 使 P 在 PID 公式中,D 左右是变化 P 的曲线,D 值越大,对 P 影响越大。加入 D 前期曲线陡峭,进站快,后期平缓,使火车能够平稳准确地进站。

相信经过这个解释,很多模友都明白了 PD在飞机的实际调整中,我们可以有针对性。根据 PD我们可以得出一个调整步骤:首先 D置零,加大 P值,使飞机适当过冲开始冲击,然后增加 D 降低数值 P 调整后期的作用,放慢过冲现象,最后调整到不过冲。P飞机倾斜后恢复的速度越快,越敏感,但会产生冲击;D 调整越大,越平稳,但越稳定 D 会议延长了调整时间,表现为反应迟钝(这里 D 指的就是 D 一般数值 PID 表述中,D 越接近 0,P 效果越大,需要注意)。

最后讲解 I 的作用,I 是积分,是为了消除误差而添加的参数。如果在上述例子中,火车靠站后,离最终目标停止线仍然很差 1 米,虽然我们也可以认为这是一个合格的停车场,但这毕竟是一个错误,如果我们同意的话 1 米的误差,在此基础上,火车第二次靠站会有 在过去,2米的误差会越来越大,所以我们必须记录这个误差,当我们第二次进入车站时,它可以工作,如果它很糟糕 1 米,火车司机可以在原来 PD基于调整I 积分,延迟 1 米输出(或提前) 999 米开始减速,最后刚到停止线。如果没有 I 多轴飞机平台的作用是飞机越来越倾斜,最终失去平衡。如果没有 I 多轴飞机平台的作用是飞机越来越倾斜,最终失去平衡。I 基于调整 PD ,PD 会影响变化 I 因此,最终的调整步骤是先调整 P 确定灵敏度,然后调整 D调整稳定性,最后调整稳定性 I 确定精度。

#include<reg51.h> #include "intrins.h" #include <lcd.H> #define uchar unsigned char #define uint unsigned int #define GPIO_KEY P2 sbit PWM=P1^4;     sbit P10=P1^0;  sbit P12=P1^2; uchar speed1[4]={ 
       "0000"};//设定转速 uchar speed2[3]={ 
       "000"};//占空比 
uchar speed[]={ 
       "0000"};//当前转速
uchar KeyValue=0;
uint AA,count=0,flag;

float pid_p=0.003,pid_i=0.003,pid_d=0.002;	//PID三个参数 初值
uint SpeedSet=3000,CurrentSpeed;//设定转速 当前转速
unsigned char pid_val_mid;//pid_val_mid脉冲宽度
unsigned int lastError=0;
long int sumError=0;//sum偏差和
	
	
void delay1(unsigned int i)
{ 
       
   unsigned int j;
	 for(;i>0;i--)
	 for(j=0;j<333;j++)
	 { 
       ;}
}	


/********************* 键盘扫描*************/
void KeyDown(void)		
{ 
       
	GPIO_KEY=0x0f;
		delay1(10);
	if(GPIO_KEY!=0x0f)
	{ 
       
		delay1(10);
		if(GPIO_KEY!=0x0f)
		{ 
       
				//测试列
			GPIO_KEY=0X0F;
			delay1(10);
			switch(GPIO_KEY)
			{ 
       
				case(0X07):	KeyValue=0;break;
				case(0X0b):	KeyValue=1;break;
				case(0X0d): KeyValue=2;break;
				case(0X0e):	KeyValue=3;break;
			}
			//测试行
			GPIO_KEY=0XF0;
			delay1(10);
			switch(GPIO_KEY)
			{ 
       
				case(0X70):	KeyValue=KeyValue;break;
				case(0Xb0):	KeyValue=KeyValue+4;break;
				case(0Xd0): KeyValue=KeyValue+8;break;
				case(0Xe0):	KeyValue=KeyValue+12;break;
			}
			
		}

	}
}

void timer()
{ 
       
  
	 TMOD=0x11;//定时器0工作方式1.16位,定时器1工作方式1,16位定时;
	 TH0=0x4b;//50ms初值
	 TL0=0xfe;
	 
	 TH1=0xfc;//1msPWM控制
	 TL1=0x66;
	 
	 TR1=1;	  //启动定时器1
	 ET1=1;	   //定时器1中断使能
	 IT0=1;//外部中断下降沿触发
	 TR0=1;	//定时器启动标志
	 ET0=1;	//定时器中断使能
	 EX0=1;	//外部中断使能
	 EA=1;	//全局中断
}


/***********************lcd显示*************/
void  display()
{ 
          
    
	  speed[0]=CurrentSpeed/1000+0x30; //当前转速
		speed[1]=CurrentSpeed/100%10+0x30;
		speed[2]=CurrentSpeed/10%10+0x30;
		speed[3]=CurrentSpeed%10+0x30;  
		
		
		speed1[0]=SpeedSet/1000+0x30;//设定转速
		speed1[1]=SpeedSet/100%10+0x30;
		speed1[2]=SpeedSet/10%10+0x30;
		speed1[3]=SpeedSet%10+0x30;  
		
		speed2[0]=pid_val_mid/100+0x30;
	  speed2[1]=pid_val_mid/10%10+0x30;//占空比
		speed2[2]=pid_val_mid%10+0x30;
		
	
	  DispHanzi(0,0,5,"当前转速:");
		DispZimu(0,5,4,speed);	
		DispHanzi(1,0,5,"设定转速:");
		DispZimu(1,5,4,speed1);

		DispHanzi(3,0,4,"占空比:");//占空比 
		DispZimu(3,4,3,speed2);
		DispHanzi(3,6,1,"%");//占空比 
		
}



/************************电机控制*************/
void keyKZ()
{ 
       
			 if(KeyValue==4)//正转
			 { 
       
			  P10=1;
		    P12=0;
				}
			 if(KeyValue==5)//反转
			 { 
       
			  P10=0;
		    P12=1;
				}
				if(KeyValue==6)//停车
			 { 
       
			  P10=0;
		    P12=0;
				}
			
			if(KeyValue==12)//设定速度加50
			  SpeedSet+=50;
			if(KeyValue==13)//设定速度减50
				SpeedSet-=50;
			if(KeyValue==14)//设定速度加1
			  SpeedSet+=1;
			if(KeyValue==15)//设定速度减1
				SpeedSet-=1;
	KeyValue=0;
				
}


/************************PID控制算法*************/
unsigned int PID()
{ 
         

  int dError=0,Error=0,B;
	
	Error=SpeedSet-CurrentSpeed;//当前误差=设置速度-实际速度
   sumError=Error+sumError;//误差和=当前误差+总误差
   dError=Error-lastError;//误差偏差=当前误差-上次误差
   lastError=Error;//上次误差
  	B=pid_p*Error+pid_i*sumError+pid_d*dError;
	
	if(B>100) pid_val_mid=100;
   if(B<0) pid_val_mid=0;
	if(B>=0&&B<=100)
   pid_val_mid=B;//输出pwm脉宽
	 return(0);
}


void Timer0_isr() interrupt 1  //定时器0中断
{ 
       
	 AA++;
	 TH0=0x4b;
	 TL0=0xfe;
	 if(AA==20)
	 { 
       		
  	 CurrentSpeed=count*3;//一分钟的转速
				count=0;
				AA=0;
				PID();
	 }

}


void key_int() interrupt 0	 //外部中断P32口
{ 
       
	count++;
}

void Timer1() interrupt 3
{ 
       
   static int c=0;
		 TH1=0xfc;
	 	 TL1=0x66;
		 c++;    //每次定时器溢出加1 
	 
	  if(c<=pid_val_mid) PWM=1;
	     
	  if(c>pid_val_mid)  PWM=0;
	    
		if(c>=100) 	c=0; 
}
	
void main()
{ 
       
		timer();//定时器初始化
		InitLCD();//LCD初始化
		while(1)
		{ 
        
		   KeyDown();	//键盘扫描
			 keyKZ();//键盘控制
			 display();//显示LCD
		}
}	

标签: apm接近传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台