智能车竞赛技术报告 | 双车接力组 - 辽宁工业大学 - 灵越1队

Posted 卓晴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能车竞赛技术报告 | 双车接力组 - 辽宁工业大学 - 灵越1队相关的知识,希望对你有一定的参考价值。

简 介: 本智能车系统以MM32SPIN27PS微控制器为核心,通过电感检测模型车的运动位置和运动方向,用编码器检测模型车的速度。使用PID控制算法调节驱动电机的转速和角度,完成对模型车运动速度和运动方向的闭环控制。为了完成接力任务并提高智能车的行驶速度和可靠性,我们使用OLED显示模块和无线模块、按键模块等调试手段,进行了大量底层和上层测试。实验结果表明,该系统设计方案可行。

关键词 MM32SPIN27PSPID,**OLED **

学 校:辽宁工业大学
队伍名称:灵越1队    
参赛队员:季昊楠   
李天宇   
刘格格   
卢怡    
带队教师:蓝和慧   

 

引言


1.1 相关背景

  第十六届全国大学生智能汽车竞赛如约而至,我队是辽宁工业大学双车接力组,共有四名参赛队员,队员都为具有正式学籍的全日制大二在校本科生,符合竞赛要求。

  在本次比赛中,本组使用大赛组委会统一提供的竞赛车模,采用灵动微电子32位微控制器MM32SPIN27作为核心控制单元,自主构思控制方案及系统设计,包括车模机械结构设计、电路设计、传感器信号采集处理、控制算法及执行、传球接力等,最终实现一套能够自主识别路线,并且可以实时输出车体状态的智能车控制系统。本文主要对车模整体设计思路,硬件与软件设计及车模的装配调试过程作简要的说明。

1.2 构成概要

  本技术报告共包含六章内容。第一章为引言部分。主要概述智能车模制作情况,并阐明了报告内容的构成。第二章为系统设计部分。详细介绍智能车模系统设计和方案选定。第三章为机械结构的实现。详细介绍模型车机械部分安装及改造、传感器的设计安装、系统电路板的固定及连接等。第四章为硬件电路,包括电路原理和车模基本参数。第五章为软件设计,微处理器控制软件主要理论、算法说明及代码设计介绍。第六章为总结。
 

第二章 统设计


2.1 设计思路

  按照本届竞赛规则规定,智能汽车系统采用灵动公司32位微控制器MM32SPIN27PS单片机作为核心控制单元用于智能汽车系统的控制。由电感采集经电磁运放模块放大,返回到单片机,计算后作为转向控制的依据。陀螺仪加速度计返回的信号作为当前车身姿态的信号,主控输出PWM波控制电机的转速以保持车身的平衡及锁定赛道。与基础四轮组不同的是,双车组需要使用左右轮的差速来进行转弯。为了控制的准确性和快速性,我们使用陀螺仪的z轴角速度作为返回信号来抵消转弯时的超调。编码器返回的信号可以形成闭环,使用PID控制电机的转速。双车组中直立车的加减速会使车身的角度发生明显的变化,这就会影响车的平衡使车速变的不可控。因此调试过程就是要在保证车身稳定的前提下逐步的提高直立车前进的整体速度。

  根据以上系统方案设计,双车组共包括六大模块:MM32SPIN27PS主控模块、传感器模块、电源模块、电机驱动模块、速度检测模块和辅助调试模块。各模块的作用如下:MM32SPIN27PS主控模块,作为整个车的控制中心就像人的“大脑”,将电磁传感器、陀螺仪加速度计和编码器等传感器的信号,根据赛道情况作出不同的决策进行不同的控制算法,驱动两个直流电机完成对车体的控制;传感器模块,用来检测当前赛道信息是智能汽车的“眼睛”,可以通过一定的前瞻性,提前感知前方的赛道信息,为智能汽车的“大脑”做出决策提供必要的依据和充足的反应时间,同时使用陀螺仪加速度计计算车模行进过程中的实时角速度和加速度信息,用以保持车模稳定行进;电源模块,为整个系统提供合适而又稳定的电源;电机驱动模块,驱动直流电机完成智能汽车的加减速控制和转向控制;速度检测模块,检测反馈智能汽车轮的转速,用于速度的闭环控制;辅助调试模块如无线串口,主要用于调试过程中对车采集数据的观察和监控。

2.2 方案选定

  按照比赛规则要求,车通过检测赛道中心电磁线的交变电磁场信号来控制车模沿着电磁线前进。由于直立车的特殊性,车身在循迹前进的过程中,必须保持车身的平衡。根据最基本保持车身平衡的基本原理,我们需要知道车身当前的角度和角速度。因此在保持车身平衡方面,我们确定以加速度计作为角度传感器,陀螺仪作为角速度传感器。另外,车身转向控制方面,也使用陀螺仪作为转向反馈。

 

第三章 械结构


3.1 机械结构安装与改造

3.1.1三轮车模

▲ 图3.1 三轮车模图片

  对于重心问题,我们将整个车的重心控制在车轮轴的附件,这样有助于转向,为此我将电路板通过热熔胶来粘在车轮附近,各个电路板通过硅胶线和杜邦线连接,并且加了一个铁球在电池前边。对于传球结构,我们将一个剪开的乒乓球通过热熔胶粘在了碳杆上,并且将这个乒乓球的剪开了几个缝隙,这样既可以保证正常行驶过程中可以夹住乒乓球,而且在传球过程中又可以正常进行传球。4个电感电感通过热熔胶粘在碳杆,其中2个是八字型,2个一字型。陀螺仪通过热熔胶几乎粘在车轮轴的附近,这样陀螺仪传回来的值偏差不会太大。

3.1.2 直立车模

▲ 图3.2 直立车模图片

  为了给直立车设置一个较好的机械零点,使车的加减速更加容易控制,我们将主板竖直安装在靠近电机的位置,驱动板放置在电机上方,用热熔胶和扎带固定用硅胶线和杜邦线进行连接,使车的重心基本保持在车轴的位置;传球装置靠一对强力磁铁将小球吸附在电池上,使传球更加简单不易出错;巡线使用了五个电感,分别是左中右三个一字电感和中间两个八字电感,通过热熔胶固定在碳杆上;陀螺仪通过车底板的钻孔用螺丝固定在两轮中间车轴位置,使得车的姿态与陀螺仪所测数据保持一至。

3.2模型车的主要技术参数

▲ 表3.2 车模主要技术参数

 

第四章 件电路


4.1 设计思路

4.1.1 硬件系统框图

▲ 图2.1 硬件系统框图

4.1.2 框图说明

  在上图所示智能车模的硬件系统框图中,智能车模是以MM32SPIN27单片机最小系统板为控制核心;使用电压为7.2V,容量为2AH的镍镉电池作为能量来源,分别为智能车模上各个模块供电;在PVC赛道上布置电磁线并接入信号源,车辆通过电感去采集赛道上各个元素的电感值,并将采集到的信号进行放大处理,送往单片机进行算法运算处理;单片机经过路况分析后,合理、准确地输出PWM信号控制左右电机的差值,从而很好地控制智能车模转向;单片机分析编码器采集到的脉冲数与所设定脉冲数的差值经过运算处理输出PWM信号控制电机的转速;从而快速、准确的完成比赛。

4.2 电源电路

  我们所使用的各个传感器模块需要5V和3.3V供电,所以我们通过线性稳压芯片将电源电压分成5V和3.3V。

▲ 图4.2.1 5V电源

▲ 图4.2.2

  为了降低干扰,我们特意把电磁运放供电部分单独拿出来。

▲ 图4.2.3 电磁运放供电

4.3电磁运放芯片

  关于运放芯片,一开始采用的是LM324,但通过焊接后测试发现,该电路的性能达不到我们的需要,采集的信号经该电路放大后过于敏感,稍一抖动,电感值变化特别巨大,所以在不断尝试后,我们最终确定了使用OPA4377,该芯片有如下几个优点:

  • 增益带宽乘积:5.5MHz
  • 低噪声:1kHz时为7.5nV/√Hz
  • 偏移电压:1mV(最大)
  • 输入偏置电流:0.2pA
  • 轨对轨输出
  • 单位增益稳定
  • EMI输入滤波
  • 静态电流:0.76mA/ch
  • 电源电压:2.2V至5.5V

  最终通过测试,该电路符合需要。

4.4驱动电路

  驱动芯片我们采用的是BTN7971,该芯片具有耐压值高,载流能力强等优点,简单来说,就是便宜好用,而且电路比较简单。电源电压直接给驱动板供电,单片机输出PWM直接驱动电机,通过逻辑芯片74HC02来控制电机转动的方向,从而完成一系列动作。在PCB板中,我们特意对7971芯片底部做了开窗,打孔等散热处理,车模在长时间运行过程中,没有出现发热现象。

▲ 图4.4.1 驱动电路原理图

▲ 图4.4.2 PCB板散热处理

 

软件设计


5.1 电感采集处理

▲ 图5.1赛道铺设图片

  我们的车模是用纯电感运行的,对于电感采回来的值进行10次求平均值处理,使电感值不会突然出现很大的偏差。正常道路上是利用两个一字电感进行循迹,用(电感左-电感右)/(电感左+电感右)得到偏差值。

  • 出库:直线行驶一段距离,这个距离由编码器积分得到,再向右打固定偏差的固定角度,这个角度由陀螺仪积分得出。
  • 环岛:利用八字电感找到特征点进环;再利用四个电感的特征点判定为环内切换为一字电感运行;再利用一字电感的特征点判定为出环,用八字电感循迹;由于此时环岛对于正常直线道路仍有影响所以在循迹的一段距离手动加了偏差,这个距离利用编码器积分得到。
  • 坡道:利用陀螺仪y轴的角速度判定。
  • 三叉:利用中间一字电感判定,给个固定偏差向右打一个角度,这个角度由陀螺仪积分得出。
  • 十字:使用左右一字电感寻迹无需处理。
  • 有球接力:当三轮撞击直立时,直立车编码器产生脉冲后利用无线串口向三轮发送信息,直立启动,三轮利用编码器行驶一段距离停止。
  • 无球接力:三轮进入三叉后向直立发送信息,直立启动,三轮利用编码器行驶一段距离停止;直立进入三叉后向直立发送信息,三轮启动,直立停止。
  • 角速度环:位置式PID,使用了PI调节;角度环:位置式PID,使用了PD调节;
  • 转向环:位置式PID,使用了PD调节,其中D的部分是陀螺仪z轴的角速度;
  • 速度环:位置式PID。由于位置式PID有对历史的累加,故转向环只有PD调节。将速度环算出的值反馈给角度环,经过角度环计算后再反馈给角速度环,最后计算值为最后的电机输出值。对于直立PID参数的整定则是先角速度环I、P,再角度环P、D的方法进行。

5.2 算法说明及代码设计介绍

【通用原理部分,此处省略3000字...】

 


  加“第十六届全国大学生智能车竞赛”不是一时冲动,而是“蓄谋已久”,在这项比赛中,我们队伍成员从零开始,查阅资料,设计机械结构,组装车模,程序设计,调整参数,分析问题,解决问题。

  大二上学期我们完成了硬件电路设计和制作,组装车模,主控芯片的了解和学习。大二下学期我们考虑使用摄像头,但因为种种原因放弃了摄像头,采用纯电磁,而后研究算法,电机控制不断对机械结构和参数进行优化,最终使车模控制达到预期效果。过程中遇到很多问题,环岛,三叉,传球,坡道处理等等,方案一次次更改,参数一次次调试,熬了一个又一个日夜,感受了多次从满怀信心到情绪崩溃,调车的过程像极了过山车,有巅峰,有低谷,有眼泪也有欢笑。无论硬件还是软件,我们收获满满,也增进了团队之间的友谊。

  在这份技术报告中,我们尽可能详细的介绍了我们车模的相关信息,不完美之处欢迎指正。
  这一年的制作和调试时间中,得到了多方面的帮助。在调试过程中,老师及时指出我们的问题让我们纠正,学弟主动帮助我们制作赛道,在试验场地和经费中,我们都得到了学校和学院的大力支持,在此特别感谢一直关注和支持智能车竞赛的学校和学院的各位领导。感谢卓大大、组委会、志愿者和线上裁判的辛苦付出。你若盛开,蝴蝶自来。结果总会与付出成正比的。希望智能车竞赛越来越好!

 

考文献


  [1] 卓晴,黄开胜,邵贝贝,《学做智能车——挑战“飞思卡尔”杯》,北京北京航空航天大学出版社,2007
[2] 邵贝贝. 单片机嵌入式应用的在线开发方法[M].北京.清华大学出版社,2004
[3] 夏路易, 石宗义,电路原理图与电路板设计教程 Protel 99SE[M]. 北京, 北京希望电子出版社
[5]尹怡欣,陶永华,新型 PID 控制及其应用.北京:机械工业出版社,1998 年.
[6]黄渊博,王潇祎,彭成,第十三届“恩智浦”杯全国大学生智能汽车竞赛河海大学常州校区 VNX 队技术报告
[7] 阎石. 数字电子电路基础. 北京, 高等教育出版社, 2005
[8] 曹丽,刘扬,刘伟.利用加速度计和陀螺仪的笔杆运动姿态的检测[M].仪器仪表学报
[9] 华成英, 童诗白. 模拟电子技术基础. 北京, 高等教育出版社, 2006

■ 附录 程序源代码

int abs(int i)                    //
  {      /* compute absolute value of int argument */
    return (i < 0 ? -i : i);
  }

float *FastAtan2(float y, float x)    //
{
	float f, g;
	float num, den;
	float result;
	float *nanresult = &result;
	int n;
	static const float a[4] = {0, (float)PI_6, (float)PI_2, (float)PI_3};
	if (x == (float)0.0)
        {
		if (y == (float)0.0)
                {
			result = 0.0;
			//return result;
			return nanresult;
		}
		result = (float)PI_2;
		if (y > (float)0.0)
                {
			//return result;
			return nanresult;
		}
		if (y < (float)0.0)
                {
			result = -result;
			//return result;
			return nanresult;
		}
	}
	n = 0;
	num = y;
	den = x;
	if (num < (float)0.0)
        {
		num = -num;
	}
	if (den < (float)0.0)
        {
		den = -den;
	}
	if (num > den)
        {
		f = den;
		den = num;
		num = f;
		n = 2;
	}
	f = num / den;

	if (f > (float)TWO_MINUS_ROOT3)
        {
		num = f * (float)SQRT3_MINUS_1 - 1.0f + f;
		den = (float)SQRT3 + f;
		f = num / den;
		n = n + 1;
	}
	g = f;
	if (g < (float)0.0)
        {
		g = -g;
	}
	if (g < (float)EPS_FLOAT)
        {
		result = f;
	}
	else
        {
		g = f * f;
		num = (ATANP_COEF1 * g + ATANP_COEF0) * g;
		den = (g + ATANQ_COEF1) * g + ATANQ_COEF0;
		result = num / den;
		result = result * f + f;
	}
	if (n > 1)
        {
		result = -result;
	}
	result = result + a[n];

	if (x < (float)0.0)
        {
		result = PI - result;
	}
	if (y < (float)0.0)
        {
		result = -result;
	}
	//return result;
	return nanresult;
}
void Yijie(void)  //
{
//	   Acc_Cul = *FastAtan2(icm_acc_x,icm_acc_z)*180/3.14;  
//	
//	   GY_Cul = -icm_gyro_y;  //
//	 
//	   CarAngle = k1*Acc_Cul + (1 - k1)*(CarAngle_last + GY_Cul*0.002);   //K1=0.3819  CarAngleÊÇÈںϽǶÈ	
//     CarAngle_last = CarAngle;	           
//     my_carangle = CarAngle_last;
	
		 Acc_Cul = *FastAtan2(icm_acc_x,icm_acc_z)*180/3.14;  
	   GY_Cul = -icm_gyro_y/131.00;  //GY_CulÊǽÇËÙ¶È
      x1 = (Acc_Cul - my_carangle) * (1 - K2) * (1 - K2);
      y1 = y1 + x1 * dt;
      x2 = y1 + 2 * (1 - K2) * (Acc_Cul - my_carangle) + GY_Cul;
      my_carangle = my_carangle + x2 * dt;

}

void AngleControl(void)     //Ö±Á¢¿ØÖÆ
{
	
	if(star==1&&my_carangle<30)
	{
		N_Kp=1.3;
		N_Ki=0.07;
		W_Kp=100;
	}
	else
	{
		star=2;
		N_Kp=2.7;
		N_Ki=0.29;
		W_Kp=30;
	}
	
	get_icm20602_accdata_spi();
	get_icm20602_gyro_spi();
	Yijie();

	N_prev_error = N_last_error;
  N_last_error = N_current_error; 
  N_current_error  = (int16)-(W_add + icm_gyro_y);
  N_P  = (int32)(N_Kp * N_current_error);
  N_I += (int32)(N_Ki * N_current_error); 
  N_D  = (int32)(N_Kd * (N_current_error - N_last_error));
    if(N_I > value)  N_I = 6000;
    if(N_I < -value) N_I = -6000;
    N_add = N_P + N_I + N_D;
    balance_pwm = N_add;
	  motor_output();
  if(speed_flag == 1)
    {
      speed_flag = 0;
       speed_control();     
    }
	if(angle_flag==1)
	{
		angle_flag = 0;
	  W_current_error = (int16)(current_angle - my_carangle  - speed_output);
    W_P  = (int16)(W_Kp * W_current_error);
    W_I += (int16)(W_Ki * W_current_error);
    W_D  = (int16)(W_Kd * (W_current_error - W_last_error));
    W_add = W_P + W_I + W_D; 
	}
	
}	

void turn_PID(void)
{
    data_analyse();
	  turn_W_current_error = error; 
    turn_W_P  = (int16)(turn_W_Kp * turn_W_current_error);
    turn_W_I += (int16)(turn_W_Ki * turn_W_current_error); 
    turn_W_D  = (int16)(turn_W_Kd * icm_gyro_z);
    turn_W_add = turn_W_P + turn_W_I - turn_W_D;
    turn_pwm = turn_W_add;  
	 

}

void motor_speed(int speed)                 //
{   
    V_prev_error = V_last_error;                                   //???????
    V_last_error = V_current_error;                                //???????
    V_current_error  = speed - speed_now;                     //???????(???????)
    V_P  = (int)(V_Kp * V_current_error);                          //P???  
    V_I += (int)(V_Ki * V_current_error);                          //I??? 
    V_D  = (int)(V_Kd * (V_current_error - V_last_error));         //D???	 	
	  if(V_I >  value)  V_I =  value;                                //????
    if(V_I < -value)  V_I = -value;
    V_add = V_P + V_I + V_D; 
    speed_output=	V_add;	
	  speed_output = speed_output*0.7 + last_speed_output*0.3;
    if(speed_output >= 10)                                          //??????
      speed_output = 10;
    if(speed_output <= 0)
      speed_output = 0;      
		 
    last_speed_output = speed_output;
		
		
	
}

void motor_output(void)                                 //
{	
		static unsigned int a;
	
				if(stop_flag==1)
				{	 
					a++;
					if(a>=400&&my_carangle<=0)
					{
						turn_pwm=0;
					}
					 left_pwm  = 0 + turn_pwm;
					 right_pwm = 0 - turn_pwm;					 
				}
				else
				{
					 a=0;
					 left_pwm  = balance_pwm + turn_pwm;
					 right_pwm = balance_pwm - turn_pwm;
				}

	if(star_flag==1)
	{	
				if(left_pwm >= 0) 
					{
						if(left_pwm > 9000)
							left_pwm = 9000;
						gpio_set(A11,0);
						pwm_duty_updata(PWM_TIM, TIM_2_CH2_A12 ,   left_pwm);   
					}
				if(left_pwm < 0)
					{
						if(left_pwm < -9000)
							left_pwm = -9000;
						gpio_set(A11,1);
						pwm_duty_updata(PWM_TIM, TIM_2_CH2_A12 ,  - left_pwm);   
					} 
				if(right_pwm >= 0) 
					{
						if(right_pwm > 9000)
							right_pwm = 9000;
						gpio_set(C9,0);
						pwm_duty_updata(PWM_TIM, TIM_2_CH4_B11,   right_pwm);   
					}
				if(right_pwm < 0)
					{
						if(right_pwm < -9000)
							right_pwm = -9000;
						gpio_set(C9,1);
						pwm_duty_updata(PWM_TIM, TIM_2_CH4_B11,  - right_pwm);   
					} 			
	}
	
}


● 相关图表链接:

以上是关于智能车竞赛技术报告 | 双车接力组 - 辽宁工业大学 - 灵越1队的主要内容,如果未能解决你的问题,请参考以下文章

智能车竞赛技术报告 | 双车接力组 - 大连海事大学 - 同舟拾贰队

智能车竞赛技术报告 | 双车接力组 - 东北大学 - 三好学生

智能车竞赛技术报告 | 双车接力组 - 黑龙江工程学院 - 睿龙二队

智能车竞赛技术报告 | 双车接力组 - 沈阳航空航天大学 - 精神小车成双 - 双轮车

智能车竞赛技术报告 | 双车接力组 - 沈阳航空航天大学 - 精神小车成双 - 三轮车

第16届智能车竞赛双车接力组—直立车经验语录