常州大学_光电组_风一
第八届“飞思卡尔”杯全国大学生
智能汽车竞赛
技 术 报 告
学 校:常州大学
队伍名称:风一队
参赛队员:张广灿
徐幸男
陶鹏
带队教师:
关于技术报告和研究论文使用授权的说明
本人完全了解第七届“飞思卡尔”杯全国大学生智能汽车邀请赛关保留、使用技术报告和研究论文的规定,即:参赛作品著作权归参赛者本人,比赛组委会和飞思卡尔半导体公司可以在相关主页上收录并公开参赛作品的设计
、技术报告以及参赛模型车的视频、图像资料,并将相关内容编纂收录在组委会出版论文集中。
参赛队员签名:
带队教师签名:
日 期:
I
目录
第一章 引言 ..................................................................1
1.1大赛介绍 ............................................................................................................. 1 第二章整体设计方案 ...........................................................2
2.1智能车直立寻迹原理............................................................................................ 2
2.1.1直立车模任务分解 ..................................................................................... 2
2.1.2直立控制 ................................................................................................... 3
2.2 智能车整体结构.................................................................................................. 5
2.3车模整体 ............................................................................................................. 5
第三章 车模机械结构 ..........................................................6
3.1 车模简化改装 ..................................................................................................... 6
3.2 线性CCD高度选择 ............................................................................................ 8
3.3 电池的安装方式.................................................................................................. 8
3.4测速编码器的安装 ............................................................................................... 9
3.5陀螺仪与加速度计的位置选择............................................................................ 10
3.6主板与驱动板的安装固定................................................................................... 11
3.7轮胎处理 ........................................................................................................... 12
3.8各个模块的连接................................................................................................. 13 第四章 硬件配置与电路设计 ...................................................14
4.1 微处理器选择 ................................................................................................... 14
4.2 资源需求分析 ................................................................................................... 15
4.3电源模块 ........................................................................................................... 15
4.4电机驱动模块 .................................................................................................... 16 第五章 软件设计 .............................................................17
5.3软件功能框架 .................................................................................................... 17
5.4 K60的硬件资源配置.......................................................................................... 18
5.5 主要算法及实现................................................................................................ 18 第六章 开发工具介绍 .........................................................27
6.1 IAR开发平台 .................................................................................................... 27
6.1.1开放平台介绍......................................................................................... 27
6.1.2下载工具介绍 .......................................................................................... 27
6.1.3野火底层库介绍 ....................................................................................... 28
6.2辅助调试软件 .................................................................................................... 30
6.2.1蓝宙CCD助手......................................................................................... 30
6.2.2下位机数据格式 ....................................................................................... 31
6.2.3蓝牙调试串口助手 ................................................................................... 32 第七章 参数调试 .............................................................36
7.1 调试参数 .......................................................................................................... 37 参考文献 .....................................................................I
附录 ........................................................................II
II
第一章 引言
1.1大赛介绍
为加强大学生实践、创新能力和团队精神的培养,促进高等教育教学改革,受教育部高等教育司委托(教高司函[2005]201号文,附件1),由教育部高等学校自动化专业教学指导分委员会(以下简称自动化分教指委)主办全国大学生智能汽车竞赛。该竞赛是以智能汽车为研究对象的创意性科技竞赛,是面向全国大学生的一种具有探索性工程实践活动,是教育部倡导的大学生科技竞赛之一。该竞赛以“立足培养,重在参与,鼓励探索,追求卓越”为指导思想,旨在促进高等学校素质教育,培养大学生的综合知识运用能力、基本工程实践能力和创新意识,激发大学生从事科学研究与探索的兴趣和潜能,倡导理论联系实际、求真务实的学风和团队协作的人文精神,为优秀人才的脱颖而出创造条件。
该竞赛由竞赛秘书处设计、规范标准硬软件技术平台,竞赛过程包括理论设计、实际制作、整车调试、现场比赛等环节,要求学生组成团队,协同工作,初步体会一个工程性的研究开发项目从设计到实现的全过程。该竞赛融科学性、趣味性和观赏性为一体,是以迅猛发展、前景广阔的汽车电子为背景,涵盖自动控制、模式识别、传感技术、电子、电气、计算机、机械与汽车等多学科专业的创意性比赛。该竞赛规则透明,评价标准客观,坚持公开、公平、公正的原则,力求向健康、普及、持续的方向发展。
该竞赛以飞思卡尔半导体公司为协办方,得到了教育部相关领导、飞思卡尔公司领导与各高校师生的高度评价,已发展成全国30个省市自治区近300所高校广泛参与的全国大学生智能汽车竞赛。2008年起被教育部批准列入国家教学质量与教学改革工程资助项目中科技人文竞赛之一(教高函[2007]30号文)。
2
第八届全国大学生智能汽车邀请赛技术报告
第二章整体设计方案
2.1智能车直立寻迹原理
2.1.1直立车模任务分解
根据比赛规则要求,维持车模直立也许可以设计出很多的方案,本参考方案假设维持车模直立、运行的动力都来自于车模的两个后车轮。后轮转动由两个直流电机驱动。因此从控制角度来看,车模作为一个控制对象,它的控制输入量是两个电极的转动速度。车模运动控制任务可以分解成以下三个基本控制任务,如图2. 1所示:
(1) 控制车模平衡:通过控制两个电机正反向运动保持车模直立平衡状态;
(2) 控制车模速度:通过调节车模的倾角来实现车模速度控制,实际上最后还是演变成通过控制电机的转速来实现车轮速度的控制。
(3) 控制车模方向:通过控制两个电机之间的转动差速实现车模转向控制。
图2.1
三个分解后的任务各自独立进行控制。由于最终都是对同一个控制对象(车模的电机)进行控制,所以它们之间存在着耦合。为了方便分析,在分析其中之一时假设其它控制对象都已经达到稳定。比如在速度控制时,需要车模已经能够保持直立控制;在方向控制的时候,需要车模能够保持平衡和速度恒定;
2
第二章整体设计方案 同样,在车模平衡控制时,也需要速度和方向控制也已经达到平稳。这三个任务中保持车模平衡是关键。由于车模同时受到三种控制的影响,从车模平衡控制的角度来看,其它两个控制就成为它的干扰。因此对车模速度、方向的控制应该尽量保持平滑,以减少对于平衡控制的干扰。以速度调节为例,需要通过改变车模平衡控制中车模倾角设定值,从而改变车模实际倾斜角度。为了避免影响车模平衡控制,这个车模倾角的改变需要非常缓慢的进行。 2.1.2直立控制
车模平衡控制是通过负反馈来实现的。因为车模有两个轮子着地[2],车体只会在轮子滚动的方向上发生倾斜。控制轮子转动,抵消在一个维度上倾斜的趋势便可以保持车体平衡了。如图2.2所示。
图2.2
下面对倒立车模进行简单数学建模,然后建立速度的比例微分负反馈控制,根据基本控制理论讨论车模通过闭环控制保持稳定的条件。 假设倒立车模简化成高度为L,质量为m的简单倒立摆,它放置在可以左右移动的车轮上。假设外力干扰引起车模产生角加速度()xt。沿着垂直于车模地盘方向进行受力分析,可以得到车模倾角与车轮运动加速度以及外力干扰加速度()at()xt之间的运动方程。如图2.3所示。
3
第八届全国大学生智能汽车邀请赛技术报告
图2.3
对应车模静止时,系统输入输出的传递函数为:
右半平面,因此车模不稳定。车模引入比例、微分反馈之后的系统如下图所示:
图2.4 加入比例微分反馈后的系统框图
这一点,需要k1>g,k2>0。由此可以得出结论,当k1>g,k2>0时,直立车模可以稳定。
在角度反馈控制中,与角度成比例的控制量是称为比例控制;与角速度成比例的控制量称为微分控制(角速度是角度的微分)。因此上面系数分别称为比例和微分控制参数。其中微分参数相当于阻尼力,可以有效抑制车模震荡。通过微分抑制控制震荡的思想在后面的速度和方向控制中也同样适用。
控
4
第二章整体设计方案 制车模直立稳定的条件如下:
(1)能够精确测量车模倾角θ的大小和角速度θ'的大小;
(2)可以控制车轮的加速度。
2.2 智能车整体结构
本次智能车的设计是基于飞思卡尔公司的32位高性能单片机kinetis k60单片机为核心的,以线性CCD为基础的智能车系统。系统主要由单片机最小系统、角度计算传感器,探测道路信息的线性ccd以及电机和电机驱动组成。如图2.5:
图2.5
2.3车模整体
车模使用的是官方的c车车模,因为要求直立行走,拆除了前轮及舵机,后轮使用两个4.7w直流伺服电机驱动。整体包括车架、电机、电池、驱动板、主控制板、速度编码器、陀螺仪、加速度计、线性ccd等部件。如图2.6:
5
第八届全国大学生智能汽车邀请赛技术报告
*
图2.6
第三章 车模机械结构
3.1 车模简化改装
原有车模为了减轻后轮振动对于车体的影响,后轮的支架与底盘之间采用了活动连接方式。但是,为了保证车模直立车体稳定性,需要将原有车模地盘与后轮支架固定在一起。最简便的方式就是可以使用热熔胶在后轮支架与底盘之间的缝隙处进行粘接。这样后轮与车体之间形成一个刚体,便于进行直立控制。如图3.1:
6
第三章 车模机械结构
图3.1
但是这是不够的,为了跟好大加固,再用PCB板加强缝隙部分,作如下处理方式 ,能更好的加强车体的链接。如图3.2
如图3.2
7
第八届全国大学生智能汽车邀请赛技术报告
3.2 线性CCD高度选择
线性CCD是小车的眼睛,是判别赛道的重要传感器,CCD的安装高度与倾斜度决定了小车的视野大小,如图3.3:
图3.3
小车视野狭窄会导致小车调整方向时的死区问题,保证赛道黑线在视野范围内,能够使小车及时纠正方向,所以我们使用了30cm高的碳纤维管,来安装CCD。如图3.4:
图3.4
3.3 电池的安装方式
所有小车的部件安装都要尽量保证小车的重心足够低,而电池是这么多零件中最重的,所以电池的安装位置对小车有很大的影响。我们考虑到影响小车平衡的两个转动惯量,以车轴为轴心的转动惯量和转向的转动惯量,电池安装
8
第三章 车模机械结构 有两个方案:
1,竖直安装,如图3.5
图3.5
2.水平安装,如图3.6:
图3.6
方案一相对于方案二来说,转向转动惯量虽然小了,但是重心偏高,而且占用了较大的空间,权衡利弊,我们选择了方案二,水平安装,如图3.7:
图3.7
3.4测速编码器的安装
编码器是用于测量小车运行速度的,由于小车只沿一个方向运行,就选择
9
第八届全国大学生智能汽车邀请赛技术报告
了欧姆龙300线的编码器,为了减小因齿轮之间回程差而引起的测速误差,所以选择将编码器的轴通过车轮直接连在电机轴上。齿轮间咬合不宜太紧,否则会增大阻力矩;不宜太松,否则会造成咬合不当,造成误差。如图3.8:
图3.8
3.5陀螺仪与加速度计的位置选择
陀螺仪和加速度计的组合是小车最重要的传感器,它们的工作效率决定了小车站立的稳定度,所以为它们选择一个良好的安装位置也是十分重要的。因为陀螺仪测得的是角速度,所以水平放置就可以了,而加速度计测得的是传感器一面所受的感应力,所以小车的前后摆动和加速与减速都会对加速度计造成干扰,所以怎样减少传感器垂直轴上的干扰是安装加速度计时要考虑的首要问题。经过观察,我们发现,越接近单摆轴的地方干扰越小,所以我们选择了相对靠下的位置,如图3.9:
10
第三章 车模机械结构
图3.9
3.6主板与驱动板的安装固定
重心过高会造成车模的不稳定容易跌倒,所以为了减小重心高度将主板安装在电机上方的位置,并用热熔胶将其固定,防止掉落。
驱动板则固定在电机的正上方,为了防止破坏赛道,将其用薄泡沫盖住。如图3.10:
图3.10
11
第八届全国大学生智能汽车邀请赛技术报告
3.7轮胎处理
1. 轮胎粘死,轮胎的橡胶部分和轮毂用502粘死,搞的里面像充足气一样。
好处是过弯时没有轮胎和轮毂的错位导致转角没有转到位。如图3.11:
图3.11
2. 打磨轮胎,众所周知,新轮胎的摩擦力是不足的,需要进行打磨处理,
这个如何打磨貌似有很多方法,但是归到最终就是多在赛道上磨合,然
后比赛的时候保留一份轮子。轮子中间有凸起的一圈,尽量去掉和磨平。
如图3.12
12
第三章 车模机械结构
图3.12
3.8各个模块的连接
为了降低连接线的重量,及减少线的故障率,使线清晰,不乱,易于检查接线故障,所以决定自己做的接线,编码器的部分直接插在主板槽上,减少接线如图3.13
图3.13
13
第八届全国大学生智能汽车邀请赛技术报告
第四章 硬件配置与电路设计
4.1 微处理器选择
根据第八届飞思卡尔细则我们选择了K60芯片作为微控制器,K60是32微处理器,处理速度足以满足实际需求,而且容易下得K60开发的底层库,以野火的底层最为出名,大大节省开发时间与周期,使编程变得容易。
我们选择了市场上价格相对便宜的一款K60系统版
14
第四章 硬件配置与电路设计
K60的常用外设
(1) PWM:三个FTM模块,可提供8路以上PWM通道
(2) AD :两个,,位,,,模块,可测,,,,,,,,,,位精度 (3) PIT :四个通用中断定时器,32位计数器
(4) 低功耗时钟(LPTimer):可用于累计脉冲
(5) 通信接口:CAN, SPI, I?C , UART
(6) 通用I/O口(GPIO):除特殊引脚及电源引脚外的其他引脚都可配置为
GPIO.
(7) DMA模块: DMA控制器提供可编程的通道,为8位、16位、32位、128
位提供双地址存取传送。
4.2 资源需求分析
根据实际方案可以得到实际所需的处理器资源如下
(1)4路PWM:用于电机正反转。
2)4路AD :一路测加速度,一路测陀螺仪,一路测CCD,还有一路预留。 (
(3)UART:用于程序调试,与上位机通信
(4)GPIO若干:用于液晶显示,按键及其他
(5)2路DMA:通过DMA的特殊特点进行测速。
4.3电源模块
单片机使用5v或者3.3v直流电源,其他模块如陀螺仪、加速度计、液晶屏、线性ccd都使用5v电源,而比赛规定电池为7.2v直流电源,所以我们使用了线性稳压器LM2940作为各个模块的电源,考虑到多个模块使用同一片稳压器会导致稳压器发热量大,工作不稳定,所以我们做了两路电源,对模块电源的使用做了合理分配。
第一路电源主要用于单片机,陀螺仪,加速度计等重要模块的电源供电,防止电源不稳定带来采集误差。
第二路电源主要用于CCD,液晶显示,编码器,驱动板等对电源稳定性要求不高设备的供电。
LM2940输出电压固定的低压差三端稳压器;输出电压5V;输出电流1A;输出电流1A时,最小输入输出电压差小于0.8V;最大输入电压26V;工作温度-40,+125?;内含
15
第八届全国大学生智能汽车邀请赛技术报告
静态电流降低电路、电流限制、过热保护、电池反接和反插入保护电路。足以满足供电要求。
4.4电机驱动模块
Bts7970是NovalithIC家族三个独立的芯片的一部分:一是p型通道的高电位场效应晶体管,二是一个n型通道的低电位场效应晶体管,结合一个驱动晶片,形成一个完全整合的高电流半桥。两片bts7970构成H桥驱动电机,使得小车具有良好的低速性能。一片hc244增强单片机引脚负载能力,确保输出稳定
。
16
第五章 软件设计
5.3软件功能框架
软件的主要功能
(1)各传感器信号的采集
(2)电机PWM输出;
(3)车模运行控制:直立控制,速度控制,转向控制
(4)车模运行流程控制:程序初始化、车模启动与结。
(5)车模信息显示:状态显视与参数设定等。
上述功能可以分成两大类: 第一类包括1-3功能,它们属里完成。第二类包括4-5功能。它的执行不需要精确的时间周期。可以放在程序的主程序中完成。这两类任务之间可以通过全局变量实现相互的通讯。如图5.1:
如图5.1
17
第八届全国大学生智能汽车邀请赛技术报告
5.4 K60的硬件资源配置
CCD1 SI1 PTA26
AO1 PTB1
CLK1 PTA27
SI2 PTA24 CCD2/预留
AO2 PTB0
CLK2 PTA25 OLED CS PTA11
DC PTA12
RST PTA13
D1 PTA14
D0 PTA15 LED LED1 PTA11
LED2 PTA16
KEY1~KEY6 PTD0~5 按键
TX PTD7 蓝牙
RX PTD6 PWM R+ PTC1
R- PTC2
L+ PTC3
L- PTC4
1 PTC5 编码器
2 PTC6
ENC PTB2 陀螺仪
MMA PTB3 加速度计
表5.1 5.5 主要算法及实现
直立控制
由直立控制的理论分析可知,直立控制需要实际的车模角度,那就要用AD采集
到加速度计与陀螺仪的值进行转化,由于加速度计易受干扰,陀螺仪具有温漂,
所以采用凯尔曼滤波进行角度融合,从而滤波。 凯尔曼滤波函数
float kalman(const float gyro_m,const float incAngle)//只读变量不可以修改
{ // 陀螺仪 角度
float K_0;//含有卡尔曼增益的另外一个函数,用于计算最优估计值
float K_1;//含有卡尔曼增益的函数,用于计算最优估计值的偏差
float Y_0;
float Y_1;
float Rate;
float Pdot[4];
18
第五章 软件设计
float angle_err;//角度偏量
float E;
static float angle = 0; //下时刻最优估计值角度
static float q_bias = 0; //最优估计值的偏差
static float P[2][2] = {{ 1, 0 }, { 0, 1 }};
Rate = gyro_m - q_bias;
Pdot[0] = Q_angle - P[0][1] - P[1][0]; //卡尔曼增益矩阵
Pdot[1] = - P[1][1];
Pdot[2] = - P[1][1];
Pdot[3] = Q_gyro;
angle += Rate * dt;
P[0][0] += Pdot[0] * dt; //计算协方差矩阵
P[0][1] += Pdot[1] * dt;
P[1][0] += Pdot[2] * dt;
P[1][1] += Pdot[3] * dt;
angle_err = incAngle - angle;
E = R_angle + P[0][0];
K_0 = P[0][0] / E;
K_1 = P[1][0] / E;
Y_0 = P[0][0];
Y_1 = P[0][1];
P[0][0] -= K_0 * Y_0; //跟新协方差矩阵
P[0][1] -= K_0 * Y_1;
P[1][0] -= K_1 * Y_0;
P[1][1] -= K_1 * Y_1;
angle += K_0 * angle_err; //给出最优估计值
q_bias += K_1 * angle_err;//跟新最优估计值偏差
return angle;
}
直立控制PID
Void StandConTrol()
{
Pwm=(int)(StandP*(-angleout+AngleG)+StandD*(-AngleDot));
}
StandP是直立P参数
StandD是直立D参数
Angleout是滤波角度
AngleDot是角加速度
19
第八届全国大学生智能汽车邀请赛技术报告
AngleG表示设定角度
速度控制
速度控制需要测量实际速度用到编码器,由于K60本身只有一个测速的LPTMR模块,所以另一路要有别的进行测速,根据野火提供的底层库,可以选择DMA或者FTM测速,由于FTM测速占用PWM模块,所以统一用,,,来测速。
测速初始化
DMA_count_Init(DMA_CH4, PTC6 ,600 , DMA_rising);
DMA_count_Init(DMA_CH3, PTE4 ,600 , DMA_rising);
测速函数
void PulseGet()
{
cd45q=cd45h;
//////////////////
//if(CarStopPulseCountFlag)
// CarStopPulseCount+=cd45h;
/////////////////
cd45h=DMA_count_get(DMA_CH4);
DMA_count_reset(DMA_CH4);
//gmpq=gmph;
//gmph=LPTMR0_CNR;
//lptmr_counter_clean();
gmpq=gmph;
gmph=DMA_count_get(DMA_CH3);
DMA_count_reset(DMA_CH3);
if(cd45h>200) cd45h=250;
if(gmph >200) gmph =250;
LeftPulse +=cd45h;//SpeedFilter(cd45h);
//ic5=SpeedFilter(cd45q);
RightPulse+=gmph;//SpeedFilter(gmph);
//ic6=SpeedFilter(gmpq ); }
速度计算函数,读取5次脉冲求平均值,以相对速度代替实际速度即脉冲个数 void SpeedCount()
{
sudu=(LeftPulse+RightPulse)/2.0/5.0;//五次平均速度哦
LeftPulse =0;
RightPulse=0;
20
第五章 软件设计
if(SpeedIFlag==0&&sudu>70) SpeedIFlag=1;
if(SpeedIFlag==1) sudu_dot+=(SpeedSet-sudu);//速度的积分
if(sudu_dot>50) sudu_dot= 50;//积分限幅
if(sudu_dot<-50) sudu_dot=-50;//积分限幅
}
速度闭环函数
Void SpeedColtrol()
{
SpeedControlOut=SpeedP*(SpeedSet-sudu)+SpeedI*sudu_dot
}
转向控制
转向控制要得到赛道的信息,就需要处理光电传感器的采集值。 线性CCD
这个模块有一般有五个PIN,其中
VCC和GND是电源,建议给低噪声的电源电压,特别是地线的连接质量一定不能差。
SI和CLK是信号输入:注意对于模块是输入,单片机需要配置为输出
AO是模拟信号输出:对于单片机需要配置为模拟输入,并启用ADC转换功能
图5.2
图5.2是单个像素积分器的结构,当S1在1的位置时,开关是断开的,简单分析可得电容上流过的电流和光电器件的光生电流相等,这个电路对光生电流进行积分。
而当S1在2的位置时,积分电容被短路,释放积累的电荷。
21
第八届全国大学生智能汽车邀请赛技术报告
S2用来采样输出,不输出(第129个CLK之后)时,接在1的位置上保持采样电容电压和运放输出一致,当轮到这个像素输出的时,打到3的位置,其他像素输出时在2的位置。
图5.3
图5.4
上面图是时序图(图5.3),简要说明下,CLK是一个上升沿触发的信号,采样一次数据的时候,首先把SI拉高,然后把CLK拉高这时候AO上已经出现了第1个(这里数数的方式是正常人数法不是程序员数法)像素的模拟电压,然后把SI拉低否则积分复位电路工作可能不正常,连续输入128个CLK(指的是上升沿)以后,128个模拟电压已经传输完毕。
根据龙丘的CCD模块参考程序编写了自己的CCD采集程序
CCD采集函数
int GetADSample()
22
第五章 软件设计 {
unsigned char i;
unsigned int ATD0DR0_RETURN;
//ATD0CTL5=0x32;
_CLK_=1;//起始电平高
_SI_=0; //起始电平低
CCD_DelayNS(); //合理的延时
_SI_=1; //上升沿
_CLK_=0;//下降沿
CCD_DelayNS(); //合理延时
_CLK_=1;//上升沿
_SI_=0; //下降沿
CCD_DelayNS(); //合理延时
CCD_DelayMS(); //合理延时
for(i=0;i<128;i++)
{
_CLK_=0;//下降沿
CCD_DelayNS(); //合理延时
CCD_DelayNS();
CCD_DelayNS();
ATD0DR0_RETURN=Pixel[i]=(ad_once(ADC0, SE9,
ADC_12bit))-BlackCCDV;//读取 ADC1_SE6a ,12位精度
//////////////////////////////////////
ccdwatch[i]=Pixel[i]>>2;
///////////////////////////////////////
_CLK_=1;//上升沿
CCD_DelayNS(); //合理延时
CCD_DelayNS();
CCD_DelayNS();
}
return ATD0DR0_RETURN; }
上面用数组Pixel保存了128个采样值,接下来就是要从128个值中得到赛道
信息,由于黑带的光照强度弱,白带强,则可以通过边沿或静态的阈值来判断。
由于调试地方光照均匀就采用静态阈值法,阈值以上为白色赛道,阈值以下为
黑色胶带,通过计算两边白带里中性点的距离之差来判断赛道转向。
23
第八届全国大学生智能汽车邀请赛技术报告
CCD处理函数
void AnalysisPixel1()
{
unsigned char i;
unsigned char count_one_left=0,count_one_right=0;
unsigned char count_zero_left=0,count_zero_right=0;
unsigned char flag_left=1,flag_right=1;
int delta_CCD_result;//,acc_CCD_result;
for(i=0;i<64;i++)
{
if(Pixel[64-i]>_COMP_VALUE_&& flag_left) count_one_left++;
else count_zero_left++;
if(Pixel[64+i]>_COMP_VALUE_&&flag_right) count_one_right++;
else
count_zero_right++;
if(count_zero_left>3)
{
flag_left=0;
}
if(count_zero_right>3)
{
flag_right=0;
}
if( flag_left==0&&flag_right==0) break;
}
if (count_one_left==64&&count_one_right==64)
{
CCD_result[_LEFT_] = 0;
CCD_result[_RIGHT_] =0;
}
else if(count_one_left==0&&count_one_right==0)
{
//CCD_result[_LEFT_] = 0;
24
第五章 软件设计
//CCD_result[_RIGHT_] =0;
}
else if(count_one_left<64&&count_one_right<64)
{
CCD_result[_LEFT_] = count_one_left;
CCD_result[_RIGHT_] = count_one_right;
}
else if(count_one_left<64&&count_one_right==64)
{
CCD_result[_LEFT_] = count_one_left;
CCD_result[_RIGHT_] = 70;//count_one_right;
}
else if(count_one_left==64&&count_one_right<64)
{
CCD_result[_LEFT_] = 70;//count_one_left;
CCD_result[_RIGHT_] = count_one_right;
}
delta_CCD_result = CCD_result[_RIGHT_]-CCD_result[_LEFT_];
//acc_CCD_result = CCD_result[_LEFT_] + CCD_result[_RIGHT_];
//if(acc_CCD_result==0) acc_CCD_result=1;
if(delta_CCD_result>0) RIGHT_LED=0,LEFT_LED=1;
if(delta_CCD_result<0) RIGHT_LED=1,LEFT_LED=0;
if(delta_CCD_result>=-5&&delta_CCD_result<=5)
{
p_CCD_result = (1.0*delta_CCD_result) / 70;//acc_CCD_result ;
}
else
{
p_CCD_result = (1.0*delta_CCD_result) / 70;//acc_CCD_result ;
}
////////////////////
//ic1=delta_CCD_result;
//ic2=acc_CCD_result ;
//////////////////
//AjustDrectionPD(delta_CCD_result);
/////////////////////
}
根据得到的差,乘以比例系数来得到实际的转向PWM,但是由于车体转动会存在
转动惯量,会使转向过冲,车么冲出赛道,所以要去两次转向之差作为D,即转
向进行PD调节。
转向控制。
void DrectionCount()
25
第八届全国大学生智能汽车邀请赛技术报告
{
DirectionOut=DrectionP*MidErr/70.0+DrectionD*MidErrErr/70.0/0.006; }
起跑线检测:起跑线是位于直道的两段黑带组成,检测的主要难度就是误判,
主要有黑色路障误判,虚线误判等,通过观察可知在直道上ccd可以看到两条
边线,当看到起跑线是必然会产生突变沿,通过检测上升或下降沿便可以的达
到检测器跑向的目的。
///////////////////////////////
//起跑线检测条件
if(ABS(DeltAngle)<3&&LostTypeArray[7]==NoneLost&&CarStartLineCheckFlag&&!StartLineFlag)
{
if(LostTypeArray[0]!=Obstacle&&LostTypeArray[1]!=Obstacle
&&LostTypeArray[2]!=Obstacle&&LostTypeArray[3]!=Obstacle
&&LostTypeArray[4]!=Obstacle&&LostTypeArray[5]!=Obstacle
&&LostTypeArray[6]!=Obstacle&&LostTypeArray[8]!=Obstacle
&&LostTypeArray[9]!=Obstacle&&LostTypeArray[10]!=Obstacle
&&LostTypeArray[11]!=Obstacle&&LostTypeArray[12]!=Obstacle
&&LostTypeArray[13]!=Obstacle&&LostTypeArray[14]!=Obstacle)
{
if((LostTypeArray[6]!=WhiteLost&&LostTypeArray[6]!=BlackLost)
&&(LostTypeArray[5]!=WhiteLost&&LostTypeArray[5]!=BlackLost)
&&(LostTypeArray[4]!=WhiteLost&&LostTypeArray[4]!=BlackLost))
{
if((MidSumArray[7]+30)
> 4; if (temp >= 10)
{
PutChar(temp - 10 + 'A');
}
else
{
PutChar(temp + '0'); }
temp = data & 0x0F; if (temp >= 10)
{
PutChar(temp - 10 + 'A');
}
Else
{
PutChar(temp + '0'); }
}
? 、PutChar() 为发送串口数据函数,和用户硬件相关。
6.2.3蓝牙调试串口助手
32
第六章 开发工具介绍
模块说明:
该串口蓝牙模块分为主机模块和从机模块,其中主机模块为USB接口,装上电脑并安装驱动就可以使用,主机模块可以搜索并和与之匹配的蓝牙从机模块通信,从机模块必须由蓝牙主机设备与其连接通信如带蓝牙功能的手机等设备,只有主从之间才能连接通信,从机与从机不能进行通信。如果同时购买了主机和从机模块,两个模块上电后自动匹配连接不需要密码,假如是手机跟从机模块连接则需要输入出厂默认的密码:1234
USB蓝牙主机实物图:
主机模块带可恢复保险丝,以免贵重的电脑意外损坏。主机模块中STATE为状态指示灯,无设备连接是闪烁状态,设备连接成功为长亮状态。POWER为电源指示灯。按一下按键主机就会从新搜索从机设备。
从机模块实物图:
33
第八届全国大学生智能汽车邀请赛技术报告
从机可以安装在小车主板等需要采集数据的主板上,供电电压为5V,带有防反接功能。STATE 为状态指示灯,无设备连接是闪烁状态,设备连接成功为长亮状态,POWER 为电源指示灯。
二、使用方法:
2.1 主机:
主机模块插在电脑USB 口之前可以先双击安装驱动程序:
安装完之后把主机模块插上电脑就可以使用了。
最简单的测试蓝牙模块是否正常方法就是:主机插上已安装好驱动的电脑,从机模块供电 ,将从机模块的RX 和TX 接线端短接,这样就是收发环回,电脑打开串口调试工具,发送什么内容就会接收什么内容,就说明蓝牙模块正常。记得每次要先退出串口调试工具后再拔掉电脑上的蓝牙模块。 2.2从机:
蓝牙模块从机的RX要与MCU的TX连接,蓝牙模块从机的TX要与MCU的RX连接。 蓝牙从机未配对时电流约30mA,配对后约10mA。
三、蓝牙模块参数修改指令集:
一、出厂默认参数: 波特率:9600,配对密码:1234;
二、AT命令集如下: 1、测试通讯 发送:AT(返回OK,一秒左右发一次) 返回:OK
2、改蓝牙串口通讯波特率 发送:AT+BAUD1 返回:OK1200 发送:AT+BAUD2 返回:OK2400 „„
1---------1200 2---------2400 3---------4800 4---------9600
5---------19200 6---------38400 7---------57600 8---------115200
9---------230400 A---------460800 B---------921600 C---------1382400
不建议用在超过115200的波特率,信号的干扰会使系统不稳定。 设置超过115200后用电脑无法使用,要用单片机编程于高于115200才能使用此波特率和
34
第六章 开发工具介绍 重新发AT命令设低波特率 用AT命令设好波特率后,下次上电使用不需再设,可以掉电保存波特率。
虚拟示波器
该虚拟示波器有四个通道CH1,CH2,CH3,CH4,可同时显示四个通道的曲线以不同颜色标识,方便选择。使用时需要在下位机的程序安装具体的通信进行发送数据。具体协议如下:
unsigned short CRC_CHECK(unsigned char *Buf, unsigned char CRC_CNT) //用于CRC校验
{
unsigned short CRC_Temp;
unsigned char i,j;
CRC_Temp = 0xffff;
for (i=0;i>1 ) ^ 0xa001;
else
CRC_Temp = CRC_Temp >> 1;
}
}
return(CRC_Temp);
}
35
第八届全国大学生智能汽车邀请赛技术报告
void OutPut_Data(void)//将四个通道数据加上校验发送出去
{
int temp[4] = {0};
unsigned int temp1[4] = {0};
unsigned char databuf[10] = {0};
unsigned char i;
unsigned short CRC16 = 0;
for(i=0;i<4;i++)
{
temp[i] = (int)OutData[i];
temp1[i] = (unsigned int)temp[i];
}
for(i=0;i<4;i++)
{
databuf[i*2] = (unsigned char)(temp1[i]%256);
databuf[i*2+1] = (unsigned char)(temp1[i]/256);
}
CRC16 = CRC_CHECK(databuf,8);
databuf[8] = CRC16%256;
databuf[9] = CRC16/256;
for(i=0;i<10;i++)
//printf("%c",databuf[i]);
uart_putchar (UART0, databuf[i]);
}
通过定义OutData[4]数组,然后对数组元素赋值,再调用OutPut_Data()函数,就能完成数据的发送。
通过上述蓝牙模块主从设备,将有下位机传来的角度,速度,转向的信息变成实时的曲线显示出来,从而改善预期效果,与实际之间的偏差。
第七章 参数调试
36
第七章 参数调试
车模制作与软件开发为车模运行打下了基础,是否运行的稳定和快速需要通过车模精心的调试才能够完成。调试过程同时也可以使得同学们加深对于控制算法物理过程深刻理解,提高解决实际工程问题的能力,为寻找更加优化的车模设计方案打下基础。调试过程对于竞赛车模制作非常重要。
车模调试分为调试准备、静态参数整定、动态参数整定、车模机械调整和竞赛策略制定等各个环节。整个调试中涉及到的参数和部件非常多,而且这些参数之间还有着紧密的相互影响。如果对于其中的物理过程认识不清,有没有正确的调试步骤,那么在调试过程中出现的各种错误现象就会掩盖正确的原因,影响整个调试进程,甚至会动摇制作的信心。
7.1 调试参数
陀螺仪静态零点值:将车模静止防止,观察液晶屏上的采集量,从而确定陀螺仪静态零点值。
加速度计静态零点值:将车模置于竖直状态观察液晶屏显示采集量,从而确定加速度计零点值。
37
第八届全国大学生智能汽车邀请赛技术报告
为了预防环境变化而引起零点漂移,可以在程序里设置自动采集程序,开机时,将车模置于垂直状态,并尽量保持静止,然后自动采集。
CCD阈值采集:将车模置于赛道分别在背景色与赛道,观察液晶屏,然后取中间值。
直立调试:直立调试主要就是凯尔曼参数的调节,凯尔曼共有(加速度计精度)Q_angle,(陀螺仪精度)Q_gyro,(过程方差)R_angle,(采样时间)dt,四个参数,(加速度计精度)Q_angle,(陀螺仪精度)Q_gyro可有数据手册大至知道,dt也比较容易确定,主要就是相邻两次滤波时间间隔,接下来就是R_angle,要通过反复调试得到。实际调试得到R_angle越小跑起来越抖,R_angle越大滤出角度越不稳定。下面是用虚拟示波器观察出来的,加速度计,与滤波出来角度的比较:
38
第七章 参数调试
黄色是加速度计,粉色是滤出来的波形,可知加速度计易受干扰,滤出波形比较平滑
39
第八届全国大学生智能汽车邀请赛技术报告
上图是小车直立时的波形图,角度基本不变,略有变化。
转向调试:转向有两个参数转向的P与转向的D,P与D根据实际测试效果取得,但是要对参数进行优化,就要经过上位机观察。下边几幅图比较 不同P值下的转向效果:
40
第七章 参数调试
41
第八届全国大学生智能汽车邀请赛技术报告
在不同的P值下观察在知道上车模(蓝色曲线)摆幅,便可以得到一个较好的P值
42
参考文献
参考文献
1. 野火小霸王系列光盘.三天入门M4—Kinetis(v2.2)
2. 竞赛秘书处: 第七届全国大学生“飞思卡尔”杯智能汽车竞赛电磁组直立行车参考
设计方案(版本2.0). 2012.
3. 卓晴, 黄开胜, 邵贝贝. 学做智能车[M]. 3. 北京:北京航空航天大学出版社, 2007年
3月.
4. 谭浩强. C程序设计(第三版)[M]. 2. 北京:清华大学出版社, 2005年1月. 5. 马建伟, 李银伢. 满意PID控制设计理论与方法[M]. 1. 北京:科学出版社, 2007.
I
第八届全国大学生智能汽车邀请赛技术报告
附录
程序
void d2c(u8 *s,const char* ss,float ch )//数字转换字符串 {
char i;
if(ss[0]=='%'&&ss[1]=='d')
sprintf((char*)s,"%d",(int)ch);
if(ss[0]=='%'&&ss[1]=='f')
{
sprintf((char*)s,"%d",(int)(ch*100));
for(i=0;s[i]!=0;i++);
if(i==1||i==0)
{
s[3]=s[1];
s[2]=s[0];
s[1]='0';
s[0]='.';
}
else
{
s[i+1]=s[i];
s[i] =s[i-1];
s[i-1]=s[i-2];
s[i-2]='.';
}
if(s[1]=='-')
{
s[1]='.';
s[0]='-';
}
}
}
unsigned short CRC_CHECK(unsigned char *Buf, unsigned char CRC_CNT)
{
unsigned short CRC_Temp;
II
附录
unsigned char i,j;
CRC_Temp = 0xffff;
for (i=0;i>1 ) ^ 0xa001;
else
CRC_Temp = CRC_Temp >> 1;
}
}
return(CRC_Temp);
}
void OutPut_Data(void)
{
int temp[4] = {0};
unsigned int temp1[4] = {0};
unsigned char databuf[10] = {0};
unsigned char i;
unsigned short CRC16 = 0;
for(i=0;i<4;i++)
{
temp[i] = (int)OutData[i];
temp1[i] = (unsigned int)temp[i];
}
for(i=0;i<4;i++)
{
databuf[i*2] = (unsigned char)(temp1[i]%256);
databuf[i*2+1] = (unsigned char)(temp1[i]/256);
}
CRC16 = CRC_CHECK(databuf,8);
databuf[8] = CRC16%256;
databuf[9] = CRC16/256;
for(i=0;i<10;i++)
//printf("%c",databuf[i]);
uart_putchar (UART0, databuf[i]);
}
III
第八届全国大学生智能汽车邀请赛技术报告
void Pwmchange()
{
unsigned int leftval,rightval;
if(pwmleft<-1000)pwmleft=-1000;
if(pwmright<-1000)pwmright=-1000;
if(pwmleft>1000)pwmleft=1000;
if(pwmright>1000)pwmright=1000;
rightval=(int)(pwmright*pwmradio);
leftval =(int)pwmleft;
if((pwmright>=0)&&(pwmleft>=0))
{
FTM_PWM_init(FTM0, CH0,20000,rightval);
FTM_PWM_init(FTM0, CH1,20000,0);
FTM_PWM_init(FTM0, CH2,20000,leftval);
FTM_PWM_init(FTM0, CH3,20000,0);
}
else if((pwmright>=0)&&(pwmleft<0))
{
leftval=-leftval;
FTM_PWM_init(FTM0, CH0,20000,rightval);
FTM_PWM_init(FTM0, CH1,20000,0);
FTM_PWM_init(FTM0, CH2,20000,0);
FTM_PWM_init(FTM0, CH3,20000,leftval);
}
else if((pwmright<0)&&(pwmleft>=0))
{
rightval=-rightval;
FTM_PWM_init(FTM0, CH0,20000,0);
FTM_PWM_init(FTM0, CH1,20000,rightval);
FTM_PWM_init(FTM0, CH2,20000,leftval);
FTM_PWM_init(FTM0, CH3,20000,0);
}
else if((pwmright<0)&&(pwmleft<0))
{
leftval =-leftval;
rightval=-rightval;
FTM_PWM_init(FTM0, CH0,20000,0);
FTM_PWM_init(FTM0, CH1,20000,rightval);
FTM_PWM_init(FTM0, CH2,20000,0);
FTM_PWM_init(FTM0, CH3,20000,leftval);
IV
附录
}
}
void fall_down()
{
FTM_PWM_init(FTM0, CH0,20000,0);
FTM_PWM_init(FTM0, CH1,20000,0);
FTM_PWM_init(FTM0, CH2,20000,0);
FTM_PWM_init(FTM0, CH3,20000,0); }
void corner()
{
//AnalysisPixel();
//AnalysisPixelNew();
AnalysisPixel1();
//AnalysisPixelDown();
Leaving=p_CCD_result ;
as=Leaving;
}
float kalman(const float gyro_m,const float incAngle)//只读变量不可以修改 { // 陀螺仪 角度
float K_0;//含有卡尔曼增益的另外一个函数,用于计算最优估计值
float K_1;//含有卡尔曼增益的函数,用于计算最优估计值的偏差
float Y_0;
float Y_1;
float Rate;
float Pdot[4];
float angle_err;//角度偏量
float E;
static float angle = 0; //下时刻最优估计值角度
static float q_bias = 0; //最优估计值的偏差
static float P[2][2] = {{ 1, 0 }, { 0, 1 }};
Rate = gyro_m - q_bias;
Pdot[0] = Q_angle - P[0][1] - P[1][0]; //卡尔曼增益矩阵
Pdot[1] = - P[1][1];
Pdot[2] = - P[1][1];
V
第八届全国大学生智能汽车邀请赛技术报告
Pdot[3] = Q_gyro;
angle += Rate * dt;
P[0][0] += Pdot[0] * dt; //计算协方差矩阵
P[0][1] += Pdot[1] * dt;
P[1][0] += Pdot[2] * dt;
P[1][1] += Pdot[3] * dt;
angle_err = incAngle - angle;
E = R_angle + P[0][0];
K_0 = P[0][0] / E;
K_1 = P[1][0] / E;
Y_0 = P[0][0];
Y_1 = P[0][1];
P[0][0] -= K_0 * Y_0; //跟新协方差矩阵
P[0][1] -= K_0 * Y_1;
P[1][0] -= K_1 * Y_0;
P[1][1] -= K_1 * Y_1;
angle += K_0 * angle_err; //给出最优估计值
q_bias += K_1 * angle_err;//跟新最优估计值偏差
return angle;
}
unsigned int SpeedFilter(unsigned int pulse)
{
static unsigned char SpeedLEN=6,pdata=0,pmax=0,pmin=5;//pmax给小,pmin給大
static unsigned int SpeedRecord[6]={0,0,0,0,0,888};
unsigned char i;
unsigned int average=0;
pdata=(pdata+1)%SpeedLEN;
SpeedRecord[pdata]=pulse;
if(pulse==0) pmax=pdata,pmin=pdata;
for(i=0;iSpeedRecord[pmax])
pmax=pdata; //得到最大值的指针
else if(pulse>2); //求算术平均值
}
void PulseGet()
{
cd45q=cd45h;
//////////////////
//if(CarStopPulseCountFlag)
// CarStopPulseCount+=cd45h;
/////////////////
pp+=cd45h;
cd45h=DMA_count_get(DMA_CH3);
DMA_count_reset(DMA_CH3);
//gmpq=gmph;
//gmph=LPTMR0_CNR;
//lptmr_counter_clean();
gmpq=gmph;
gmph=DMA_count_get(DMA_CH4);
DMA_count_reset(DMA_CH4);
if(cd45h>250) cd45h=250;
if(gmph >250) gmph =250;
LeftPulse +=cd45h;//SpeedFilter(cd45h);
//ic5=SpeedFilter(cd45q);
RightPulse+=gmph;//SpeedFilter(gmph);
//ic6=SpeedFilter(gmpq ); }
void SpeedCount()
{
sudu=(LeftPulse+RightPulse)/2.0/5.0;
LeftPulse =0;
RightPulse=0;
if(SpeedIFlag==0&&sudu>70) SpeedIFlag=1;
if(SpeedIFlag==1) sudu_dot+=(SpeedSet-sudu);
if(sudu_dot>50) sudu_dot= 50;
if(sudu_dot<-50) sudu_dot=-50; }
void countsudu2()
{
int aa,suduxx2c,suduxxc;
static int pulsecount = 0;//记录有效脉冲次数
VII
第八届全国大学生智能汽车邀请赛技术报告
suduxx2c=sududmaflag*30000+ cd45h;//-cd45q;//前后两次之差即使时间段内的脉冲数即速度
suduxxc =suduflag*30000+gmph;//-gmpq; //48ms脉冲数 //每2次平均一次
if(suduxx2c>200||suduxxc>200)//简单滤毛刺
//if(suduxx2c+50suduxx2[flagsudu]||suduxxc+50<
suduxx[flagsudu]||suduxxc-50>suduxx[flagsudu])
{
suduxx2[flagsudu]=0;
suduxx[flagsudu] =0;
}
else
{
pulsecount++;
suduxx2[flagsudu]= suduxx2c;
suduxx[flagsudu] = suduxxc;
}
flagsudu++;
if(flagsudu==5)
{
flagsudu=0;
sudu1=0;
sudu2=0;
if(pulsecount!=0)
{
for(aa=0;aa0) sudu=-sudu;
//if(show1)//?
{
sudu_dot += SpeedSet-sudu; //I控制
}
if(sudu_dot>300) sudu_dot=300;
VIII
附录
if(sudu_dot<-300) sudu_dot=-300;
suduq=SpeedSet-sudu;
}
if(suduflag==1)
suduflag=0;//捕获寄存器溢出中断时加一
if(sududmaflag==1)
sududmaflag=0;//捕获寄存器溢出中断时加一
}
void count() //计算出当前的mma nec的值
{
float FilterAngle;
enc=d_enc ;
enc= (enc-encsta)*3.3;
mma=d_mma;////
mma=(mma-mmasta)*3.3;
enc= enc/4.096/0.67;//温漂
mma=mma/4.096/800;//基值对否
a_enc=enc;
if(mma>1)
mma=1;
if(mma<-1)
mma=-1;
mma=180/3.1416*asinf(mma);
a_mma=mma;//////////////
angleq=angleout;
FilterAngle= kalman(enc,mma);//调用Kalman计算
angleout=1.0*FilterAngle+0*angleq;
DeltAngle=angleout-angleq;
AngleDot=(angleout-angleq)/0.006;
/////////////////////////////////
//LCD_P6x8Str(0,4,"r_angle:");
//sprintf(str,"%.3f",angleout);
// LCD_P6x8Str(64,4,str);
/////////////////////////////////
//PID();
}
void dao(){ if(angleout>(AngleG+10)||angleout<(AngleG-10)) //
IX
第八届全国大学生智能汽车邀请赛技术报告
StandP=400;
else StandP=220;
}
void mmaencSample()
{
unsigned int mma_ad,enc_ad;
mma_ad=ad_once(ADC0, SE13, ADC_12bit);//读取 ADC1_SE4a ,12位精度
enc_ad=ad_once(ADC0, SE12, ADC_12bit);//读取 ADC1_SE5a ,12位精度
d_enc=enc_ad;
d_mma=mma_ad;
}
void mmaencInit()
{
unsigned int mma_ad,enc_ad,mmasum=0,encsum=0,i;
for(i=0;i<8;i++)
{
mma_ad=ad_once(ADC0, SE13, ADC_12bit);//读取 ADC1_SE4a ,12位精度
enc_ad=ad_once(ADC0, SE12, ADC_12bit);//读取 ADC1_SE5a ,12位精度
mmasum+=mma_ad;
encsum+=enc_ad;
}
mmasta=mmasum>>3;
encsta=encsum>>3;
}
//////////////////////////////////////////
void button_init()
{
u8 str[10];
int i=0,signflag=0;
gpio_init(PORTD,0,GPI_UP,0);
gpio_init(PORTD,1,GPI_UP,0);
gpio_init(PORTD,2,GPI_UP,0);
gpio_init(PORTD,3,GPI_UP,0);
gpio_init(PORTD,4,GPI_UP,0);
gpio_init(PORTD,5,GPI_UP,0);
gpio_init(PORTE, 4,GPI_UP,0);
gpio_init(PORTD,13,GPI_UP,0);
gpio_init(PORTD,14,GPI_UP,0);
gpio_init(PORTD,15,GPI_UP,0);
X
附录
while(zkg)//zkg_flag
{
mmaencSample();
count();
LCD_Fill(0x00); //初始清屏
d2c(str,"%f",AngleG);
LCD_P6x8Str(6,0,str);
d2c(str,"%f",angleout);
LCD_P6x8Str(68,0,str);
d2c(str,"%d",mmasta);
LCD_P6x8Str(6,1,str);
d2c(str,"%d",encsta);
LCD_P6x8Str(68,1,str);
d2c(str,"%d",d_mma);
LCD_P6x8Str(6,2,str);
d2c(str,"%d",d_enc);
LCD_P6x8Str(68,2,str);
d2c(str,"%f",a_mma);
LCD_P6x8Str(6,3,str);
d2c(str,"%d",a_enc);
LCD_P6x8Str(68,3,str);
d2c(str,"%d",SpeedStart);
LCD_P6x8Str(6,4,str);
d2c(str,"%d",SpeedEnd);
LCD_P6x8Str(68,4,str);
d2c(str,"%d",StandP);
LCD_P6x8Str(6,5,str);
d2c(str,"%f",StandD);
LCD_P6x8Str(68,5,str);
d2c(str,"%f",DrectionP);
LCD_P6x8Str(6,6,str);
XI
第八届全国大学生智能汽车邀请赛技术报告
d2c(str,"%f",DrectionD);
LCD_P6x8Str(68,6,str);
LCD_DLY_ms(10);
if(!jdjia)
{
while(!jdjia);
i++;
if(i==14) i= 0;
if(i==3) i= 8;
}
if(!jdjian)
{
while(!jdjian);
i--;
if(i==-1) i=13;
if(i== 7) i=2;
}
if(i%2==0) LCD_P6x8Str(6 ,i/2," ");
else LCD_P6x8Str(68 ,i/2," ");
if(!sdjia)
{
while(!sdjia);
signflag=1;
}
if(!sdjian)
{
while(!sdjian);
signflag=-1;
}
if(i== 0) AngleG+=0.1*signflag;
if(i== 1) ;
if(i== 2)
{
if(signflag!=0)
{
LCD_DLY_ms(1000);
mmaencInit();
i=8;
}
XII
附录
}
if(i== 3) ;//{LCD_DLY_ms(1000);mmaencInit();i=8}
if(i== 4) ;
if(i== 5) ;
if(i== 6) ;
if(i== 7) ;
if(i== 8) SpeedStart+=5*signflag;
if(i== 9) SpeedEnd +=5*signflag;
if(i==10) StandP+=10*signflag;
if(i==11) StandD+=0.1*signflag;
if(i==12) DrectionP+=10*signflag;
if(i==13) DrectionD+=1*signflag;
signflag=0;
LCD_DLY_ms(20);
}
LCD_Fill(0x00); //初始清屏
//LCD_P6x8Str(0,0,"set success!!!");
}
//////////////////////////////////////////
void SendHex(unsigned char hex)
{
unsigned char temp;
temp = hex >> 4;
if(temp < 10)
{
uart_putchar(UART0,temp + '0');
} else
{
uart_putchar(UART0,temp - 10 + 'A');
}
temp = hex & 0x0F;
if(temp < 10)
{
uart_putchar(UART0,temp + '0');
}
else
{
uart_putchar(UART0,temp - 10 + 'A');
}
}
void SendImageData(unsigned char * ImageData)
XIII
第八届全国大学生智能汽车邀请赛技术报告
{
unsigned char i;
/* Send Data */
uart_putchar(UART0,'*');
uart_putchar(UART0,'L');
uart_putchar(UART0,'D');
SendHex(0);
SendHex(0);
SendHex(0);
SendHex(0);
for(i=0; i<128; i++)
{
SendHex(*ImageData++);
}
uart_putchar(UART0,0);
uart_putchar(UART0,'#'); }
//////////////////////////////////////////
void main(void) //两个温漂注意 //计数记不准
{
u8 str[10];
DisableInterrupts;
///////////////////////
LCD_Init();
adc_init(ADC0, SE8);//初始化对应为PTB0,CCD1
adc_init(ADC0, SE9);//初始化对应为PTB1,CCD0
adc_init(ADC0, SE12);//初始化对应为PTB2,ENC
adc_init(ADC0, SE13);//初始化对应为PTB3,MMA
///////////////////////
pit_init_ms(PIT0, 3);//初始化PIT0,定时时间为3ms
//pit_init_ms(PIT1, 3);//初始化PIT1,定时时间为1ms
FTM_PWM_init(FTM0, CH0,20000,0); //右前 //FTM模块产生PWM,即
PTC1 ,频率为 20k
FTM_PWM_init(FTM0, CH1,20000,0); //右后 //FTM模块产生PWM,即
XIV
附录 PTC2 ,频率为 20k
FTM_PWM_init(FTM0, CH2,20000,0); //左前 //FTM模块产生PWM,即 PTC3 ,频率为 20k
FTM_PWM_init(FTM0, CH3,20000,0); // 左后 //FTM模块产生PWM,即 PTC4 ,频率为 20k
//lptmr_counter_init(LPT0_ALT2, 29999, 2, LPT_Rising); //初始化脉冲计数器即PTC5 输入,每隔INT_COUNT产生中断,延时2个时钟滤波,上升沿触发
DMA_count_Init(DMA_CH4, PTA13 ,600 , DMA_rising);
DMA_count_Init(DMA_CH3, PTE2 ,600 , DMA_rising);
///////////////////
gpio_init(PORTE,0,GPO,1);
gpio_init(PORTA,4,GPO,1);
/////////////////////
CCD_Init();
button_init();
gpio_init(PORTD,4,GPI_UP,0);
uart_init(UART0,9600);
SpeedSet=0;
EnableInterrupts;
while(1)
{
///////////////
mmaencSample();
//PID();
///////////////
//PTE0_OUT=1;
//PTE0_OUT=0;
if(!pause&&!xxx)
{
xxx=1;
SecondTimeCountFlag=1;
StartLineFlag=0;
}
XV
第八届全国大学生智能汽车邀请赛技术报告
if(!xxx)
//else
{
d2c(str,"%d",Pixel[0]);
LCD_P6x8Str(0,2,str);
d2c(str,"%d",Pixel[64]);
LCD_P6x8Str(40,2,str);
d2c(str,"%d",Pixel[127]);
LCD_P6x8Str(80,2,str);
d2c(str,"%d",ic1);
LCD_P6x8Str(6,0,str);
d2c(str,"%d",ic2);
LCD_P6x8Str(30,0,str);
d2c(str,"%d",StartLineFlag);
LCD_P6x8Str(60,0,str);
//sprintf(str,"%d",LostType);
//LCD_P6x8Str(30,0,str);
d2c(str,"%d",_COMP_VALUE_);
LCD_P6x8Str(90,0,str);
d2c(str,"%f",AngleG);
LCD_P6x8Str(6,4,str);
d2c(str,"%f",angleout);
LCD_P6x8Str(68,4,str);
d2c(str,"%d",ic5);
LCD_P6x8Str(6,6,str);
d2c(str,"%d",ic6);
LCD_P6x8Str(68,6,str);
if(!jdjia)
{
while(!jdjia);
AngleG+=0.2;//DrectionD+=5;
}
if(!jdjian)
{
while(!jdjian);
AngleG-=0.2;//DrectionD-=5;
XVI
附录
}
if(!sdjia)
{
while(!sdjia);
_COMP_VALUE_+=50;
}
if(!sdjian)
{
while(!sdjian);
_COMP_VALUE_-=30;
}
}
/////////////////////////////////
/*
sprintf(str,"%d",Pixel[0]);
LCD_P6x8Str(0,2,str);
sprintf(str,"%d",Pixel[64]);
LCD_P6x8Str(40,2,str);
sprintf(str,"%d",ic1);
LCD_P6x8Str(80,2,str);
SendImageData(Pixel);
*/
////////////////////////////////
}
}
void AnalysisPixel1()
{
unsigned char i;
unsigned char count_one_left=0,count_one_right=0;
unsigned char count_zero_left=0,count_zero_right=0;
unsigned char flag_left=1,flag_right=1;
int delta_CCD_result;//,acc_CCD_result;
for(i=0;i<64;i++)
{
if(Pixel[64-i]>_COMP_VALUE_&& flag_left) count_one_left++;
else
count_zero_left++;
if(Pixel[64+i]>_COMP_VALUE_&&flag_right) count_one_right++;
else
count_zero_right++;
XVII
第八届全国大学生智能汽车邀请赛技术报告
if(count_zero_left>3)
{
flag_left=0;
}
if(count_zero_right>3)
{
flag_right=0;
}
if( flag_left==0&&flag_right==0) break;
}
if (count_one_left==64&&count_one_right==64)
{
CCD_result[_LEFT_] = 0;
CCD_result[_RIGHT_] =0;
}
else if(count_one_left==0&&count_one_right==0)
{
//CCD_result[_LEFT_] = 0;
//CCD_result[_RIGHT_] =0;
}
else if(count_one_left<64&&count_one_right<64)
{
CCD_result[_LEFT_] = count_one_left;
CCD_result[_RIGHT_] = count_one_right;
}
else if(count_one_left<64&&count_one_right==64)
{
CCD_result[_LEFT_] = count_one_left;
CCD_result[_RIGHT_] = 70;//count_one_right;
}
else if(count_one_left==64&&count_one_right<64)
{
CCD_result[_LEFT_] = 70;//count_one_left;
CCD_result[_RIGHT_] = count_one_right;
}
delta_CCD_result = CCD_result[_RIGHT_]-CCD_result[_LEFT_];
XVIII
附录
//acc_CCD_result = CCD_result[_LEFT_] + CCD_result[_RIGHT_];
//if(acc_CCD_result==0) acc_CCD_result=1;
if(delta_CCD_result>0) RIGHT_LED=0,LEFT_LED=1;
if(delta_CCD_result<0) RIGHT_LED=1,LEFT_LED=0;
if(delta_CCD_result>=-5&&delta_CCD_result<=5)
{
p_CCD_result = (1.0*delta_CCD_result) / 70;//acc_CCD_result ;
}
else
{
p_CCD_result = (1.0*delta_CCD_result) / 70;//acc_CCD_result ;
}
////////////////////
//ic1=delta_CCD_result;
//ic2=acc_CCD_result ;
//////////////////
//AjustDrectionPD(delta_CCD_result);
/////////////////////
}
int GetADSample()
{
unsigned char i;
unsigned int ATD0DR0_RETURN;
//ATD0CTL5=0x32;
_CLK_=1;//起始电平高
_SI_=0; //起始电平低
CCD_DelayNS(); //合理的延时
_SI_=1; //上升沿
_CLK_=0;//下降沿
CCD_DelayNS(); //合理延时
_CLK_=1;//上升沿
_SI_=0; //下降沿
CCD_DelayNS(); //合理延时
CCD_DelayMS(); //合理延时
for(i=0;i<128;i++)
{
XIX
第八届全国大学生智能汽车邀请赛技术报告
_CLK_=0;//下降沿
CCD_DelayNS(); //合理延时
CCD_DelayNS();
CCD_DelayNS();
ATD0DR0_RETURN=Pixel[i]=(ad_once(ADC0, SE9,
ADC_12bit));//>>4;//读取 ADC1_SE6a ,12位精度
_CLK_=1;//上升沿
CCD_DelayNS(); //合理延时
CCD_DelayNS();
CCD_DelayNS();
//PTE0_OUT=1;
//mma_ad=ad_once(ADC0, SE13, ADC_12bit);//读取 ADC1_SE4a ,12位精度
//PTE0_OUT=0;
//enc_ad=ad_once(ADC0, SE12, ADC_12bit);//读取 ADC1_SE5a ,12位精度
//d_enc=enc_ad;
//d_mma=mma_ad;
//corner();
/*
encxx+=enc_ad;
mmaxx+=mma_ad; //
if((i+1)%8==0)
{
d_enc=encxx>>3;
d_mma=mmaxx>>3;
encxx=0;
mmaxx=0;
}
*/
}
return ATD0DR0_RETURN; }
XX