智能车入门补充篇——电感值处理、转向控制与巡线

冒泡法

冒泡法是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。冒泡排序的时间复杂度为O(n^2)。

	//排序 四路ADC
	for(i = 0;i < ELC_GROUP;i ++)//所有的组都需要排序
	{
		for(k = 0;k < ELC_NUM;k ++)//每个电感号组内排序
		{
			len = ELC_TIME;
			while(len > 1)//排序到只剩下一个元素后不再进行排序
			{
				L_max = 0;
				L_max_index = 0;
				for(j = 0;j < len;j ++)
				{
					if(ELC[i][j][k] > L_max)
					{
						L_max = ELC[i][j][k];//记录最大值
						L_max_index = j;//记录最大值下标
					}
				}
				ELC[i][L_max_index][k] = ELC[i][len - 1][k];//交换数据
				ELC[i][len - 1][k] = L_max;//最大值后移
				len --;
			}
			L_sum[k] += ELC[i][ELC_NEED][k];
		}
	}

归一化

归一化是一种数据预处理方法,用于将不同规模的数据转换为同一规模的数据。常见的归一化方法包括最小-最大归一化和z-score归一化。最小-最大归一化将数据缩放到(0,1]的范围内,z-score归一化将数据转换为均值为0,标准差为1的分布。

注意,归一化的时候尽量避免归到0,否则当0做分母的时候会带来数据处理上的麻烦。

//第一次归一化
	for(i = 0;i < ELC_NUM;i++)
	{
		LNor[i] = LNow[i];
		LNor[i] = LNor[i]*100/LNORMAX[i]; 
	}
	//电磁保护
	if(ELC_Sum_14 <= 55)
		ELC_PROTECT_FLAG = 'T';
	else
		ELC_PROTECT_FLAG = 'F';
	//复制原归一化值
//	LNorm[0] = LNor[0] + 1;
//	LNorm[1] = LNor[1] + 1;
//	LNorm[2] = LNor[2] + 1;
//  LNorm[3] = LNor[3] + 1;
//	for(i = 0; i < ELC_NUM; i++) {
//				LNow[i] = LNow[i] + 1;
//	}
//	LNow[0] = 100*(1150-LNow[0])/(900);
//	LNow[1] = LNow[1] + 1;
//	LNow[2] = LNow[2] + 1;
//	LNow[3] = 100*(910-LNow[3])/650;
	LNow[0] = LNow[0]+1;
	LNow[1] = LNow[1] + 1;
	LNow[2] = LNow[2] + 1;
	LNow[3] = LNow[3]+1;

滤波

滤波是一种信号处理方法,用于去除信号中的噪声或不需要的成分。常见的滤波方法包括低通滤波、高通滤波、带通滤波和带阻滤波等。滤波的实现可以使用数字滤波器或模拟滤波器。

卡尔曼滤波是一种用于估计系统状态的滤波方法,它可以通过对系统的测量值和模型进行融合来提高状态估计的精度。卡尔曼滤波的核心思想是通过对系统状态的预测和测量值的校正来不断更新状态估计值。卡尔曼滤波广泛应用于导航、控制、信号处理等领域。

差比和加权算法

差比和

  1. 读取左右两个电磁感应模块的电磁信号值;
  2. 对左右两个电磁感应模块的电磁信号值进行差分处理,得到一个差值;
  3. 根据差值的正负来判断小车是否偏离了中线;
  4. 根据差值的大小来调整小车的转向角度,使其重新回到中线上。

加权

加权算法是一种常用的循迹算法,它通过对左右两个电磁感应模块的电磁信号进行加权处理,得到一个加权值,用来判断小车是否偏离了中线。根据加权值的大小来调整小车的转向角度,使其重新回到中线上。

直接调节电感差比和差加权算法可能会因无法直观的了解各参数而走弯路,建议先调出一套相对稳定的电感差比和加权方案,然后将其改写为电感差比和差加权算法。

使用差比和差加权算法时,小车在弯道道型出现小幅度过调,此时轻微降低比例系数即可完全拟合。

	//14 23电感作差
	LError[0] = LNow[3]- LNow[0];//横电感值差
	LError[1] = LNow[2]- LNow[1];//斜电感值差
	//14 23电感做和
	LSum[0] = LNow[3] + LNow[0];//横电感值和
	LSum[1] = LNow[2] + LNow[1];//横电感值和
	//差比和计算两种中线
//	ELC_Center_14 = LError[0] * (409600/63) / LSum[0];//横电感
	ELC_Center_14 = LError[0] * 4096 / pow( LSum[0],  1.5);//横电感
//	ELC_Center_23 = LError[1] * 4096 / pow( LSum[1],  1.5);//横电感
//	ELC_Center_23 = LError[1] * 100 / LSum[1];//横电感
//	ELC_Center_1234=100*(0.80*LError[0]+0.20*LError[1])/(0.80*LSum[0]+0.20*LSum[1]);
	//中线限幅 200 
//	ELC_Center_14 = limit_ab(ELC_Center_14,-100,100);
//	ELC_Center_23 = limit_ab(ELC_Center_23,-100,100);
	ELC_Center=ELC_Center_14;

※电感值处理代码

下面是我当时用的处理方案。

#include "inductance.h"
#include <math.h>
uint16	  LNow[10];
float	    LNor[10];
uint16	  LNowinit[10] = {1300,1200,1500,1200,1300,1300,1500,1300,3700,3700};
uint16    LNORMAX[10]  = {2980,2000,2000,2980,3350,1500,1500,3350,3700,3700};
uint16    ELC[ELC_GROUP][ELC_NUM];
//偏差
int32    ELC_Center_14 = 0;
int32    ELC_Center_23 = 0;	
int32    ELC_Center_58 = 0;
int32    ELC_Center0 = 0;
int32    ELC_Center1 = 0;
int32    ELC_Center = 0;
int32	   ELC_CenterRepair = 0;
int32    ELC_Center_Last = 0;
//电感和
uint16    ELC_Sum_14 = 0;
uint16    ELC_Sum_23 = 0;
uint16    ELC_Sum_58 = 0;
uint16    ELC_Sum_1234 = 0;
uint16    ElC_Sum_146=0;
//电感差
int16     ELC_Err_14 = 0;
int16     ELC_Err_23 = 0;
int16     ELC_Err_58 = 0;
//权重系数
float     K1=0.8f;
float     K2=0;
float     K3=0.1f;
float     K4=0.1f;
//电感保护
uint8     ELC_PROTECT_FLAG=0;
 
//电感处理
void Inductor_deal(void)
{ 
	uint16 L_sum[ELC_NUM] = {0,0,0,0,0,0,0,0,0,0,};
	int8 i = 0,k = 0;
	uint16 ELC_max[ELC_NUM] = {4095,4095,4095,4095,4095,4095,4095,4095,4095,4095};
	uint16 ELC_min[ELC_NUM] = {0,0,0,0,0,0,0,0,0,0,};
	//读取ADC
	for(i = 0;i < ELC_GROUP  ;i ++)
	{
			ELC[i][0] = adc_once(ADC1,ADC_12BIT);
			ELC[i][1] = adc_once(ADC2,ADC_12BIT);
			ELC[i][2] = adc_once(ADC3,ADC_12BIT);
			ELC[i][3] = adc_once(ADC4,ADC_12BIT);
			ELC[i][4] = adc_once(ADC5,ADC_12BIT);
			ELC[i][5] = adc_once(ADC6,ADC_12BIT);
			ELC[i][6] = adc_once(ADC7,ADC_12BIT);
			ELC[i][7] = adc_once(ADC8,ADC_12BIT);			
			ELC[i][8] = adc_once(ADC9,ADC_12BIT);
			ELC[i][9] = adc_once(ADC10,ADC_12BIT);
	}
	//挑出最大最小值
	for(k = 0; k < ELC_NUM ; k++) 
	{
		for(i = 0; i < ELC_GROUP; i++) 
		{
			if(ELC[i][k] >= ELC_min[k])
			{
				ELC_min[k]=ELC[i][k];
			}
			if(ELC[i][k] <= ELC_max[k])
			{
				ELC_max[k]=ELC[i][k];
			}
     L_sum[k] += ELC[i][k];
		}
  }
  //第一次归一化
	if(Fork.state == Fork_begin)
	{	
		for(i = 0;i < ELC_NUM;i ++)
		{
			LNow[i] = ((L_sum[i]-ELC_max[i]-ELC_min[i])/ (ELC_GROUP-2));
			LNow[i] = LNow[i]+1;
		} 
  }
	else
	{	
		for(i = 0;i < ELC_NUM;i ++)
		{
			LNow[i] = 2.2*(L_sum[i]-ELC_max[i]-ELC_min[i])/ (ELC_GROUP-2);
			LNow[i] = LNow[i]+1;
		} 
  }		
	//第二次归一化
	for(i = 0;i < ELC_NUM;i++)
	{
		LNor[i] = LNow[i];
		LNor[i] = LNor[i]*100/LNORMAX[i]; 
	} 
	//电磁保护
	if(max_ab(LNow[0],LNow[3])<= 20&&max_ab(LNow[1],LNow[2])<= 20&&max_ab(LNow[4],LNow[7])<= 500&&LNow[6]<40)
		ELC_PROTECT_FLAG = 'T';
	else
		ELC_PROTECT_FLAG = 'F';
//电感值差
	ELC_Err_14 = LNor[3] - LNor[0];
	ELC_Err_23 = LNor[2] - LNor[1];
	ELC_Err_58 = LNor[7] - LNor[4];
//电感值和
	ELC_Sum_14 = LNor[0] + LNor[3];
	ELC_Sum_58 = LNor[4] + LNor[7];
	ELC_Sum_23 = LNor[1] + LNor[2];	
	ELC_Sum_1234= ELC_Sum_14 + ELC_Sum_23;
	
//差比和处理
//	ELC_Center_14=(int16)((float)1000*(sqrt(LNor[3])-sqrt(LNor[0]))/(LNor[3]+ LNor[0]));
//	ELC_Center_23=(int16)((float)1000*(sqrt(LNor[2])-sqrt(LNor[1]))/(LNor[2]+ LNor[1]));
//	ELC_Center_58=(int16)((float)1000*(sqrt(LNor[7])-sqrt(LNor[4]))/(LNor[7]+ LNor[4]));	
//	ELC_Center_14=(int16)((float)1400*(LNor[3]+LNor[2]-(LNor[0]+LNor[1]))/(LNor[3]+LNor[5]+ LNor[0]+LNor[1]+ LNor[2]));
//	ELC_Center_23=(int16)((float)1000*(sqrt(LNor[2])-sqrt(LNor[1]))/(LNor[2]+ LNor[1]));
//	ELC_Center_58=(int16)((float)1400*(sqrt(LNor[7])-sqrt(LNor[4]))/(LNor[7]+LNor[6]+LNor[4]));
//	ELC_Center_23=(int16)((float)100*(LNor[2]-LNor[1])/(LNor[2]+ LNor[1]));
//	ELC_Center_14=(int32)((float)900*(LNor[3]-LNor[0])/(LNor[3]*LNor[0]));
//	ELC_Center_23=(int32)((float)700*(LNor[2]-LNor[1])/(LNor[2]*LNor[1]));
//  ELC_Center_58=(int32)((float)800*(LNor[7]-LNor[4])/(LNor[7]*LNor[4]));
	  ELC_Center_14=(int32)((float)2000*(sqrt(LNor[3])-sqrt(LNor[0]))/(LNor[3]+1.5*LNor[5]+ LNor[0]));
	  ELC_Center_23=(int32)((float)1500*(sqrt(LNor[2])-sqrt(LNor[1]))/(LNor[2]+ LNor[1]));
	  ELC_Center_58=(int32)((float)1800*(sqrt(LNor[7])-sqrt(LNor[4]))/(LNor[7]+LNor[6]+LNor[4]));	
//系数修正
    K2=(float)myabs(8.5f*(limit_ab(ELC_Center_14,-100.0f,100.0f)/1000.0f));
	  K1=(float)(1.30f-K2); 
//		ELC_Center1=(int32)((float)120*(0.4*(LNor[3]-LNor[0])+1.2*(LNor[2]-LNor[1]))/(0.4*(LNor[3]+ LNor[0])+LNor[5]+1.0f*myabs(LNor[2]-LNor[1])));
//	  ELC_Center1=(int32)((float)1650*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+ K2*(sqrt(LNor[2])-sqrt(LNor[1])))/(0.4*(LNor[3]+ LNor[0])+1.5*LNor[5]+0.8f*myabs(LNor[2]-LNor[1])));
//		ELC_Center1=(int32)((float)1650*(0.4*(sqrt(LNor[3])-sqrt(LNor[0]))+(sqrt(LNor[2])-sqrt(LNor[1])))/(0.4*(LNor[3]+ LNor[0])+1.5*LNor[5]+0.8f*myabs(LNor[2]-LNor[1])));
//		ELC_Center0= (int32)((float)1650*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*(LNor[3]+ LNor[0])+1.5*LNor[5]+(K2+0.2)*myabs(LNor[2]-LNor[1])));
//	  ELC_Center0= (int32)((float)1650*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*(LNor[3]+ LNor[0])+1.5*LNor[5]+(K2+0.2)*myabs(LNor[2]-LNor[1])));
//    ELC_Center1= (int32)((float)2300*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*sqrt((LNor[3]*LNor[0]))+1.5*LNor[5]+(K2+0.2)*(LNor[1]+LNor[2])));
	  ELC_Center0= (int32)((float)2200*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*sqrt((LNor[3]*LNor[0]))+1.5*LNor[5]+(K2+0.2)*(LNor[1]+LNor[2])));
	  K3=(float)myabs(5.5f*(limit_ab(ELC_Center0,-100.0f,100.0f)/1000.0f));
		K4=1.0-K3;
		ELC_Center1= K4*ELC_Center0+K3*ELC_Center_23;
//		Elc_boundary_deal();
//		ELC_Center1=ELC_Center0;
/*特殊元素,处理*/	
	if(Cross.FindFlag == 'T')
    {
			if(Cross.state==Crossin)
			{
				ELC_Center1= K4*ELC_Center0+(K3+0.2)*ELC_Center_23;
			}
			else if(Cross.state==Crosson)
			{
				ELC_Center1= K4*ELC_Center0+0.4*ELC_Center_58;
			}		
	  }
	 if(Fork.Dir == 'L'&&Fork.state == Fork_middle){ELC_Center1=0.6*ELC_Center_58+0.4*ELC_Center_14;}
   if(max_ab(LNow[0],LNow[3])>=150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
	 { 
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));}		
		 else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_23));}	
			else
			{
			  if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
				ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
				else
			  ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
			}	
		}
		else	if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])>=80&&max_ab(LNow[4],LNow[7])>=150)
		{ 
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
				if(myabs(ELC_Center_23)>myabs(ELC_Center_14))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));}		
		 else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_23));}	
			else
			{
			  if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
				ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
				else
			  ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
			}	
		}
		else if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
		{
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
			  ELC_Center1=(int16)((float)(2.0*ELC_Center_58));}
			else
				 ELC_Center1 = ELC_Center_Last;	
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_14))
//					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
//					else
//			    ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));}		
//		 else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
//				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
//					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
//			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_23));}	
//			else
//			{
//			  if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
//				ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
//				else
//			  ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
//			}	
		}
		else if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])<150)
		{
			 ELC_Center1 = ELC_Center_Last;		
		}
		ELC_Center=KalmanFilter(&KFP_ELCCenter,ELC_Center1);
    ELC_Center_Last = ELC_Center;
}
	
	
void Elc_boundary_deal(void)
{
    //14正常23正常58正常
		if(max_ab(LNow[0],LNow[3])>=150&&max_ab(LNow[1],LNow[2])>=80&&max_ab(LNow[4],LNow[7])>=150)
		{
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
			ELC_Center0 =(int16)((float)(K1*ELC_Center_14)+(float)((K2+0.0)*ELC_Center_23));}
 
			else  if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0&&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
					ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
			else  if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号
				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
					ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
			
			else
			{ELC_Center0=(int16)((float)(K1*ELC_Center_14)+(float)((K2+0.0)*ELC_Center_23));}
		}
    //14正常23不正常58正常
	  else  if(max_ab(LNow[0],LNow[3])>=150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
 		{
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
			if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
				ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
				else
			  ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
 
			else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
					ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
			    ELC_Center0=(int16)((float)(1.0*ELC_Center_58));}
			
			else
			{
			  if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
				ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
				else
			  ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));
			}		
		}
    //14不正常23正常58正常
    else  if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])>=80&&max_ab(LNow[4],LNow[7])>=150)
		{
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0){//都同号
			if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
				ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
				else
			   ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
			else if(  ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
			ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}	
			else if(  ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号		
			ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}	
			else
			{
			if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
				ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
				else
			  ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));
			}	
		}
    //14不正常23不正常58正常
    else  if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
		{	
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
			   ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.2*ELC_Center_14)+(float)(0.1*ELC_Center_23));}	
 
			else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
					ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}			
			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号	
				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
					ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
			else
					ELC_Center0=(int16)((float)(1.0*ELC_Center_58)+(float)(0.0f*ELC_Center_14)+(float)(0.0f*ELC_Center_23));
		}
		//14不正常23不正常58不正常
    else  if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])<150 )//14不正常23不正常58不正常
		{	
		 ELC_Center0=  ELC_Center_Last;	
		}
}		
	
	
	
	
	
 
 
 
 
 
 
 
//#include "inductance.h"
//#include <math.h>
//uint16	  LNow[10];
//float	    LNor[10];
//uint16	  LNom[10];
//uint16	  LNowinit[10] = {1300,1200,1500,1200,1300,1300,1500,1300,3700,3700};
//uint16    LNORMAX[10]  = {2980,2000,2000,2980,3350,1500,1500,3350,3700,3700};
//uint16    ELC[ELC_GROUP][ELC_NUM];
偏差
//int32    ELC_Center_14 = 0;
//int32    ELC_Center_23 = 0;	
//int32    ELC_Center_58 = 0;
//int32    ELC_Center0 = 0;
//int32    ELC_Center1 = 0;
//int32    ELC_Center = 0;
//int32	   ELC_CenterRepair = 0;
//int32    ELC_Center_Last = 0;
电感和
//uint16    ELC_Sum_14 = 0;
//uint16    ELC_Sum_23 = 0;
//uint16    ELC_Sum_58 = 0;
//uint16    ELC_Sum_1234 = 0;
//uint16    ElC_Sum_146=0;
//uint16    Fork_Sum_1234=0;
电感差
//int16     ELC_Err_14 = 0;
//int16     ELC_Err_23 = 0;
//int16     ELC_Err_58 = 0;
权重系数
//float     K1=0.8f;
//float     K2=0;
//float     K3=0.1f;
//float     K4=0.1f;
电感保护
//uint8     ELC_PROTECT_FLAG=0;
 
电感处理
//void Inductor_deal(void)
//{ 
//	uint16 L_sum[ELC_NUM] = {0,0,0,0,0,0,0,0,0,0,};
//	int8 i = 0,k = 0;
//	uint16 ELC_max[ELC_NUM] = {4095,4095,4095,4095,4095,4095,4095,4095,4095,4095};
//	uint16 ELC_min[ELC_NUM] = {0,0,0,0,0,0,0,0,0,0,};
//	//读取ADC
//	for(i = 0;i < ELC_GROUP  ;i ++)
//	{
//			ELC[i][0] = adc_once(ADC1,ADC_12BIT);
//			ELC[i][1] = adc_once(ADC2,ADC_12BIT);
//			ELC[i][2] = adc_once(ADC3,ADC_12BIT);
//			ELC[i][3] = adc_once(ADC4,ADC_12BIT);
//			ELC[i][4] = adc_once(ADC5,ADC_12BIT);
//			ELC[i][5] = adc_once(ADC6,ADC_12BIT);
//			ELC[i][6] = adc_once(ADC7,ADC_12BIT);
//			ELC[i][7] = adc_once(ADC8,ADC_12BIT);			
//			ELC[i][8] = adc_once(ADC9,ADC_12BIT);
//			ELC[i][9] = adc_once(ADC10,ADC_12BIT);
//	}
//	//挑出最大最小值
//	for(k = 0; k < ELC_NUM ; k++) 
//	{
//		for(i = 0; i < ELC_GROUP; i++) 
//		{
//			if(ELC[i][k] >= ELC_min[k])
//			{
//				ELC_min[k]=ELC[i][k];
//			}
//			if(ELC[i][k] <= ELC_max[k])
//			{
//				ELC_max[k]=ELC[i][k];
//			}
//     L_sum[k] += ELC[i][k];
//		}
//  }
//  //第一次归一化
//	if(Fork.state == Fork_begin)
//	{	
//		for(i = 0;i < ELC_NUM;i ++)
//		{
//			LNow[i] = ((L_sum[i]-ELC_max[i]-ELC_min[i])/ (ELC_GROUP-2));
//			LNow[i] = LNow[i]+1;
//		} 
//  }
//	else
//	{	
//		for(i = 0;i < ELC_NUM;i ++)
//		{
//			LNom[i] = (L_sum[i]-ELC_max[i]-ELC_min[i])/ (ELC_GROUP-2);
//			LNow[i] = 2.2*LNom[i];
//			LNow[i] = LNow[i]+1;
//		} 
//  }		
//	//第二次归一化
//	for(i = 0;i < ELC_NUM;i++)
//	{
//		LNor[i] = LNow[i];
//		LNor[i] = LNor[i]*100/LNORMAX[i]; 
//	} 
//	//电磁保护
//	if(max_ab(LNow[0],LNow[3])<= 50&&max_ab(LNow[1],LNow[2])<= 50&&max_ab(LNow[4],LNow[7])<= 500&&LNow[6]<40)
//		ELC_PROTECT_FLAG = 'T';
//	else
//		ELC_PROTECT_FLAG = 'F';
电感值差
//	ELC_Err_14 = LNor[3] - LNor[0];
//	ELC_Err_23 = LNor[2] - LNor[1];
//	ELC_Err_58 = LNor[7] - LNor[4];
电感值和
//	ELC_Sum_14 = LNor[0] + LNor[3];
//	ELC_Sum_58 = LNor[4] + LNor[7];
//	ELC_Sum_23 = LNor[1] + LNor[2];	
//	ELC_Sum_1234= ELC_Sum_14 + ELC_Sum_23;
//  Fork_Sum_1234= LNom[0] + LNom[1]+LNom[2] + LNom[3];	
差比和处理
	ELC_Center_14=(int16)((float)1000*(sqrt(LNor[3])-sqrt(LNor[0]))/(LNor[3]+ LNor[0]));
	ELC_Center_23=(int16)((float)1000*(sqrt(LNor[2])-sqrt(LNor[1]))/(LNor[2]+ LNor[1]));
	ELC_Center_58=(int16)((float)1000*(sqrt(LNor[7])-sqrt(LNor[4]))/(LNor[7]+ LNor[4]));	
	ELC_Center_14=(int16)((float)1400*(LNor[3]+LNor[2]-(LNor[0]+LNor[1]))/(LNor[3]+LNor[5]+ LNor[0]+LNor[1]+ LNor[2]));
	ELC_Center_23=(int16)((float)1000*(sqrt(LNor[2])-sqrt(LNor[1]))/(LNor[2]+ LNor[1]));
	ELC_Center_58=(int16)((float)1400*(sqrt(LNor[7])-sqrt(LNor[4]))/(LNor[7]+LNor[6]+LNor[4]));
	ELC_Center_23=(int16)((float)100*(LNor[2]-LNor[1])/(LNor[2]+ LNor[1]));
	ELC_Center_14=(int32)((float)900*(LNor[3]-LNor[0])/(LNor[3]*LNor[0]));
	ELC_Center_23=(int32)((float)700*(LNor[2]-LNor[1])/(LNor[2]*LNor[1]));
  ELC_Center_58=(int32)((float)800*(LNor[7]-LNor[4])/(LNor[7]*LNor[4]));
	ELC_Center_14=(int32)((float)2000*(sqrt(LNor[3])-sqrt(LNor[0]))/(LNor[3]+1.5*LNor[5]+ LNor[0]));
	ELC_Center_23=(int32)((float)1500*(sqrt(LNor[2])-sqrt(LNor[1]))/(LNor[2]+ LNor[1]));
//	  ELC_Center_14=(int32)((float)1400*(sqrt(LNor[3])-sqrt(LNor[0]))/(LNor[3]+LNor[5]+ LNor[0]));
//	  ELC_Center_23=(int32)((float)1000*(sqrt(LNor[2])-sqrt(LNor[1]))/(LNor[2]+ LNor[1]));
//	  ELC_Center_58=(int32)((float)1800*(sqrt(LNor[7])-sqrt(LNor[4]))/(LNor[7]+LNor[4]));	
系数修正
//    K2=(float)myabs(6.5f*(limit_ab(ELC_Center_14,-100.0f,100.0f)/1000.0f));
//	  K1=(float)(1.30f-K2); 
		ELC_Center1=(int32)((float)120*(0.4*(LNor[3]-LNor[0])+1.2*(LNor[2]-LNor[1]))/(0.4*(LNor[3]+ LNor[0])+LNor[5]+1.0f*myabs(LNor[2]-LNor[1])));
	  ELC_Center1=(int32)((float)1650*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+ K2*(sqrt(LNor[2])-sqrt(LNor[1])))/(0.4*(LNor[3]+ LNor[0])+1.5*LNor[5]+0.8f*myabs(LNor[2]-LNor[1])));
		ELC_Center1=(int32)((float)1650*(0.4*(sqrt(LNor[3])-sqrt(LNor[0]))+(sqrt(LNor[2])-sqrt(LNor[1])))/(0.4*(LNor[3]+ LNor[0])+1.5*LNor[5]+0.8f*myabs(LNor[2]-LNor[1])));
		ELC_Center0= (int32)((float)1650*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*(LNor[3]+ LNor[0])+1.5*LNor[5]+(K2+0.2)*myabs(LNor[2]-LNor[1])));
	  ELC_Center0= (int32)((float)1650*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*(LNor[3]+ LNor[0])+1.5*LNor[5]+(K2+0.2)*myabs(LNor[2]-LNor[1])));
    ELC_Center1= (int32)((float)2300*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*sqrt((LNor[3]*LNor[0]))+1.5*LNor[5]+(K2+0.2)*(LNor[1]+LNor[2])));
	  ELC_Center0= (int32)((float)2200*(K1*(sqrt(LNor[3])-sqrt(LNor[0]))+(K2+0.2f)*(sqrt(LNor[2])-sqrt(LNor[1])))/(K1*sqrt((LNor[3]*LNor[0]))+1.5*LNor[5]+(K2+0.2)*(LNor[1]+LNor[2])));
	  K3=(float)myabs(5.5f*(limit_ab(ELC_Center0,-100.0f,100.0f)/1000.0f));
		K4=1.0-K3;
		ELC_Center1= K4*ELC_Center0+K3*ELC_Center_23;
//		Elc_boundary_deal();
    ELC_Center0=ELC_Center_58;
//		ELC_Center1=ELC_Center0;
///*特殊元素,处理*/	
//	if(Cross.FindFlag == 'T')
//    {
//			if(Cross.state==Crossin)
//			{
//				ELC_Center1=0.6*ELC_Center0;
//			}
//			else if(Cross.state==Crosson)
//			{
//				ELC_Center1= ELC_Center0;
//			}		
//	  }
	 if(Fork.Dir == 'L'&&Fork.state == Fork_middle){ELC_Center1=0.6*ELC_Center_58+0.4*ELC_Center_14;}
   if(max_ab(LNow[0],LNow[3])>=150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
	 { 
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));}		
		 else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_23));}	
			else
			{
			  if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
				ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
				else
			  ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
			}	
		}
		else	if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])>=80&&max_ab(LNow[4],LNow[7])>=150)
		{ 
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
				if(myabs(ELC_Center_23)>myabs(ELC_Center_14))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));}		
		 else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_58));
					else
			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_23));}	
			else
			{
			  if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
				ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
				else
			  ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
			}	
		}
		else if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
		{
			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
			  ELC_Center1=(int16)((float)(2.0*ELC_Center_58));}
			else
				 ELC_Center1 = ELC_Center_Last;	
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_14))
//					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
//					else
//			    ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));}		
//		 else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
//				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
//					ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
//			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//					ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center1=(int16)((float)(1.2*ELC_Center_58)+(float)(0.3*ELC_Center_23));}	
//			else
//			{
//			  if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
//				ELC_Center1=(int16)((float)(1.2*ELC_Center_14)+(float)(0.3*ELC_Center_23));
//				else
//			  ELC_Center1=(int16)((float)(1.2*ELC_Center_23)+(float)(0.3*ELC_Center_14));
//			}	
		}
		else if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])<150)
		{
			 ELC_Center1 = ELC_Center_Last;		
		}
//		ELC_Center=KalmanFilter(&KFP_ELCCenter,ELC_Center1);
//    ELC_Center_Last = ELC_Center;
//}
//	
//	
//void Elc_boundary_deal(void)
//{
//    //14正常23正常58正常
//		if(max_ab(LNow[0],LNow[3])>=150&&max_ab(LNow[1],LNow[2])>=80&&max_ab(LNow[4],LNow[7])>=150)
//		{
//			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
//			ELC_Center0 =(int16)((float)(K1*ELC_Center_14)+(float)(K2*ELC_Center_23));}
 
//			else  if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0&&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
//				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
//			else  if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
//			
//			else
//			{ELC_Center0=(int16)((float)(K1*ELC_Center_14)+(float)(K2*ELC_Center_23));}
//		}
//    //14正常23不正常58正常
//	  else  if(max_ab(LNow[0],LNow[3])>=150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
// 		{
//			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
//			if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
//				ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
//				else
//			  ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
 
//			else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
//				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
//			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号			
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
//			
//			else
//			{
//			  if(myabs(ELC_Center_14)>myabs(ELC_Center_23))
//				ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_23));
//				else
//			  ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_14));
//			}		
//		}
//    //14不正常23正常58正常
//    else  if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])>=80&&max_ab(LNow[4],LNow[7])>=150)
//		{
//			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0){//都同号
//			if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//				ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//				else
//			   ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
//			else if(  ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
//				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}		
//			else if(  ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号		
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
//			else
//			{
//			if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//				ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//				else
//			  ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));
//			}	
//		}
//    //14不正常23不正常58正常
//    else  if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])>=150)
//		{	
//			if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23>=0 ){//都同号
//			   ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.2*ELC_Center_14)+(float)(0.1*ELC_Center_23));}	
 
//			else if(ELC_Center_14*ELC_Center_58>=0&&ELC_Center_23*ELC_Center_58<0 &&ELC_Center_14*ELC_Center_23<=0){//23异, 14,58同号
//				if(myabs(ELC_Center_14)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_14)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_14));}			
//			else if(ELC_Center_14*ELC_Center_58<0&&ELC_Center_23*ELC_Center_58>=0 &&ELC_Center_14*ELC_Center_23<=0){//14异, 23,58同号	
//				if(myabs(ELC_Center_23)>myabs(ELC_Center_58))
//					ELC_Center0=(int16)((float)(0.7*ELC_Center_23)+(float)(0.3*ELC_Center_58));
//					else
//			    ELC_Center0=(int16)((float)(0.7*ELC_Center_58)+(float)(0.3*ELC_Center_23));}		
//			else
//		    ELC_Center0=  ELC_Center_Last;	
//		}
//		//14不正常23不正常58不正常
//    else  if(max_ab(LNow[0],LNow[3])<150&&max_ab(LNow[1],LNow[2])<80&&max_ab(LNow[4],LNow[7])<150 )//14不正常23不正常58不正常
//		{	
//		 ELC_Center0=  ELC_Center_Last;	
//		}
//}		
//	
//	
//	
//	
//	

经典PID

  • PID控制器是一种常见的控制器,它可以通过对系统的反馈信号进行处理,来控制系统的输出。在PID控制器中,P代表比例控制,I代表积分控制,D代表微分控制。
  • 比例、积分、微分控制,简称PID控制,又称PID调节。PID控制的基本方法是根据系统输入与预定输出的偏差的大小运用比例、积分、微分计算出一个控制量,将这个控制量输入系统,获得输出量,通过反馈回路再次检测该输出量的偏差,循环上述过程,以使输出达到预定值。 PID控制器问世至今已有近 70年历史,其有着结构简单、稳定性好、工作可靠、调整方便等优点。
  当被控对象的结构和参数不能完全掌握,或得不到精确的数学模型时,控制理论的其它技术难以采用时,系统控制器的结构和参数必须依靠经验和现场调试来确定,这时应用PID控制技术最为方便。即当我们不完全了解一个系统和被控对象,或不能通过有效的测量手段来获得系统参数时,也适合用PID控制技术。

  • 连续型PID的公式:
  即对err(t)分别进行比例,积分,微分运算之后进行加权求和得到输出U(t)。
  • 由于单片机控制是采样控制,只能根据采样时刻的偏差控制输出量而不能计算连续输出量,所以要采用离散化的 PID算法。离散数字 PID分为位置式和增量式两种。

  而增量式PID算法对应可由位置式推出:

  具体的代码实现为:

float Realize_PID(PIDTypeDef_t *pid, float get, float set) {
pid->Now_Val = get;
pid->Ex_Val = set;
pid->Err_Now = pid->Ex_Val - pid->Now_Val;

   pid->Output_p = pid->Kp * pid->Err_Now;
   pid->Output_i += pid->Ki * pid->Err_Now;
   pid->Output_d = pid->Kd * (pid->Err_Now - pid->Err_Last);
   pid->Output = pid->Output_p + pid->Output_i + pid->Output_d;

   pid->Err_Last = pid->Err_Now;
   
   return pid->Output;
}

float Incremental_PID(PIDTypeDef_t *pid, float get, float set) {
pid->Now_Val = get;
pid->Ex_Val = set;
pid->Err_Now = pid->Ex_Val - pid->Now_Val;

   pid->Output_p = pid->Kp * (pid->Err_Now - pid->Err_Last);
   pid->Output_i = pid->Ki * pid->Err_Now;
   pid->Output_d = pid->Kd * (pid->Err_Now - 2.000f * pid->Err_Last + pid->Err_LastLast);
   pid->Output += pid->Output_p + pid->Output_i + pid->Output_d;

   pid->Err_Last = pid->Err_Now;
   pid->Err_LastLast = pid->Err_Last;
   
   return pid->Output;
}

• 公式中没有体现周期T,其实考虑到周期是一个常数,就直接合在了系数中。采样周期和控制周期都会影响系数。

  • 在PID算法中,比例环节 P 的作用是成比例地反映控制系统的偏差信号e(t),一旦产生偏差,比例控制环节立即产生控制作用以减小偏差;积分环节 I 的作用是消除静差,提高系统的无差度。微分环节 D 的作用是反映偏差信号的变化趋势,能够在偏差信号变化之前先引入一个有效的早期修正信号来提前修正偏差,加快系统的动作速度,减少调节时间。

  • 所谓增量式PID 是指数字控制器的输出只是控制量的增量△u(k)。增量式PID优点在于,由于输出的是增量所以误动作时影响小,必要时可用逻辑判断的方法关掉。另外由于控制增量△u(k)的确定仅与最近k次的采样值有关,所以较容易通过加权处理而获得比较好的控制效果。

  • 在PID参数的选择上,公认的常规方案是,过程控制系统(如电机控制)因较慢的响应常采用PI控制,突出积分项的作用,而随动控制系统(如舵机控制)为了达到较快的响应常采用PD控制。
  • 大多智能车队会推荐速度环使用增量式PID,方向环使用位置式PID,这是由于增量PID由于也不容易造成电机的正反转切换。但我们认为,在合适的参数下,增量式PID与位置式PID应该是可以等价。

改进式PID

死区

死区是一种常见的控制器设计技术,它可以避免系统在小范围内的震荡。具体来说,死区是指在控制器输出的范围内设置一个区域,当系统的输出在这个区域内时,控制器不进行调整,从而避免了系统的震荡。

变速积分

变速积分是一种针对系统存在积分饱和的情况下的PID控制器。它通过对积分项进行变速,来避免积分项在系统运动过程中出现饱和的情况。具体来说,变速积分会根据系统的运动状态来调整积分项的速度。

有效偏差法

有效偏差法是一种针对系统存在偏差的情况下的PID控制器。它通过对偏差进行处理,来提高系统的响应速度和稳定性。具体来说,有效偏差法会根据系统的运动状态来调整偏差项的大小。

遇限削弱积分

遇限削弱积分是一种针对系统存在积分饱和的情况下的PID控制器。它通过对积分项进行处理,来避免积分项在系统运动过程中出现饱和的情况。具体来说,遇限削弱积分会根据系统的运动状态来调整积分项的大小。

专家PID

专家PID是一种针对复杂系统的PID控制器。它通过对系统的特性进行分析,来设计出最优的PID控制器。具体来说,专家PID会根据系统的特性来调整PID控制器的参数。

if (pid->Err_ABS < S_Err) {
   //小偏差 较小误差, 调小比例
   pid->Output = Offine_K * pid->Output;
} else if (pid->Err_ABS > L_Err) {
//大偏差
   //串联BangBang-PID
pid->Output = (pid->Err_Now > 0) ? (9500) : (-9500);
} else {
//正常偏差
if ((pid->Err_Now * (pid->Err_Now - pid->Err_Last) > 0 && pid->Err_Last * (pid->Err_Last - pid->Err_LastLast) > 0) || (pid->Err_Now - pid->Err_Last) == 0) {
       //偏差在朝向偏差绝对值增大的方向变化(偏差越来越大), 或者偏差一直为某一固定值
       if (pid->Err_ABS > Mid_Err) {
           //控制器实施较强的控制作用
           pid->Output = Online_K * pid->Output;
      } else {
      //但是偏差绝对值本身并不是很大
           pid->Output = pid->Output + 0;
      }
} else if(pid->Err_Now * (pid->Err_Now - pid->Err_Last) < 0 && (pid->Err_Now - pid->Err_Last) * (pid->Err_Last - pid->Err_LastLast) > 0 || (pid->Err_Now == 0 && pid->Err_Last == 0) {
       //偏差的绝对值向减小的方向变化,或者已经达到平衡状态
       //此时可以保持控制器输出不变
} else if(pid->Err_Now * (pid->Err_Now - pid->Err_Last) < 0 && ((pid->Err_Now - pid->Err_Last) * (pid->Err_Last - pid->Err_LastLast) < 0)) {
       //偏差处于极值极限状态
       if (pid->Err_ABS > Mid_Err) {
           pid->Output = Online_K * pid->Output;
      } else {
           //但是偏差绝对值本身并不是很大
           pid->Output = pid->Output + 0;
      }
  } else {
       //正常情况
       pid->Output = pid->Output + 0;
  }
}

模糊PID

模糊PID是一种针对复杂系统的PID控制器。它通过对系统的特性进行模糊化处理,来设计出最优的PID控制器。具体来说,模糊PID会根据系统的特性来调整PID控制器的参数。

//------------------------------------ 模糊PID ---------------------------------------------//

/*论域*/
#define 	NB		-6 
#define 	NM 		-4
#define 	NS		-2
#define 	ZO		0
#define 	PS 		2
#define 	PM		4
#define 	PB		6

int8 ruleKp[7][7] = {
	
/*  \ Ec */ 	 /* NB 负大   NM 负中  NS 负小   ZO 零  PS 正小  PM 正中  PB 正大 */	
/* E \ */		  	/* -6        -4        -2      0        2        4         6*/
/* NB 负大 -6 */	  PB	,	 PB    ,  PM    ,  PM   ,   PS   ,   ZO   ,   ZO   ,
/* NM 负中 -4 */	  PB	,	 PB    ,  PM    ,  PS   ,   PS   ,   ZO   ,   NS   ,
/* NS 负小 -2 */	  PM	,	 PM    ,  PM    ,  PS   ,   ZO   ,   NS   ,   NS   ,
/* ZO 零    0 */	  PM	,	 PM    ,  PS    ,  ZO   ,   NS   ,   NM   ,   NM   ,
/* PS 正小  2 */	  PS	,	 PS    ,  ZO    ,  NS   ,   NM   ,   NM   ,   NM   ,
/* PM 正中  4 */	  PS	,	 ZO    ,  NS    ,  NS   ,   NM   ,   NB   ,   NB   ,
/* PB 正大  6 */	  ZO	,	 ZO    ,  NS    ,  NM   ,   NM   ,   NB   ,   NB   ,
};

/*Ki规则表*/
int8 ruleKi[7][7] = {
	
/*  \ Ec */ 	 /* NB 负大   NM 负中  NS 负小   ZO 零  PS 正小  PM 正中  PB 正大 */	
/* E \ */		  	/* -6        -4        -2      0        2        4         6*/
/* NB 负大 -6 */	  NB	,	 NB    ,  NM    ,  NM   ,   NS   ,   ZO   ,   ZO   ,
/* NM 负中 -4 */	  NB	,	 NB    ,  NM    ,  NM   ,   NS   ,   ZO   ,   ZO   ,
/* NS 负小 -2 */	  NB	,	 NM    ,  NS    ,  NS   ,   ZO   ,   PS   ,   PS   ,
/* ZO 零    0 */	  NM	,	 NM    ,  NS    ,  ZO   ,   PS   ,   PM   ,   PM   ,
/* PS 正小  2 */	  NM	,	 NS    ,  ZO    ,  PS   ,   PS   ,   PM   ,   PM   ,
/* PM 正中  4 */	  ZO	,	 ZO    ,  PS    ,  PS   ,   PM   ,   PB   ,   PB   ,
/* PB 正大  6 */	  ZO	,	 ZO    ,  PS    ,  PM   ,   PM   ,   PB   ,   PB   ,	

};

/*Kd规则表*/
int8 ruleKd[7][7] = {
	
/*  \ Ec */ 	 /* NB 负大   NM 负中  NS 负小   ZO 零  PS 正小  PM 正中  PB 正大 */	
/* E \ */		  	/* -6        -4        -2      0        2        4         6*/
/* NB 负大 -6 */	  NB	,	 NB    ,  NM    ,  NB   ,   NM   ,   ZO   ,   ZO   ,
/* NM 负中 -4 */	  NB	,	 NB    ,  NM    ,  NM   ,   NS   ,   ZO   ,   PS   ,
/* NS 负小 -2 */	  NM	,	 NM    ,  NS    ,  NS   ,   ZO   ,   PS   ,   PS   ,
/* ZO 零    0 */	  NM	,	 NM    ,  NS    ,  ZO   ,   PS   ,   PM   ,   PM   ,
/* PS 正小  2 */	  NS	,	 NS    ,  ZO    ,  PS   ,   PS   ,   PM   ,   PM   ,
/* PM 正中  4 */	  NS	,	 ZO    ,  PS    ,  PM   ,   PM   ,   PB   ,   PB   ,
/* PB 正大  6 */	  ZO	,	 ZO    ,  PM    ,  PB   ,   PM   ,   PB   ,   PB   ,	
};

//statement
FuzzyPIDTypedef  ServoFuzzyPID;


/*隶属度计算函数*/
void Calculate_Membership(float qv,int * index,float *ms)
{
  if((qv>=NB)&&(qv<NM))
  {
    index[0]=0;
    index[1]=1;
    ms[0]=-0.5*qv-2.0;  //y=-0.5x-2.0
    ms[1]=0.5*qv+3.0;   //y=0.5x+3.0
  }
  else if((qv>=NM)&&(qv<NS))
  {
    index[0]=1;
    index[1]=2;
    ms[0]=-0.5*qv-1.0;  //y=-0.5x-1.0
    ms[1]=0.5*qv+2.0;   //y=0.5x+2.0
  }
  else if((qv>=NS)&&(qv<ZO))
  {
    index[0]=2;
    index[1]=3;
    ms[0]=-0.5*qv;      //y=-0.5x
    ms[1]=0.5*qv+1.0;   //y=0.5x+1.0
  }
  else if((qv>=ZO)&&(qv<PS))
  {
    index[0]=3;
    index[1]=4;
    ms[0]=-0.5*qv+1.0;  //y=-0.5x+1.0
    ms[1]=0.5*qv;       //y=0.5x
  }
  else if((qv>=PS)&&(qv<PM))
  {
    index[0]=4;
    index[1]=5;
    ms[0]=-0.5*qv+2.0;  //y=-0.5x+2.0
    ms[1]=0.5*qv-1.0;   //y=0.5x-1.0
  }
  else if((qv>=PM)&&(qv<=PB))
  {
    index[0]=5;
    index[1]=6;
    ms[0]=-0.5*qv+3.0;  //y=-0.5x+3.0
    ms[1]=0.5*qv-2.0;   //y=0.5x-2.0
  }
}

//模糊PID实现
float FuzzyPID(float *pid_param, FuzzyPIDTypedef *pid,float _nowval,float _exval)
{
	//读取数值
	pid->kp1 = pid_param[FUZZYPID_Kp1];
	pid->ki1 = pid_param[FUZZYPID_Ki1];
	pid->kd1 = pid_param[FUZZYPID_Kd1];
	pid->kp2 = pid_param[FUZZYPID_Kp2];
	pid->ki2 = pid_param[FUZZYPID_Ki2];
	pid->kd2 = pid_param[FUZZYPID_Kd2];
	pid->sumError = pid_param[FUZZYPID_SumMax];
	pid->exval = _exval;
	pid->nowval = _nowval;
	//更新当前误差
	pid->nowError =  pid->exval - pid->nowval;
	pid->ErrorInc = pid->nowError - pid->lastError;
	//误差以及误差增量限幅
	pid->nowError = limit(pid->nowError,pid->nowErrmax);
	pid->ErrorInc = limit(pid->ErrorInc,pid->ECmax);
	TEST=myabs(pid->nowError);
	if(myabs(MAX_ERROR)<=myabs(TEST))
	{MAX_ERROR=myabs(TEST);}
	/********  模糊化  *******/
	//量化 论域{-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6}
	pid->E_Quantized  = 6.0 * pid->nowError / pid->nowErrmax;
	pid->EC_Quantized = 6.0 * pid->ErrorInc / pid->ECmax;
	//计算隶属度
	Calculate_Membership(pid->E_Quantized,pid->E_Index,pid->E_Membership);
	Calculate_Membership(pid->EC_Quantized,pid->EC_Index,pid->EC_Membership);
	/********  解模糊  *******/
	//计算kx2的系数
	pid->kp2k = 
		pid->E_Membership[0] * pid->EC_Membership[0] * ruleKp[pid->E_Index[0]][pid->EC_Index[0]] +\
		pid->E_Membership[0] * pid->EC_Membership[1] * ruleKp[pid->E_Index[0]][pid->EC_Index[1]] +\
		pid->E_Membership[1] * pid->EC_Membership[0] * ruleKp[pid->E_Index[1]][pid->EC_Index[0]] +\
		pid->E_Membership[1] * pid->EC_Membership[1] * ruleKp[pid->E_Index[1]][pid->EC_Index[1]] ;
	pid->ki2k = 
		pid->E_Membership[0] * pid->EC_Membership[0] * ruleKi[pid->E_Index[0]][pid->EC_Index[0]] +\
		pid->E_Membership[0] * pid->EC_Membership[1] * ruleKi[pid->E_Index[0]][pid->EC_Index[1]] +\
		pid->E_Membership[1] * pid->EC_Membership[0] * ruleKi[pid->E_Index[1]][pid->EC_Index[0]] +\
		pid->E_Membership[1] * pid->EC_Membership[1] * ruleKi[pid->E_Index[1]][pid->EC_Index[1]] ;
	pid->kd2k = 
		pid->E_Membership[0] * pid->EC_Membership[0] * ruleKd[pid->E_Index[0]][pid->EC_Index[0]] +\
		pid->E_Membership[0] * pid->EC_Membership[1] * ruleKd[pid->E_Index[0]][pid->EC_Index[1]] +\
		pid->E_Membership[1] * pid->EC_Membership[0] * ruleKd[pid->E_Index[1]][pid->EC_Index[0]] +\
		pid->E_Membership[1] * pid->EC_Membership[1] * ruleKd[pid->E_Index[1]][pid->EC_Index[1]] ;
	//计算总的kx
	pid->kp = pid->kp1 + pid->kp2 * (myabs(pid->kp2k) / 6.0f);//除以论域极值 计算的是kp增量百分比
	pid->ki = pid->ki1 + pid->ki2 * (myabs(pid->ki2k) / 6.0f);
	pid->kd = pid->kd1 + pid->kd2 * (myabs(pid->kd2k) / 6.0f);//除以论域极值 计算的是kp增量百分比
	//计算输出
	pid->out = \
		pid->kp * (float)pid->nowError + \
		pid->ki * (float)(pid->nowError + pid->lastError + pid->preError) + \
		pid->kd * (float)(pid->nowError - 0.7 * pid->lastError - 0.3 * pid->preError);
	//更新误差
	pid->preError = pid->lastError;
	pid->lastError = pid->nowError;
	//输出限幅
	pid->out = limit(pid->out,pid->outmax);
	//输出
	return pid->out;
}



舵机转向偏差计算

/**
*@Name			:DirectionControl
*@Description 	:DirectionControl
*@Param			:None
*@Return		:None
*@Sample		:DirectionControl();
**/
void DirectionControl(void)
{
    if (CarInfo.ClosedLoopMode==DirectLoop || \
            CarInfo.ClosedLoopMode==AllLoop || \
            CarInfo.ClosedLoopMode==SpeedLoop) {
        if (CarInfo.Protect_Flag=='F'){
                DirectionOut = FuzzyPID(ServoFuzzyPIDParam[0],&ServoFuzzyPID, ELC_CenterRepair, 0);
//                DirectionOut = Position_PID(ServoNonLinearPIDParam[0],&ServoNonLinearPID,0,ELC_CenterRepair);

        }
        else {
            DirectionOut = 0;
        }
        ServoAdd = DirectionOut;
        ServoWrite();
    }
    else        return;
}

电机差速控制

电机差速控制是指通过控制车辆两侧电机的转速差异来实现车辆的转向和转弯。一般来说,当车辆需要向左转时,右侧电机的转速会比左侧电机的转速快,从而使车辆向左转弯。反之,当车辆需要向右转时,左侧电机的转速会比右侧电机的转速快,从而使车辆向右转弯。

阿克曼系数是指车辆转向时前轮转角与后轮转角之间的比值。在智能车竞赛中,阿克曼系数的大小会影响车辆的转弯半径和稳定性。一般来说,阿克曼系数越大,车辆的转弯半径越小,但稳定性也会相应降低。反之,阿克曼系数越小,车辆的转弯半径越大,但稳定性也会相应提高。

/**
*@Name			:DiffSpeedControl
*@Description 	:DiffSpeedControl差速控制
*@Param			:None
*@Return		:NULL
*@Sample		:DiffSpeedControl();
**/
void DiffSpeedControl(void)
{
    if (CarInfo.ClosedLoopMode == AllLoop && CarInfo.Protect_Flag == 'F') {
			if(ServoAdd<=-70) {//右转
				Speed_diff_l=ExSpeed;
				Speed_diff_r=(int)(ExSpeed*(1+((float)Ackerman_k/1000)*tan((float)ServoAdd*3.14/3136)/0.396));
			}
			else if(ServoAdd>=70) {//左转
				Speed_diff_l=(int)(ExSpeed*(1-((float)Ackerman_k/1000)*tan((float)ServoAdd*3.14/3136)/0.396));
				Speed_diff_r=ExSpeed;
			}
			else {
				Speed_diff_l=ExSpeed;
				Speed_diff_r=ExSpeed;
			}
	}
	else
	{
		ExSpeed_L=ExSpeed;
		ExSpeed_R=ExSpeed;
	}
}

※转向控制代码

#include "control.h"

CarInfoTypedef   CarInfo;

//定时器中断 1ms
uint16  NormalSpeed =320;
uint16  NormalSpeed1 =320;
uint16  NormalSpeed2 =320;
int16   ExSpeed=200;
int16   ExSpeedAdd=0;
int     Ackerman_k =250;//左右差速系数
int     Ackerman_k1 =250;
int     Ackerman_k2 =230;
int16   ExSpeed_L  = 0;
int16   ExSpeed_R  = 0;
int16   SpeedOut_L =  0;
int16   SpeedOut_R =  0;
int16   DirectionOut = 0;
uint16 Outgargespeed=330;
uint16 IslandSpeed =320;
uint16 Fork1=260;
uint16 Fork2=320;
uint16 Fork3=320;
uint16 LFork1=250;
uint16 LFork2=250;
uint16 RampSpeed =160;
uint16 LongStraightSpeed=350;
uint16 Ingargespeed1=300;
uint16 Ingargespeed2=300;
uint16 Cnt;
int16  Coe=300;
int16  AddMax=15;
uint8  flag1 = 0;
uint8  StartCar = 1;
uint8  CarOutProtect='T';

//初始化一些设置
uint8 CarSystem_Init(void)
{
	//设置标志
	CarInfo.Protect_Flag = 'F';
	//ret
	return 1;
}

/**
*@Name			:Timer6_IT
*@Description 	:Timer6_IT基本定时器6中断服务函数,用于电机控制及其他中断服务
*@Param			:None
*@Return		:NULL
*@Sample		:Timer6_IT();
**/
void Timer_IT(void)
{
		KeyScanInt();
		if(!flag1){
		Cnt++; 
		Beep_IntCnt();
		Car_Protect();	
  //--------------------------电磁处理和元素判断-------------------------------//
		TOFGetData();//获取激光测距的值
		Inductor_deal();//获取前瞻电感值及滤波归一化等
		Ele_judge();//元素识别与识别后的处理
  //----------------------------陀螺仪数值获取---------------------------------//
	if(Cnt% 5== 0 ) {
		ICM20602DataFilter();//陀螺仪获取数据
		ICM_I_Int();//陀螺仪积分
	}
	
	if(!StartCar){
  //-------------------------------方向控制------------------------------------//
	if(Cnt% 5== 0) {
		DirectionControl();//舵机打角
	}
  //-------------------------------速度控制------------------------------------//
		ExSpeedControl();//顺序不能错
		DiffSpeedControl();
		SpeedControl();//电机控制
	}
  //------------------------------清零计数------------------------------------//
	if(Cnt>= 1000)	Cnt= 0;
	}

}


void MoBan_Speed_Up(void)
{
	if(
	sqrt(myabs(LNor[L1]-LNor[L5]))+sqrt(myabs(LNor[L4]-LNor[L8]))+sqrt(myabs(LNor[L6]-LNor[L7]))<=10	
	)
	{
	ExSpeed=ExSpeed+100;
	BeepTick(1, 100);		
	}
}

//舵机PID控制
void DirectionControl(void)
{

		if(OutGarage.state == GarageOutTurn||OutGarage.state ==GarageIn\
		||Island.state == IslandInTurn||Island.state ==IslandOutTurn \
		||Fork.state == Fork_in||Fork.state == Fork_end\
		||InGarage.state == GarageInTurn||InGarage.state == GarageStraighten||InGarage.state == GarageEnd\
		||BackGarage.state == BackGarageForward||BackGarage.state == BackGarageTurn||BackGarage.state == BackGarageBackStraight){
					ServoAdd=Forced;
		}
		else
		{
			if(Island.FindFlag == 'T'){
				DirectionOut = FuzzyPID(ServoFuzzyPIDParam[1],&ServoFuzzyPID, 0, ELC_Center);
//      DirectionOut = Position_PID(ServoNonLinearPIDParam[0],&ServoNonLinearPID,ELC_Center,0);
			}
			else if(Fork.FindFlag == 'T')
			{
				DirectionOut = FuzzyPID(ServoFuzzyPIDParam[2],&ServoFuzzyPID, 0, ELC_Center);
			}
			else 
			{
				DirectionOut = FuzzyPID(ServoFuzzyPIDParam[0],&ServoFuzzyPID, 0, ELC_Center);
			}
			  ServoAdd = DirectionOut;
		}
		/*********************************/
//		if(Island.state == IslandOutTurn){
//		ServoAdd= limit_ab(ServoAdd,620,720) ;
//		}
//		if(Island.state == IslandIn){
//		ServoAdd= limit_ab(ServoAdd,620,720) ;
//		}
//		if(Cross.state==Crossin){
//		ServoAdd= limit_ab(ServoAdd,0,800) ;
//		}
//		if(Island.state == IslandOutCenter)
//		{
//		ServoAdd= limit_ab(ServoAdd,-500,300) ;
//		}
			 ServoWrite();
}



//差速控制
void DiffSpeedControl(void)
{
    if (CarInfo.Protect_Flag == 'F'&&Island.FindFlag == 'F'&&Fork.FindFlag == 'F'){
			if(ServoAdd<=-70) {//右转
				ExSpeed_L=ExSpeed;
				ExSpeed_R=(int)(ExSpeed*(1+((float)Ackerman_k/1000)*tan((float)ServoAdd*3.14/3136)/0.396));
			}
			else if(ServoAdd>=0) {//左转
				ExSpeed_L=(int)(ExSpeed*(1-((float)Ackerman_k/1000)*tan((float)ServoAdd*3.14/3136)/0.396));
				ExSpeed_R=ExSpeed;
			}
			else {
				ExSpeed_L=ExSpeed;
				ExSpeed_R=ExSpeed;
			}
	  }

}

//速度PID控制
void SpeedControl(void)
{
    EncoderRead();
    if (CarInfo.Protect_Flag == 'F') {
//				if(Wheel_L.SpeedNow-ExSpeed>50){SpeedOut_L=-999;}//梆梆算法
//				else if(Wheel_R.SpeedNow-ExSpeed>50)SpeedOut_R =-999;
//				else
//				{

		/*正常情况*/
		SpeedOut_L = SimpleIncremental_PID(&SpeedPIDParam[0][0],&SpeedPIDLeft,ExSpeed_L,Wheel_L.SpeedNow);
		SpeedOut_R = SimpleIncremental_PID(&SpeedPIDParam[0][0],&SpeedPIDRight,ExSpeed_R,Wheel_R.SpeedNow);

		/*特殊情况*/
		if (BackGarage.FindFlag=='T') {
		SpeedOut_L = SimpleIncremental_PID(&SpeedPIDParam[1][0],&SpeedPIDLeft,ExSpeed_L,Wheel_L.SpeedNow);
		SpeedOut_R = SimpleIncremental_PID(&SpeedPIDParam[1][0],&SpeedPIDRight,ExSpeed_R,Wheel_R.SpeedNow);

		}
//				}
    }
    else if (CarInfo.Protect_Flag == 'T'){//速度控零保护
			if (myabs(Wheel_L.SpeedNow)>= 400 || myabs(Wheel_R.SpeedNow) >= 400) {
					SpeedOut_L = 0;
					SpeedOut_R = 0;
			}
			else {
			SpeedOut_L = SimpleIncremental_PID(&SpeedPIDParam[0][0],&SpeedPIDLeft,0,Wheel_L.SpeedNow);
			SpeedOut_R =SimpleIncremental_PID(&SpeedPIDParam[0][0],&SpeedPIDRight,0,Wheel_R.SpeedNow);
			}
    }
		pwm_l = SpeedOut_L;
		pwm_r = SpeedOut_R;
		MotorWrite();
}

//冲出赛道电磁削减保护
int16 CarOutProtectCnt = 0;
void Car_Protect(void)
{
	//---------------电磁保护--------------//&&Fork.FindFlag   == 'F'&&Island.FindFlag == 'F'
	if(CarOutProtect=='T')
	{
	if(ELC_PROTECT_FLAG == 'T'&&OutGarage.Flag == 'T'&&BackGarage.FindFlag=='F')
	{
		CarOutProtectCnt ++;
	}
	else
	{
		CarOutProtectCnt=0;
	}
	if(CarOutProtectCnt >=50)
	{
		CarInfo.Protect_Flag = 'T';
	}
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/177227.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

国内怎么投资黄金,炒黄金有哪些好方法?

随着我国综合实力的不断强大&#xff0c;投资市场的发展也日臻完善&#xff0c;现已成为了国际黄金市场的重要组成部分&#xff0c;人们想要精准判断金市走向&#xff0c;就离不开对我国经济等信息的仔细分析。而想要有效提升盈利概率&#xff0c;人们还需要掌握国内黄金投资的…

centos无法进入系统之原因解决办法集合

前言 可爱的小伙伴们&#xff0c;由于精力有限&#xff0c;暂时整理了两类。如果没有你遇到的问题也没有关系&#xff0c;欢迎底下留言评论或私信&#xff0c;小编看到后第一时间帮助解决 一. Centos 7 LVM xfs文件系统修复 情况1&#xff1a; [sda] Assuming drive cache:…

Docker Swarm总结(2/3)

目录 8、service 操作 8.1 task 伸缩 8.2 task 容错 8.3 服务删除 8.4 滚动更新 8.5 更新回滚 9、service 全局部署模式 9.1 环境变更 9.2 创建 service 9.3 task 伸缩 10、overlay 网络 10.1 测试环境 1搭建 10.2 overlay 网络概述 10.3 docker_gwbridg 网络基础…

​极氪,中国传统汽车品牌电动化的样板间

这篇文章早就想写了&#xff0c;因为太忙的原因就一直跳票&#xff0c;正好最近两件事的出现&#xff0c;又触发了想写这篇文章的冲动。 两件事主要是&#xff1a; 一&#xff0c;10 月份各家陆续公布了单月销量以及累计销量&#xff1b; 二&#xff0c;极氪在北京正式发布了 …

算法刷题-动态规划-1

算法刷题-动态规划-1 不同路径不同路径||方法一&#xff1a;方法二 第N个泰波那契数递归写法滚动数组 三步问题递归操作滚动数组 使用最小画法爬楼梯递归 解码方法方法一方法二&#xff1a;&#xff08;大佬讲解&#xff09; 不同路径 //机器人不同的路径进入到指定的地点 publ…

OSG文字-渐变文字(4)

渐变文字(osgText::FadeText类)继承自osgText::Text类继承关系图如图9-6所示 图9-6 osgText::FadeText的继承关系图 从继承关系图中可以看出&#xff0c;它继承自osgText::Text类&#xff0c;因此&#xff0c;它具备一般文字属性的设置方法这里不再重复说明。创建渐变文字与一般…

【JavaEE】Spring更简单的存储和获取对象(类注解、方法注解、属性注入、Setter注入、构造方法注入)

一、存储Bean对象 在这篇文章中我介绍了Spring最简单的创建和使用&#xff1a;Spring的创建和使用 其中存储Bean对象是这样的&#xff1a; 1.1 配置扫描路径 想要成功把对象存到Spring中&#xff0c;我们需要配置对象的扫描包路径 这样的话&#xff0c;就只有被配置了的包…

详解Python中哈希表的使用。站在开发者角度,与大家一起探究哈希的世界。

文章目录 1. 前言2. 哈希表2.1 哈希函数2.2 哈希算法2.3 常见哈希算法2.4 哈希冲突 3.总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面…

【数据库】数据库中的备份与恢复,保障容灾时的数据一致性与完整性

数据库的备份机制 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定期…

【LeetCode刷题】-- 29.两数相除

29.两数相除 思路&#xff1a; class Solution {public int divide(int dividend, int divisor) {//考察被除数为最小值的情况if(dividend Integer.MIN_VALUE){//被除数为最小值&#xff0c;除数是1&#xff0c;返回最小值if(divisor 1){return Integer.MIN_VALUE;}//除数是-…

2023年亚太杯数学建模思路 - 案例:粒子群算法

文章目录 1 什么是粒子群算法&#xff1f;2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法&#xff1f; 粒子群算法&#xff08;Pa…

阿里云跨账号建立局域网

最近有活动&#xff0c;和好友一并薅了下阿里云的羊毛。琢磨着两台机器组一个局域网&#xff0c;于是有了这个需求&#xff0c;把步骤记录一下&#xff1a; 假设两台机器叫A和B&#xff0c;我们开始进行建立和组网 1. 建立ECS 把A机器公共环境装好&#xff0c;然后使用《实例与…

ROSNS3(一)

https://github.com/malintha/rosns3 第一步&#xff1a;clone和构建rosns3客户端 第二步&#xff1a;运行 最详细的ubuntu 安装 docker教程 - 知乎 1. unable to find source space /home/muta/src 解决方法&#xff1a; 将副将将碰到的bug&#xff0c;解决方法_#include &…

【蓝桥杯省赛真题45】Scratch九宫格游戏 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解

目录 scratch九宫格游戏 一、题目要求 编程实现 二、案例分析 1、角色分析

csdn最新最全pytest系列——pluggy插件源码解读(一)HookspecMarker类和HookimplMarker类分析

简介 pluggy是一个非常优秀的插件系统&#xff0c;它是理解pytest的核心&#xff0c;只有理解了pluggy的原理&#xff0c;才能更好的理解和使用pytest&#xff0c;否则见到了pytest的很多应用都会感觉很难理解 pluggy插件总共的代码量不足一千行&#xff0c;而实现的功能却是…

909-2015-T3

文章目录 1.原题2.算法思想2.1.求树的高度2.2.求路径 3.关键代码4.完整代码5.输出结果 1.原题 试编写算法&#xff0c;求给定二叉树上从根节点到叶子节点的一条路径长度等于树的深度减一的路径&#xff08;即列出从根节点到该叶子节点的节点序列&#xff09;&#xff0c;若这样…

解决 VSCode 配置远程连接,过程试图写入的管道不存在

解决 VSCode 配置远程连接&#xff0c;过程试图写入的管道不存在

【数据结构】链表中二级指针的应用

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 (注:为方便演示本篇使用的x86系统,因此指针的大小为4个字节) 目录 &#x1f4cc;形参的改变不影响实参! 1.调用函数更改整型时传值调用与传址调用的区别 &#x1f38f;传值…

掌握Katalon Studio 导入 swagger 接口文档,接口测试效率提升100%

katalon studio大家都已经不陌生了&#xff0c;是一款现在非常主流的自动化测试工具&#xff0c;包括了web、api、APP&#xff0c;甚至PC应用程序都可以使用它来完成自动化测试。 swagger是一款RESTFUL接口的文档在线自动生成软件&#xff0c;swagger是一个规范和完整的框架&a…

【数据库】数据库中的检查点Checkpoint,数据落盘的重要时刻

检查点(checkpoint) ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定…