⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v_pid.h

📁 PIC16X187实现的PID算法
💻 H
字号:
//***************************PID算法有关**********************************************
//**************************定义PID的三个参数*************************
#define VV_KAVALUE  0x40
#define VV_KBVALUE  0x09
#define VV_KCVALUE  0x10
   
// Ka, Kc偏大, 从10以内开始较好
#define Pmax       0x1EA           //默认占空比最大值
#define Pmix       0x33           //默认占空比最小值
#define cMax       0x33           //默认电流最大值
#define ctime       0x02         //默认电流采样时基
#define SpRmp      0X7d    //默认初始转速  800,(4)15000/800=187 (6)10000/800=187
#define Sperror       5    //误差允许数据
extern unsigned int  PWMOUT ;
const unsigned char Cek[8]={0x03,0x0c,0x30,0x05,0x09,0x24,0x23,0x25};     //电流PID查表
/******************************************************************************
设置相应转速的PID常量:
控制死区;上下限;
*******************************************************************************/
bank1  typedef struct 	//定义运算数据
{
	signed int vi_RefH;		  	 //速度PID,速度设定值
	signed int vi_FeedBack;		 //速度PID,速度反馈值
	
	signed int vi_PreError;	  	//速度PID,前一次,速度误差, vi_Ref - vi_FeedBack
	signed int vi_PreDerror;	//速度PID,前一次,速度误差之差, d_error - PreDerror ;
	
	signed char v_Ka;			//速度PID,Ka = Kp
	signed char v_Kb;			//速度PID,Kb = ( T / Ti )
	signed char v_Kc;			//速度PID,kc =  ( Td / T )

	signed int vi_PreU;		//转速电机控制输出值
		
} PID;
PID	 sPID;        		//  PID Control Structure		

/******************************************************************************
设置相应电流的PID常量:
控制死区;上下限;
*******************************************************************************/
bank1 typedef	struct 	//定义运算数据
{
 	signed char vi_RefH;		  	 //电流PID,电流设定值
 	signed char vi_FeedBack;		 //电流PID,电流反馈值
	
 	signed char vi_PreError;	  	//电流PID,前一次,电流误差, vi_Ref - vi_FeedBack
 	signed char vi_PreDerror;	//电流PID,前一次,电流误差之差, d_error - PreDerror ;
	
 	signed char v_Ka;			//电流PID,Ka = Kp
 	signed char v_Kb;			//电流PID,Kb = ( T / Ti )
 	signed char v_Kc;			//电流PID,kc =  ( Td / T )
	
    unsigned char Delay;			//采样时击
    unsigned char Delay1;			//采样时击记数
    unsigned char Count;			//采样个数
    unsigned char HED ;              //数据采集完成 0xff
 	signed int vi_PreU;		//电流控制输出值
		
} PID1;
PID1	 cPID;        		//  PID Control Structure
/**********************************************************************
PID参数初始化
**********************************************************************/
void PIDInit ()
{	
	sPID.vi_RefH = SpRmp ;			//速度设定值
	sPID.vi_FeedBack = 0 ;		//速度反馈值
	
	sPID.vi_PreError = 0 ;	  	//前一次,速度误差,,vi_Ref - vi_FeedBack
	sPID.vi_PreDerror = 0 ;		//前一次,速度误差之差,PreDerror - d_error
	
	sPID.v_Ka = VV_KAVALUE;
	sPID.v_Kb = VV_KBVALUE;
	sPID.v_Kc = VV_KCVALUE;
	
	sPID.vi_PreU = 0 ;		//电机控制输出值
    
    cPID.vi_RefH = 0 ;			//电流PID,电流设定值
	cPID.vi_FeedBack = 0 ;		//电流PID,电流反馈值
	
	cPID.vi_PreError = 0 ;	  	//电流PID,前一次,电流误差, vi_Ref - vi_FeedBack
	cPID.vi_PreDerror = 0 ;		//电流PID,前一次,电流误差之差, d_error - PreDerror ;
	
	cPID.v_Ka = VV_KAVALUE;
	cPID.v_Kb = VV_KBVALUE;
	cPID.v_Kc = VV_KCVALUE;
    cPID.vi_RefH = cMax;       
    cPID.Delay = ctime;        
	
	cPID.vi_PreU = 0 ;	    	//电流控制输出值
}
/**********************************************************************
电流环PID算法
查表求偏值
**********************************************************************/
unsigned char  c_PIDCalc()
{ signed char ck, ck1,hh;
  ck = cPID.vi_RefH - cPID.vi_FeedBack;	  //计算本次偏差
return(0);
  if(ck<0) {
    ck1 = ck;
    ck1>>=3;
    hh=Cek[ck1];
    return (hh);
  }
  else return(0);
}

/**********************************************************************
转速环PID算法
**********************************************************************/
signed int v_PIDCalc( unsigned char PWMINT )
{
      
	  int ek, ek1,d_error,tempsep,RR;
	  unsigned char beta;
      
      RR =  PWMOUT;

	  ek = sPID.vi_RefH - sPID.vi_FeedBack;	
      ek1 = ek;			                                    // 本次速度误差   
   if(abs(ek1)>=1) {                               
	  // 遇限削弱积分法
      if  ( abs(ek1)<5 )
		     beta=0;
	  else beta = 1;
	
	  d_error = ek - sPID.vi_PreError;			         	// 本次速度误差与前次误差之差
      sPID.vi_PreDerror = d_error - sPID.vi_PreDerror;		// 更新前一次速度误差之差
      tempsep=sPID.vi_PreDerror;
      tempsep= tempsep>>2;
      d_error=d_error>>2;                                   //运算数据
        if  ( abs(ek1)<40 )
		     ek = ek >> 2; 
	    else ek = ek >> 4; 
	  

	  // PID控制, 更新电机控制输出值 
	  sPID.vi_PreU = ( sPID.v_Ka *ek   + beta * ( sPID.v_Kb * d_error  )) >>5;	
		// 增量的范围转换为(0~400),需要尝试改变移位数
      if(sPID.vi_PreU>=0)                //需要减速
        RR-= abs(sPID.vi_PreU);
        
      else                               //需要加速
       {
        sPID.vi_PreU=abs(sPID.vi_PreU);
        RR+= sPID.vi_PreU;
        }
	  sPID.vi_PreError = ek1;													// 更新前一次速度误差
		
	  // 处理饱和效应
	  if (RR>=Pmax ) PWMOUT = Pmax;  
	  else if ( RR <PWMINT ) PWMOUT = PWMINT;  
      else  PWMOUT = RR ;
  }
     return      ( PWMOUT );

//return 	((sPID.vi_Ref << 1)+ 50 );  // 开环返回值
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -