LCR技术报告
第八届“飞思卡尔”杯全国大学生
智能汽车竞赛
技 术 报 告
学 校:电子科技大学
队伍名称: LCR
参赛队员: 熊策
徐天昊
牛记朋
带队教师: 田 雨
关于技术报告和研究论文使用授权的说明
本人完全了解第八届“飞思卡尔”杯全国大学生智能汽车邀请赛关保留、使用技术报告和研究论文的规定,即:参赛作品著作权归参赛者本人,比赛组委会和飞思卡尔半导体公司可以在相关主页上收录并公开参赛作品的设计方案、技术报告以及参赛模型车的视频、图像资料,并将相关内容编纂收录在组委会出版论文集中。
参赛队员签名:熊 策
带队教师签名: 田 雨
日 期:
目录
第一章 引言 ......................................................................................... - 1 -
1.1 大赛介绍 ....................................................................................... - 1 -
1.2系统设计框架介绍 ......................................................................... - 2 -
第二章 智能车机械结构调整与优化 ..................................................... - 3 -
2.1 智能车参数要求 ............................................................................ - 3 -
2.2 智能车整体参数调校 ..................................................................... - 3 -
2.3 编码器安装 ................................................................................... - 5 -
2.4 陀螺仪与加速度传感器安装 .......................................................... - 5 -
第三章 硬件电路设计说明 ................................................................... - 7 -
3.1 单片机最小系统模块 ..................................................................... - 7 -
3.2 传感器模块 ................................................................................... - 7 -
3.3电机模块 ........................................................................................ - 9 -
3.4测速模块 ........................................................................................ - 9 -
3.5陀螺仪与加速度计模块 ................................................................ - 10 -
3.6人机交互模块 ............................................................................... - 11 -
第四章 智能车控制软件设计说明 ...................................................... - 12 -
4.1 MC9S12XS128片资源简介 ......................................................... - 12 -
4.2 MC9S12XS128所用模块简介 ..................................................... - 13 -
4.2.2 PWM 模块 ................................................................................. - 13 -
4.3软件功能与框架 ........................................................................... - 14 -
4.4控制算法与函数 ........................................................................... - 16 -
4.5辅助调试工具介绍 ....................................................................... - 23 -
第五章 系统调试 ............................................................................... - 28 -
第六章 车辆主要参数 ........................................................................ - 29 -
第七章 总结 ....................................................................................... - 30 - 参考文献 ............................................................................................ - 31 - 附录1:部分程序源代码 .................................................................... - 32 -
第一章 引言
1.1 大赛介绍
全国大学生智能汽车竞赛原则上该竞赛由竞赛秘书处为各参赛队提供/购置规定范围内的标准硬软件技术平台,竞赛过程包括理论设计、实际制作、整车调试、现场比赛等环节,要求学生组成团队,协同工作,初步体会一个工程性的研究开发项目从设计到实现的全过程。该竞赛融科学性、趣味性和观赏性为一体,是以迅猛发展、前景广阔的汽车电子为背景,涵盖自动控制、模式识别、传感技术、电子、电气、计算机、机械与汽车等多学科专业的创意性比赛。该竞赛规则透明,评价标准客观,坚持公开、公平、公正的原则,保证竞赛向健康、普及,持续的方向发展。
本次比赛分为光电、摄像头和电磁三个赛题组,在车模中使用透镜成像进行道路检测方法属于摄像头赛题组,使用电磁信号巡线属于电磁赛题组,除此之外则属于光电赛题组。本论文主要介绍光电赛题组的智能车制作。在这份报告中,我们主要通过对整体方案、机械、硬件、算法等方面的介绍,详细阐述我队在此次智能汽车竞赛中的思想和创新。具体表现在电路的创新设计、算法以及辅助调试模块等方面的创新。
1.2系统设计框架介绍
系统是以检测赛道两边黑线为基础,通过单片机处理信号实现对车体控制,实现车体能够准确沿着预设路径寻迹。系统电路部分需要包括单片机控制单元、电机驱动电路、陀螺仪与加速度计电路、线性CCD电路等部分,除此之外系统还需要一些外部设备,例如编码器测速、直流电机驱动车体和控制车体方向。综上所述,本智能车系统包含了以下几个模块:
1.电源模块
2.单片机最小系统模块
3.传感器模块
4.电机模块
5.陀螺仪与加速度计模块
6.测速模块
7.人机交互模块
系统的整体模块如图1.2.1所示:
图1.2.1 系统框架图
智能车机械结构调整与优化
第二章 智能车机械结构调整与优化
2.1 智能车参数要求
1.传感器数量要求:传感器数量不超过16个:光电传感器接受单元计为1 个传感器,发射单元不计算;CCD 传感器计为1 个传感器;
2.电机型号:RN260-CN -2875
3.全部电容容量和不得超过 2000 微法;电容最高充电电压不得超过25 伏。
2.2 智能车整体参数调校
智能车的整体参数,包括车体重心、高度、传感器排布方式等,都对整个智能车系统的稳定运行起着至关重要的作用。因此,对智能车机械系统的调节,有助于小车更快更稳定的运行。
小车的布局以精简、可靠、稳定为前提,通过对小车的布局,尽量保证小车左右平衡,以及寻找一个合适的重心,保证小车既能稳定快速前进,又能在转弯时流畅。光电组车模如图2.2.1所示
图2.2.1 车模示意图
车模运行状态如图2.2.2所示
第八届全国大学生智能汽车竞赛技术报告
图2.2.2 车模示意图
车模整体外观如图2.2.3所示
图2.2.3 车模整体外观
智能车机械结构调整与优化
2.3 编码器安装
选用可以5V工作电压的512线MINI光电编码器进行速度的测量,保证测量的精度。速度传感器用螺钉通过支架固定在后轮支架上,这样固定好之后,就有了较高的稳定性。然后调节编码器齿轮,使其与差速齿轮紧密咬合,增大测速的精确性,但是咬合过紧也增大了摩擦,减小了对电机做功的利用率,影响小车的快速行驶,因此减小摩擦同时增强齿轮间的咬合是我们主要考虑的因素。用齿轮润滑油涂抹齿轮有不错效果。编码器安装示意图如图2.4.1所示:
图2.3.1 编码器安装示意图
2.4 陀螺仪与加速度传感器安装
本次设计中陀螺仪采用的是村田公司的ENC-03系列的陀螺仪。智能车在行进过程中,车体仅绕两后轮的轴心线做转动。芯片外观是长方形的,安装时,应注意将长的一边与后轮轴心线平行。此外,还应注意的是,陀螺仪的输出受温度的影响比较大,为避免环境温度变化对输出的影响,我们将陀螺仪和加速度计作为一个单独的模块,采用FFC线与主板连接,安装在车身的背面。 与陀螺仪一样,加速度传感器的性能与安放位置也有很大的关系。加速度传感器是根据其XYZ轴上的模拟输出电压来确定车身的倾角。由于我们测量的倾角只有一个,所以可以使用Z轴的输出来计算,当小车倾角为0时,Z轴对应的面应该处于水平。
第八届全国大学生智能汽车竞赛技术报告
图2.4.1 ENC-03陀螺仪与加速度计
转直立陀螺仪位置不水平会造成弯加减速。而事实上即便在安装传感器时非常小心,但陀螺仪芯片和陀螺仪电路板、陀螺仪电路板和主板、主板和车轮之间都有位置误差,累计起来你的陀螺仪还是可能不平,我们使用了如下测试陀螺仪倾斜程度的方法。将车身放置在一个推力轴承上,让车体在上面转动,读取陀螺仪返回的数据。用这种方法矫正陀螺仪方便有效,如图2.4.2所示。
图2.4.2 推力轴承
硬件电路设计说明
第三章 硬件电路设计说明
本智能车硬件系统以稳定为设计的原则,在有限的条件下做到最好。单片机采用MC9S12XS128。使用LM2940-5为各个模块供电,电机驱动使用芯片BTS7970。调试过程中,采用OLED、蓝牙等模块辅助,方便小车的调试。本章均有详细介绍。
3.1 单片机最小系统模块
以MC9S12XS128为核心的单片机最小系统是本智能车的核心。
图3.1.1主板电路
3.2 传感器模块
线性CCD是光电组小车最重要的模块之一,能够分辨白色的赛道及黑色的边线,对道路状况的检测起着至关重要的作用。
TSL1401线性CCD传感器包含128个线性排列的光电二极管。每个光电二极管都有各自的积分电路,以下我们将此电路统称为像素。每个像素所采集的图像灰度值与它所感知的光强和积分时间成正比。
一般来说线性CCD模块的焦距是固定的,因此要想得到清晰的图像就需要通过调节镜头的
- 7 -
第八届全国大学生智能汽车竞赛技术报告
进出来解决。如果镜头拧的位置合适,则会得到清晰的图像,CCD输出的数据在波形上会表现的比较尖锐,如图3.2.1所示。
图 3.2.1
- 8 -
硬件电路设计说明
图3.2.3 传感器排布方案
3.3电机模块
电机采用芯片BTS7970,其应用非常简单,只需要向芯片第2 引脚输入PWM 波就能控制。当系统中只需要单向控制时,只需要让电机一端接地,另一端接BTS7960 第4 引脚。如果需要电机双向旋转控制,则需要另一片BTS7960 共同组成全桥。由于小车使用双电机,所以我们使用4片BTS7970构成两个全桥分别控制两个电机。
图3.3.1 电机驱动电路
3.4测速模块
本小车使用512线的光电编码器进行小车的测速,以保证测量精度,并且直接有方向输出,使用方便。LM2940-5为其提供5V工作电压。由于
MC9S1
- 9 -
第八届全国大学生智能汽车竞赛技术报告
2XS128只有一个脉冲计数器,我们采用分时复用的方式对左右两轮计数。
图3.4.1 多路选择器电路
3.5陀螺仪与加速度计模块
我们采用AMS1117为陀螺仪(ENC-03MB)和加速度计(MMA7361)提供3.3V的工作电压。由于陀螺仪数据手册上的输出有过冲,不利于积分,我们采用官方提供的电路。
3.5.1陀螺仪电路
- 10 -
硬件电路设计说明
3.5.2加速度计电路
3.6人机交互模块
为了方便调试,本车有蓝牙模块,有效进行运行参数之间的传送,除此之外,还设置了键盘、液晶显示屏,以方便控制参数的修改和智能车的调试。
- 11 -
第八届全国大学生智能汽车竞赛技术报告
第四章 智能车控制软件设计说明
4.1 MC9S12XS128片资源简介
MC9S12XS128 微控制单元作为MC9S12 系列的16位单片机,由标准片上外围设备组成,包括16位中央处理器、128KB的Flash 存储器、8KB的RAM、2KB的EEPROM、两个异步串行通信接口、两个串行外围接口、一组8通道的输入捕捉或输出捕捉的增强型捕捉定时器、两组8 通道10 路模数转换器、一组8通道脉宽调制模块、一个字节数据链路控制器、29路独立的数字I/O接口、20路带中断和唤醒功能的数字I/O 接口、5个增强型CAN总线接口。同时,单片机内的锁相环电路可使能耗和性能适应具体操作的需要。MC9S12XS128片内资源表如图5.1:
- 12 -
智能车控制软件设计说明
图4.1 MC9S12XS128片内资源
4.2 MC9S12XS128所用模块简介
在整个系统设计中,用到了5个单片机基本功能模块:时钟模块、PWM 输出模块、ECT 模块、串口通信模块以及普通IO 模块。根据系统实际需求,对各个模块进行了初始化配置,通过对相应数据寄存器或状态寄存器的读写,实现相应的功能。
4.2.1时钟模块
XS12 单片机中有四个不同的时钟,即外部晶振时钟、锁相环时钟、总线时钟和内核时钟。 当前电路板采用的是16MHz 的有源晶振,因此外部晶振时钟为16MHz;默认设置下,锁相环时钟为80MHz,总线时钟为40MHz,内核时钟为16MHz。锁相环时钟与外部晶振时钟的倍、分频关系由SYNR、REFDV 两寄存器决定。总线时钟用作片上外围设备的同步,而内核时钟则用作CPU 的同步,它决定了指令执行的速度。 时钟模块初始化程序如下:
void Pll_Init(void)
{
CLKSEL = 0x00; // disengage PLL to system
PLLCTL_PLLON = 1; // turn on PLL
SYNR = 0x53; // 注意VCOFRQ[7:6];SYNDIV[5:0];fVCO= 2*fOSC*(SYNDIV +
1)/(REFDIV + 1);fPLL= fVCO/(2 × POSTDIV);BUS= fPLL/2
REFDV = 0x07; // REFFRQ[7:6];REFDIV[5:0]
POSTDIV = 0x00;
_asm(nop);
_asm(nop);
while(!(CRGFLG_LOCK == 1)); //when pll is steady ,then use it;
CLKSEL_PLLSEL = 1;//engage PLL to system;
}
4.2.2 PWM 模块
脉宽调制模块有8 路独立的可设置周期和占空比的8 位PWM 通道,每个通道配有专门的计数器。该模块有4 个时钟源,能分别控制8 路信号。通过配置寄存器
- 13 -
第八届全国大学生智能汽车竞赛技术报告
可设置PWM 的使能与否、每个通道的工作脉冲极性、每个通道输出的对齐方式、时钟源以及使用方式(八个8 位通道还是四个16 位通道)。PWM 模块的初始化设置过程为:
void PWM_Init(void)
{
PWME = 0x00; //输出通道使能位。1可对外输出波形;0不能对外输出波形。设置之前先禁止PWM[ 2 5 6 7]
PWMPOL = 0xff; // 通道对外输出波形先是高电平然后再变为低电平
PWMCLK = 0xff; //用clock_A,clock_B
PWMCAE = 0x00; // 0为左对齐输出;1为居中对其输出。只有输出通道关闭情况下才可设置。
PWMCTL = 0x00; //把PWM不级联
//PWMPRCLK = 0x33;//时钟预分频,时钟A和B与分频 结果CLKA=CLKB=E=5M. // PWMPRCLK[0-7] PCKA [0 1 2] PCKB [4 5 6]
// CLKA= Bus clock / (2^ PCKA) CLKB= Bus clock / (2^ PCKB)
// CLKA=40M / (2^ 3)=5M CLKB= 5M
PWMPRCLK = 0x00;
PWMSCLB=8;
PWMSCLA=8;
PWMPER0 = 250;
PWMPER2 = 250;
PWMPER4 = 250;
PWMPER7 = 250;
PWMDTY0 = 0; //初始时电机占空比为0,即电机转速为0.
//占空比=PWMDTYx/PWMPERx
PWMDTY2 = 0;
PWMDTY4 = 0;
PWMDTY7 = 0;
PWME = 0xb5; //PWM使能
}
4.3软件功能与框架
软件的主要功能包括有:
(1)各传感器信号的采集、处理;
- 14 -
智能车控制软件设计说明
(2)电机PWM输出;
(3)车模运行控制:直立控制、速度控制、方向控制;
(4)车模运行流程控制:程序初始化、车模启动与结束、车模状态监控;
(5)车模信息显示与参数设定:状态显示、上位机监控、参数设定等。
图4.3.1 主程序框架
程序上电运行后,便进行单片机的初始化。初始化的工作包括有两部分,一部分是对于单片机各个应用到的模块进行初始化。第二部分是应用程序初始化,是对于车模控制程序中应用到的变量值进行初始化。 初始化完成后,首先进入车模直立检测子程序。该程序通过读取加速度计的数值判断车模是否处于直立状态。如果一旦处于直立状态则启动车模直立控制、方向控制以及速度控制。 车模的直立控制、速度控制以及方向控制都是在中断程序中完成。通过全局标志变量确定是否进行这
- 15 -
第八届全国大学生智能汽车竞赛技术报告
些闭环控制。中断程序框图如图4.3.2所示。
图4.3.2 中断服务程序
图4.3.2中,使用定时器,产生一毫秒的周期中断。中断服务程序的任务被均匀分配在0-4的中断片段中。因此每个中断片段中的任务执行的周期为5毫秒,频率为200Hz。
将任务分配到不同的中断片段中,一方面防止这些任务累积执行时间超过1毫秒,扰乱一毫秒中断的时序,同时也考虑到这些任务之间的时间先后顺序。 这些任务包括: (1)电机测速脉冲计数器读取与清除。累积电机转动角度。累积电机速度,为后面车模速度控制提供平均数; (2)启动AD转换。进行20次模拟量采集,然后计算各个通道的模拟量的平均值。这个过程是对于模拟信号进行低通滤波。(3)车模直立控制过程。包括车模角度计算、直立控制计算、电机PWM输出等。 (4)车模速度控制:在这个时间片段中,又进行0-19计数。在其中第0片段中,进行速度PID调节。因此,速度调节的周期为100毫秒。也就是每秒钟调节10次。 (5)车模方向控制:根据前面读取的电磁场检波数值,计算偏差数值。然后计算电机差模控制电压数值。
4.4控制算法与函数
4.4.1直立控制程序设计 平衡控制算法最重要的是滤波算法和控制算法。这里滤波的主要作用是使用加速度 - 16 -
智能车控制软件设计说明
计滤除陀螺仪的漂移,也可以说是将加速度计和陀螺仪的数据融合。其中滤波算法有卡尔曼滤波,官方的互补滤波,不滤波。控制算法有PID和LQR线性二次型调节器。卡尔曼滤波因为过于复杂而没有使用,官方互补滤波和卡尔曼滤波效果相似而且简单,不滤波动态效果最好但是无法消除陀螺仪累积误差。最终我们选用了官方互补滤波,因为陀螺仪数据必须是最重要的。
将车模角度和角速度乘以各自相应的系数就可以得到直立控制输出量
[4]
图4.4.1 直立控制算法框图
void AngleCalculate(void){ float fDeltaValue;
int nGyro_Angle,nGravityAngle;
UINT8 Gyro_Angle_H,Gyro_Angle_L,GravityAngle_H,GravityAngle_L; UINT8 Gyro_H,Gyro_L;
g_fGravityAngle = g_nCarAcceVal*Rz;
g_fGyroscopeAngleSpeed = g_nCarGyroVal*Rgyro;//角速度单g_fCarAngle=g_fGyroscopeAngleIntegral; g_nCarAngle= (int)(g_fCarAngle/Rz);
fDeltaValue=( g_fGravityAngle-g_fCarAngle)/Tz; g_fAngleDeltaValue=fDeltaValue;
g_fGyroscopeAngleIntegral += ( g_fGyroscopeAngleSpeed + fDeltaValue );
//nGravityAngle=(int)(g_fGravityAngle*100);
//GravityAngle_H=(byte)((nGravityAngle&0xff00)>>8); //GravityAngle_L=(byte)(nGravityAngle&0x00ff); //send_buf[5]= GravityAngle_H; //send_buf[6]= GravityAngle_L;
//GYROSCOPE_ANGLE_SIGMA_FREQUENCY;
位转化
- 17 -
第八届全国大学生智能汽车竞赛技术报告
//nGyro_Angle=(int)(g_fCarAngle*100);
//Gyro_Angle_H=(byte)((nGyro_Angle&0xff00)>>8); //Gyro_Angle_L=(byte)(nGyro_Angle&0x00ff); //send_buf[3]= Gyro_Angle_H; //send_buf[4]= Gyro_Angle_L;
//Gyro_H=(byte)(((g_nCarGyroVal)&0xff00)>>8); //Gyro_L=(byte)(g_nCarGyroVal&0x00ff); //send_buf[7]=Gyro_H; //send_buf[8]=Gyro_L; }
void AngleControl(void){
float fValue;
UINT8 AngleControl_H,AngleControl_L; int nAngleControl;
g_fCarSpeedSet= g_fSpeedControlOut;
fValue=g_fGyroscopeAngleSpeed*AngleDgainTemp*0.1+(g_fCarAngle)*AnglePgainTemp g_fAngleControlOut = fValue;
//nAngleControl=(int)(g_fAngleControlOut*100);
//AngleControl_H=(byte)((nAngleControl&0xff00)>>8); //AngleControl_L=(byte)(nAngleControl&0x00ff); //send_buf[9]=AngleControl_H; //send_buf[10]=AngleControl_L; }
4.4.2速度控制程序设计
为了使得速度具有一定的物理含义,对于所取得的电机速度值需要进行单位转换。根据定义单位的物理含义,可以确定速度单位转换的比例值。
- 18 -
智能车控制软件设计说明
图4.4.2 速度控制算法框图
void SpeedControl(void){
float fDelta,fCarSpeedReal; float fP,fI;
UINT8 fCarSpeed_H,fCarSpeed_L,fCarSpeedReal_H,fCarSpeedReal_L,
fSpeedControlIntegral_H,fSpeedControlIntegral_L;
int nfCarSpeed,nfCarSpeedReal,nSpeedControlIntegral;
fCarSpeed = (g_nSpeedLeftCe+g_nSpeedRightCe)/2;
fCarSpeedReal= (g_fSpeedAveRight+g_fSpeedAveLeft)*0.5;
fCarSpeed=fCarSpeed_old*0.6+(g_fSpeedAveRight+g_fSpeedAveLeft)*0.2; g_fCarSpeed =fCarSpeed*CAR_SPEED_CONSTANT; fDelta = g_fSpeedGet- g_fCarSpeed; fP = fDelta * SpeedPgain; fI = fDelta * SpeedIgain;
if( g_fSpeedControlIntegral >=3)//8) ) {
if( fDelta
g_fSpeedControlIntegral += fI;; } }
else if( g_fSpeedControlIntegral
- 19 -
第八届全国大学生智能汽车竞赛技术报告
if( fDelta > 0 ) {
g_fSpeedControlIntegral += fI; } } else{
g_fSpeedControlIntegral += fI; }
fCarSpeed_old=fCarSpeed;
//nfCarSpeedReal=(int)(fCarSpeedReal);
//fCarSpeedReal_H=(byte)((nfCarSpeedReal&0xff00)>>8); //fCarSpeedReal_L=(byte)(nfCarSpeedReal&0x00ff); //send_buf[3]=fCarSpeedReal_H; //send_buf[4]=fCarSpeedReal_L; //nfCarSpeed=(int)(fCarSpeed);
//fCarSpeed_H=(byte)((nfCarSpeed&0xff00)>>8); // fCarSpeed_L=(byte)(nfCarSpeed&0x00ff); // send_buf[5]=fCarSpeed_H; //send_buf[6]=fCarSpeed_L;
//nSpeedControlIntegral=(int)(g_fSpeedControlIntegral*10);
//fSpeedControlIntegral_H=(byte)((nSpeedControlIntegral&0xff00)>>8); //fSpeedControlIntegral_L=(byte)(nSpeedControlIntegral&0x00ff); //send_buf[7]=fSpeedControlIntegral_H; //send_buf[8]=fSpeedControlIntegral_L; }
//缓冲函数
void SpeedControlOutput(void){
- 20 -
智能车控制软件设计说明
float fValue;
UINT8 SuduControl_H,SuduControl_L; int nSuduControl;
fValue = g_fSpeedControlOutNew - g_fSpeedControlOutOld;
g_fSpeedControlOut=fValue*g_nSpeedControlPeriod/SPEED_CONTROL_PERIOD+g_fSpeedControlOutOld;
// nSuduControl=(int)(g_fSpeedControlOut*100); //SuduControl_H=(byte)((nSuduControl&0xff00)>>8); //SuduControl_L=(byte)(nSuduControl&0x00ff); //send_buf[11]=SuduControl_H; //send_buf[12]=SuduControl_L; }
4.4.3 方向控制程序设计
车模方向控制利用线性CCD采集到的赛道中心值与车身中心值的偏差值来计算车模电机差值驱动电压。程序如下: void DirectionControl(void){
static float fDelta,fDelta_Old;
float fP,fD,Direction_P,Direction_D; UINT8 loss_flag=0;
UINT8 fDelta_H,fDelta_L,fcenter_H,fcenter_L; int nfDelta,nfcenter;
if((left_loss_flag==0)&&(right_loss_flag==0)){
fDelta=(left_edge+right_edge)/2-PHOTO_CENTER; center = (left_edge+right_edge)/2; }
else if (left_loss_flag==0){
fDelta = left_edge + half_plus -PHOTO_CENTER; center = left_edge + half_plus; }else if (right_loss_flag==0){
fDelta = right_edge - half_plus-PHOTO_CENTER; center = right_edge - half_plus; }else{
fDelta=fDelta_Old;
- 21 -
第八届全国大学生智能汽车竞赛技术报告
fP = fDelta*Direction_P*0.01;
fD = fDelta_error*Direction_D*0.01; fDelta_Old = fDelta;
g_fDirectionControlOutOld=g_fDirectionControlOutNew; g_fDirectionControlOutNew =fP +fD;
//nfDelta=(int)(fDelta*10);
//fDelta_H=(byte)((nfDelta&0xff00)>>8); //fDelta_L=(byte)(nfDelta&0x00ff); //send_buf[15]=fDelta_H; //send_buf[16]=fDelta_L; }
//方向控制缓冲函数
void DirectionControlOutput(void){ float fValue ;
UINT8 DirectionControl_H,DirectionControl_L; int nDirectionControl;
fValue = g_fDirectionControlOutNew-g_fDirectionControlOutOld;
g_fDirectionControlOut=fValue*g_nDirectionControlPeriod/DIRECTION_CONTROL_PERIOD+g_fDirectionControlOutOld;
//nDirectionControl=(int)(g_fDirectionControlOut*100);
//DirectionControl_H=(byte)((nDirectionControl&0xff00)>>8); //DirectionControl_L=(byte)(nDirectionControl&0x00ff); //send_buf[11]=DirectionControl_H; //send_buf[12]=DirectionControl_L; }
4.4.4 障碍的检测与控制
今年的规则与前几届相比在赛道中设置了高度不超过5mm的障碍,这无疑增加了小车稳定控制的难度,对于直立车难度更为明显。
- 22 -
智能车控制软件设计说明
一开始我们采取的方案是不检测,直冲障碍,结果速度在1.2m/s左右就到了瓶颈,即便是我们改变机械或者是调节直立参数,速度的提升也只有0.2-0.3m/s。后来我们仔细分析障碍的特征,结合上位机采集到的数据确定了三种过障碍的方案。
方案一:利用超声波检测装置,此方案需要在车模已有的模块中单独增加一个超声波模块,一开始检测障碍的效果很明显,但是随着赛道难度和复杂度的增加,经常出现误检测的情况(例如经常将坡道检测为障碍);
方案二:利用车上现有的加速度计模块,检测竖直方向的分量变化,此方案的缺点在于障碍检测不具有预见性,即只有当车模接触到障碍时才能检测到障碍,而且路面稍有起伏也会造成对障碍检测的干扰;
方案三:直接用CCD检测障碍,由于障碍的颜色为黑色,所以可以利用CCD灰度值的变化检测障碍,并进行减速控制。利用CCD还有一个好处是可以任意选择检测路障的前瞻。
结合三个方案的优劣,我们最终选定方案三。
4.5辅助调试工具介绍
一个好的调试工具可以加快小车的制作的过程,在实际制作当中我们也尝试过不同的上位机,主要有一下三种
方案一:直接使用freescale codewarrior 自带的调试工具 True-Time Simulator & Real-TimeDebugger,使用该工具可以单步调试程序,在全速运行的情况下,调到Periodiacl mode ,模式,还可以实时的观察各个变量、存储器以及寄存器的值,但此功能还远远不能满足小车调试的需要
- 23 -
第八届全国大学生智能汽车竞赛技术报告
方案二:使用串口猎人,如下
- 24 -
智能车控制软件设计说明
该软件使用串口通信的方式与下位机进行通信,如果使用蓝牙,还可以进行无线数据传输,便于车在行驶的过程中实时观察数据变化。该软件还可以自行设计通信协议,同时可以显示多条波形,可以满足大部分的调试需求,具有普适性,但对于某些特殊的要求,该软件还是有一些欠缺。
方案三:使用Labview开发工具 自行设计上位机,
LabVIEW是一种程序开发环境,由美国国家仪器(NI)公司研制开发的,类似于C和BASIC开发环境,但是LabVIEW与其他计算机语言的显著区别是:其他计算机语言都是采用基于文本的语言产生代码,而LabVIEW使用的是图形化编辑语言G编写程序,产生的程序是框图的形式。labview拥有非常强大的库函数,图像处理、机器人控制、信号处理、各种通信、FPGA、英特网接口等等。
- 25 -
第八届全国大学生智能汽车竞赛技术报告
使用Labview的VISA串口控件、图形显示控件就能实现下位机参数的接收和实时显示,但仅仅是接收和显示还不能满足我们的需要,因此,我们还使用了Labview的文件文件I/O控件进行参数的保存,这样,把之前的数据调出来就可以进行对比分析,十分方便,对所存数据的读取显示由另外两个子Vi来完成
- 26 -
智能车控制软件设计说明
调试工具的制作,除了使用Labview外,还可以使用Matlab,Matlab的数据处理能力非常强大,但对于小车的制作来说,由于数据量不算太大,所以仅仅使用Labview就可以满足。
综上,我们在最后的调试选择了方案三。
- 27 -
第八届全国大学生智能汽车竞赛技术报告
第五章 系统调试
开发工具使用的是大赛组委会提高的Codewarrior5.0开发环境,如图5.1.1所示。它能够为单片机 XS128提供与之配套的应用程序开发模块。在目标程序的下载方面,通过BDM与单片机之间的连接下载程序。在调试方面,使用了XS128的串口,利用串口线 XS128和PC的串口相连,使用串口调试工具或PC的超级终端进行程序的调试。使用Altium Designer设计硬件电路
。
图5.1
- 28 -
智能车控制软件设计说明
第六章 车辆主要参数
- 29 -
第八届全国大学生智能汽车竞赛技术报告
第七章 总结
文中介绍了如下内容,智能车机械结构的设计和制作方法,以及如何将智能车优化为适合竞速的模型;智能车各个模块的工作原理和设计电路,如电源模块、电机驱动模块、测速模块等;智能车速度控制算法和角度控制算法;系统开发过程中所用到的开发工具、软件以及调试过程。综合来看,智能车包括硬件和软件部分,是综合多学科知识的平台,对于我们专业课的学习和知识面的扩展有极大的帮助。
通过本次比赛,我们都学到了很多知识,对于汽车的机械结构、光电传感器、软件设计有了深入的了解,最关键的是掌握了一套较为完善的系统开发流程。
- 30 -
智能车控制软件设计说明
参考文献
[1] 邵贝贝. 嵌入式实时操作系统[LC/OS-Ⅱ(第2版)[M]. 北京.清华大学出版社.2004
[2] 谭浩强,C语言程序设计[M].清华大学出版社,2006.1 [3]新型PID控制及其应用2002年作者:陶永华主编
[4]周金萍等《MATLAB6.5 实践与提高》,中国电力出版社
[5]MC33886 Technical Data, Freescale Semiconductor July 2005. [6]卓晴.基于电磁引导的智能车控制算法
[7]Ramon Pallas-Areny, John G. Webster. 传感器和信号调节(第二版)[M].北京:清华大学出版社,2003.
- 31 -
第八届全国大学生智能汽车竞赛技术报告
附录1:部分程序源代码
#include /* common defines and macros */
#include
#include
#include
UINT8 send_buf[17]={
- 32 -
附录1:部分程序源代码
UINT8 send_flag=0; UINT8 test_luzhang=0; UINT8 test = 0;
UINT8 go_enable=0;//配置完毕出发 UINT8 send_enable = 0; UINT8 speed_enable=1; UINT8 cross_flag=0; UINT8 Luzhang_flag=0;
UINT8 LuzhangDetect_flag=0; UINT8 Luzhang_enable=0; int Luzhang=0;
UINT8 Luzhang_count=0; UINT8 Luzhang_Detect=0; UINT8 Luzhang_show=0; UINT8 Count_Delay=0;
UINT8 Image_enable=1;//AD采集中的变量定义 UINT16 Zero_Get_Value;
/*******************************************************************************/
//姿态控制中的变量的定义 float g_fAngleDeltaValue=0; int g_nCarAcceVal;
int g_nCarGyroVal; //AD读到的加速度和角加速度的电压均值 int g_nCarAngle;
int ACCER_OFFSET =1468;//1490; //加速度计零偏值 V //1350 int GYRO_ZERO =1590 ; //陀螺仪零偏 V // 1633 int GYRO_ZERO_Temp=0;
float g_fGravityAngle ; //转换后的陀螺仪角度
float g_fGyroscopeAngleSpeed;//转换后的陀螺仪角速度 float g_fCarAngle; //运算后的角度
float g_fGyroscopeAngleIntegral;//角速度积分后的角度 float g_fAngleControlOut=0;
float AnglePgain = 0.36;//0.36;//0.4;
- 33 -
第八届全国大学生智能汽车竞赛技术报告
float AngleDgain = 0.042;//0.042;//0.05; float AngleDgainTemp=0.0;//0.34; float AnglePgainTemp=0.0;//0.004; UINT8 Zero_Get_enable;
/*******************************************************************************/
/*******************************************************************************/
//速度PI控制
int g_nSpeedRightCe; int g_nSpeedLeftCe;
UINT8 g_nSpeedControlPeriod=0; float g_fSpeedSet=31.5;//31.5 float g_fSpeedZhidao=34.0;
float g_fSpeedZhangai=27.5;//30.0 float g_fSpeedXiapo=27.0;
float g_fSpeedQipao=30.0;//30.0
float g_fSpeedGet=0 ; // float SpeedP_Luzhang=0.2;
float SpeedPgain =0.4;//0.810; float SpeedIgain =0.008;//0.017; float g_fSpeedControlOut=0.0; float g_fSpeedControlOut_Old=0.0; float g_fSpeedControlIntegral; float g_fSpeedControlOutOld; float g_fSpeedControlOutNew; float fCarSpeed=0; float g_fCarSpeed=0;
UINT8 g_nSpeedControlCount; int g_nSpeedRightCount=0; int g_nSpeedLeftCount=0; float g_fSpeedAveRight=0; float g_fSpeedAveLeft=0; float g_fCarSpeedSet=0; UINT8 speed_control=1; float fCarSpeed_old=0.0; UINT8 first_to_speed=0; UINT8 SuDulvbo_Enable=0; UINT8 XianFuQieHuan=0;
- 34 -
附录1:部分程序源代码
UINT8 Hufuwanbi=0; UINT8 JianSu_flag=0;
/*******************************************************************************/
/*******************************************************************************/
//方向PD控制
UINT8 Line_Solve_Flag=0; UINT8 Right_Temp=0; UINT8 Left_Temp=0;
UINT8 Left_Loss_Search=0; UINT8 Right_Loss_Search=0; UINT8 PixelAverage_count=0; UINT8 Black_flag=0; UINT8 loss = 0;
unsigned char half_plus = 48;//48; UINT8 half_plus_Acce; unsigned char Pixel[128];
unsigned char Show_Pixel[128]; UINT8 Baud_Pixel[128]; int left_edge=20; int right_edge=107; int right_edge_old=107; int left_edge_old=20; float center = 64;
int center_queue[2]=0; UINT8 right_loss_count; UINT8 left_loss_count;
float g_fDirectionControlOutNew; float g_fDirectionControlOutOld; UINT8 g_nDirectionControlPeriod ;
UINT8 g_nDirectionControlCount; float g_ffDD=0; UINT8 Road_Width;
unsigned char PixelAverageValue; UINT8 PixelAverageValue_old; unsigned char IntegrationTime=5; UINT8 IntegrationTime_old;
- 35 -
第八届全国大学生智能汽车竞赛技术报告
float TurnPgain =0.130; float TurnDgain =1.20; float TurnPgainTemp=0.0;
float TurnDgainTemp=0.0; float g_fDirectionControlOut=0; UINT8 thre=90;
UINT8 right_valid_line_num; UINT8 left_valid_line_num; UINT8 right_loss_flag ; UINT8 left_loss_flag; float fDelta_Send; int right_max = 0; int left_max = 0; int g_ncenter; UINT8 ucenter;
UINT8 Diff_Max=30; UINT8 ChaZhi_Max=30; UINT8 right_loss_flag_temp; UINT8 left_loss_flag_temp ; float Direction_Delta[2]=0; UINT8 cross=0; UINT8 thre_max=0; UINT8 thre_min=0;
UINT8 SpecialControl=0; UINT8 beep_flag=0;
UINT8 Stop_Speed_Enable=0; float g_fDelta_error=0.0; UINT8 left_diushi_count=0; UINT8 right_diushi_count=0;
//电机控制
float g_fLeftMotorOut; float g_fRightMotorOut; unsigned char CmdFlag = 1; UINT16 Current_Speed; int Speed;
void main(void) {
- 36 -
附录1:部分程序源代码
UINT8 key;
Zero_Get_enable=0; DisableInterrupts; Port_Init(); Pll_Init(); PWM_Init(); TIM_Init(); Pit_Init(); AD_Init();
Debug_Driver_Init(); //检测程序初始化 UART0_Init(); Wdog_Init(); ui_init(); beep();
if(Zero_Get_enable==0) {
Delay_1ms (2000);
Zero_Get(GYRO_CHANNEL,&temp_int); GYRO_ZERO=Zero_Get_Value; }
EnableInterrupts; main_setting(); Delay_1ms(1500); for(;;) {
key=key_get();
if(key!= KEY_NOP){ Delay_1ms(20); key=key_get();
if(key!= KEY_NOP){ main_setting(); Delay_1ms(1500); } }
if((go_enable==1)&&(send_flag==1)){ UART0_SendByte(send_buf[0]); UART0_SendByte(send_buf[1]); UART0_SendByte(send_buf[2]);
- 37 -
第八届全国大学生智能汽车竞赛技术报告
UART0_SendByte(send_buf[3]); UART0_SendByte(send_buf[4]); UART0_SendByte(send_buf[5]); UART0_SendByte(send_buf[6]); UART0_SendByte(send_buf[7]); UART0_SendByte(send_buf[8]); UART0_SendByte(send_buf[9]); UART0_SendByte(send_buf[10]); UART0_SendByte(send_buf[11]); UART0_SendByte(send_buf[12]); UART0_SendByte(send_buf[13]); UART0_SendByte(send_buf[14]); UART0_SendByte(send_buf[15]); UART0_SendByte(send_buf[16]); send_flag=0; } } } }
#include
#include
//姿态控制中的变量的定义 extern int g_nCarAcceVal;
extern int g_nCarGyroVal; //AD读到的加速度和角加速度的电压均值 extern int ACCER_OFFSET ; //加速度计零偏值 V extern int GYRO_ZERO ; //陀螺仪零偏 V extern float g_fGravityAngle ; //转换后的陀螺仪角度
extern float g_fGyroscopeAngleSpeed;//转换后的陀螺仪角速度 extern float g_fCarAngle; //运算后的角度
extern float g_fGyroscopeAngleIntegral;//角速度积分后的角度 extern float g_fAngleControlOut; extern float AnglePgain; extern float AngleDgain;
- 38 -
附录1:部分程序源代码
extern UINT8 go_enable; extern int g_nCarAngle; extern float g_fCarSpeedSet; extern UINT8 send_buf[17]; extern float AngleDgainTemp; extern float AnglePgainTemp;
void Voltage_Gravity(void){
UINT8 i;
UINT16 AcceMax,AcceMin,temp[1]; INT32 lCarAcceValSum;
lCarAcceValSum=0; AcceMax=0; AcceMin=4095; for(i=0;i
MyAdRead(ACCE_CHANNEL,&temp[0]); lCarAcceValSum+=temp[0];
if( temp[0] > AcceMax ) AcceMax = temp[0]; if( temp[0]
g_nCarAcceVal = ((INT16)((lCarAcceValSum ACCER_OFFSET); }
void Voltage_Gryo(void){
UINT8 i;
UINT16 GyroMax,GyroMin,temp[1]; INT32 lCarGyroValSum;
lCarGyroValSum=0; GyroMax=0; GyroMin=4095; for(i=0;i
MyAdRead(GYRO_CHANNEL,&temp[0]);
- 39 -
- AcceMax - AcceMin) >>3) -
第八届全国大学生智能汽车竞赛技术报告
lCarGyroValSum+=temp[0];
if( temp[0] > GyroMax ) GyroMax = temp[0]; if( temp[0]
g_nCarGyroVal = ((INT16)((lCarGyroValSum - GyroMax - GyroMin) >>3) - GYRO_ZERO); }
void AngleCalculate(void){ float fDeltaValue;
int nGyro_Angle,nGravityAngle;
UINT8 Gyro_Angle_H,Gyro_Angle_L,GravityAngle_H,GravityAngle_L; UINT8 Gyro_H,Gyro_L;
g_fGravityAngle = g_nCarAcceVal*Rz;
g_fGyroscopeAngleSpeed = g_nCarGyroVal*Rgyro;//角速度g_fCarAngle=g_fGyroscopeAngleIntegral; g_nCarAngle= (int)(g_fCarAngle/Rz);
fDeltaValue=( g_fGravityAngle-g_fCarAngle)/Tz; g_fAngleDeltaValue=fDeltaValue;
g_fGyroscopeAngleIntegral += ( g_fGyroscopeAngleSpeed + fDeltaValue );
//nGravityAngle=(int)(g_fGravityAngle*100);
//GravityAngle_H=(byte)((nGravityAngle&0xff00)>>8); //GravityAngle_L=(byte)(nGravityAngle&0x00ff); //send_buf[5]= GravityAngle_H; //send_buf[6]= GravityAngle_L;
//GYROSCOPE_ANGLE_SIGMA_FREQUENCY; //nGyro_Angle=(int)(g_fCarAngle*100);
//Gyro_Angle_H=(byte)((nGyro_Angle&0xff00)>>8); //Gyro_Angle_L=(byte)(nGyro_Angle&0x00ff); //send_buf[3]= Gyro_Angle_H; //send_buf[4]= Gyro_Angle_L;
//Gyro_H=(byte)(((g_nCarGyroVal)&0xff00)>>8); //Gyro_L=(byte)(g_nCarGyroVal&0x00ff); //send_buf[7]=Gyro_H; //send_buf[8]=Gyro_L;
- 40 -
单位转化
附录1:部分程序源代码
}
void AngleControl(void){
float fValue;
UINT8 AngleControl_H,AngleControl_L; int nAngleControl;
g_fCarSpeedSet= g_fSpeedControlOut;
fValue=g_fGyroscopeAngleSpeed*AngleDgainTemp*0.1+(g_fCarAngle)*AnglePgainTemp g_fAngleControlOut = fValue;
//nAngleControl=(int)(g_fAngleControlOut*100);
//AngleControl_H=(byte)((nAngleControl&0xff00)>>8); //AngleControl_L=(byte)(nAngleControl&0x00ff); //send_buf[9]=AngleControl_H; //send_buf[10]=AngleControl_L; }
#include
extern int g_nSpeedRightCe; extern int g_nSpeedLeftCe; extern float g_fSpeedSet ; extern float SpeedPgain; extern float SpeedIgain;
extern float g_fSpeedControlIntegral; extern float g_fSpeedControlOutOld;
- 41 -
第八届全国大学生智能汽车竞赛技术报告
extern float g_fSpeedControlOutNew; extern float g_fCarSpeed;
extern float g_fSpeedControlOut;
extern UINT8 g_nSpeedControlPeriod; extern UINT8 go_enable; extern float g_fSpeedGet;
extern int g_nSpeedRightCount; extern int g_nSpeedLeftCount; extern float g_fSpeedAveRight; extern float g_fSpeedAveLeft; extern float g_fLeftMotorOut; extern float g_fRightMotorOut; extern float fCarSpeed;
extern float g_fAngleControlOut; extern float g_fDirectionControlOut; extern UINT8 send_buf[17]; extern float fCarSpeed_old;
void RightSpeedGet(void){
g_nSpeedRightCe = PACNT;
if(PORTT_BIT_GET(RD)==0) g_nSpeedRightCe *= (-1); PORTT_BIT_SET(CHOOSE); Clear_enconder;
g_nSpeedRightCount+=g_nSpeedRightCe; }
void LeftSpeedGet(void){
g_nSpeedLeftCe = PACNT;
if(PORTT_BIT_GET(LD)) g_nSpeedLeftCe *= (-1); PORTT_BIT_CLR(CHOOSE); Clear_enconder;
g_nSpeedLeftCount+=g_nSpeedLeftCe; }
- 42 -
附录1:部分程序源代码
void SpeedControl(void){ float fDelta,fCarSpeedReal; float fP,fI;
UINT8 fCarSpeed_H,fCarSpeed_L,fCarSpeedReal_H,fCarSpeedReal_L, fSpeedControlIntegral_H,fSpeedControlIntegral_L; int nfCarSpeed,nfCarSpeedReal,nSpeedControlIntegral;
fCarSpeed = (g_nSpeedLeftCe+g_nSpeedRightCe)/2;
fCarSpeedReal= (g_fSpeedAveRight+g_fSpeedAveLeft)*0.5;
fCarSpeed=fCarSpeed_old*0.6+(g_fSpeedAveRight+g_fSpeedAveLeft)*0.2; g_fCarSpeed =fCarSpeed*CAR_SPEED_CONSTANT; fDelta = g_fSpeedGet- g_fCarSpeed; fP = fDelta * SpeedPgain; fI = fDelta * SpeedIgain;
if( g_fSpeedControlIntegral >=3)//8) ){ if( fDelta
g_fSpeedControlIntegral += fI;; }
}else if( g_fSpeedControlIntegral 0 ) { g_fSpeedControlIntegral += fI; } }else{ g_fSpeedControlIntegral += fI; }
fCarSpeed_old=fCarSpeed;
//nfCarSpeedReal=(int)(fCarSpeedReal);
//fCarSpeedReal_H=(byte)((nfCarSpeedReal&0xff00)>>8); //fCarSpeedReal_L=(byte)(nfCarSpeedReal&0x00ff); //send_buf[3]=fCarSpeedReal_H; //send_buf[4]=fCarSpeedReal_L; //nfCarSpeed=(int)(fCarSpeed);
- 43 -
第八届全国大学生智能汽车竞赛技术报告
//fCarSpeed_H=(byte)((nfCarSpeed&0xff00)>>8); // fCarSpeed_L=(byte)(nfCarSpeed&0x00ff); // send_buf[5]=fCarSpeed_H; //send_buf[6]=fCarSpeed_L;
//nSpeedControlIntegral=(int)(g_fSpeedControlIntegral*10);
//fSpeedControlIntegral_H=(byte)((nSpeedControlIntegral&0xff00)>>8); //fSpeedControlIntegral_L=(byte)(nSpeedControlIntegral&0x00ff); //send_buf[7]=fSpeedControlIntegral_H; //send_buf[8]=fSpeedControlIntegral_L; }
//缓冲函数
void SpeedControlOutput(void){ float fValue;
UINT8 SuduControl_H,SuduControl_L; int nSuduControl;
fValue = g_fSpeedControlOutNew - g_fSpeedControlOutOld;
g_fSpeedControlOut=fValue*g_nSpeedControlPeriod/SPEED_CONTROL_PERIOD+g_fSpeedControlOutOld;
// nSuduControl=(int)(g_fSpeedControlOut*100);
//SuduControl_H=(byte)((nSuduControl&0xff00)>>8); //SuduControl_L=(byte)(nSuduControl&0x00ff); //send_buf[11]=SuduControl_H; //send_buf[12]=SuduControl_L; }
#include
#include
- 44 -
附录1:部分程序源代码
/* 外部变量声明 */
extern float g_fDirectionControlOut; extern UINT8 right_loss_flag ; extern UINT8 left_loss_flag; extern UINT8 thre;
extern unsigned char Pixel[128]; extern int left_edge; extern int right_edge; extern int right_edge_old; extern int left_edge_old; extern float center;
extern unsigned char half_plus ;
extern float g_fDirectionControlOutNew; extern float g_fDirectionControlOutOld; extern float TurnPgain ; extern float TurnDgain ;
extern UINT8 g_nDirectionControlPeriod; extern int right_max ; extern int left_max ;
extern UINT8 Diff_Max; extern UINT8 loss;
extern UINT8 go_enable;
extern UINT8 left_diushi_count; extern UINT8 right_diushi_count; extern UINT8 Luzhang_flag; extern UINT8 thre_max; extern UINT8 thre_min; extern UINT8 send_buf[17];
void StartIntegration(void) {
unsigned char i;
PORTA_BIT_SET(0); /* SI = 1 */ SamplingDelay();
PORTA_BIT_SET(2); /* CLK = 1 */ SamplingDelay();
PORTA_BIT_CLR (0); /* SI = 0 */
- 45 -
第八届全国大学生智能汽车竞赛技术报告
SamplingDelay();
PORTA_BIT_CLR (2); /* CLK = 0 */
for(i=0; i
PORTA_BIT_SET(2); /* CLK = 1 */ SamplingDelay(); SamplingDelay();
PORTA_BIT_CLR (2); /* CLK = 0 */ }
SamplingDelay(); SamplingDelay();
PORTA_BIT_SET(2); /* CLK = 1 */ SamplingDelay(); SamplingDelay();
PORTA_BIT_CLR (2); /* CLK = 0 */ }
void ImageCapture(unsigned char * ImageData) {
unsigned char i;
unsigned int temp_int;
PORTA_BIT_SET(0); /* SI = 1 */ SamplingDelay();
PORTA_BIT_SET(2); /* CLK = 1 */ SamplingDelay();
PORTA_BIT_CLR (0); /* SI = 0 */ SamplingDelay();
for(i = 0; i
MyAdRead(0,&temp_int);
*ImageData++ = (byte)(temp_int>>4);
PORTA_BIT_CLR (2); /* CLK = 0 */ for(i=0; i
- 46 -