第八届飞思卡尔光电平衡组华东交通大学-追风队技术报告 本文关键词:卡尔,追风,交通大学,第八届,光电
第八届飞思卡尔光电平衡组华东交通大学-追风队技术报告 本文简介:第八届“飞思卡尔”杯全国大学生智能汽车竞赛技术报告学校:华东交通大学队伍名称:追风队参赛队员:黄健刘勇勇张望带队教师:甘岚涂春萍1关于技术报告和研究论文使用授权的说明本人完全了解第八届“飞思卡尔”杯全国大学生智能汽车邀请赛关保留、使用技术报告和研究论文的规定,即:参赛作品著作权归参赛者本人,比赛组委
第八届飞思卡尔光电平衡组华东交通大学-追风队技术报告 本文内容:
第八届“飞思卡尔”杯全国大学生
智能汽车竞赛技术报告
学
校:华东交通大学
队伍名称:追风队
参赛队员:黄健
刘勇勇
张望
带队教师:甘岚
涂春萍
1
关于技术报告和研究论文使用授权的说明
本人完全了解第八届“飞思卡尔”杯全国大学生智能汽车邀请赛关保留、使用技术报告和研究论文的规定,即:参赛作品著作权归参赛者本人,比赛组委会和飞思卡尔半导体公司可以在相关主页上收录并公开参赛作品的设计方案、技术报告以及参赛模型车的视频、图像资料,并将相关内容编纂收录在组委会出版论文集中。
参赛队员签名:
带队教师签名:
日
期:
____________
I
1
摘要
本文记录了华东交通大学追风队队员在准备第八届“飞思卡尔”杯全国智能汽车竞赛中的工作成果和体会,并总结了方案中成功的经验和不足之处,愿与各高校代表队分享。
本智能车系统以飞思卡尔高性能16位单片机MC9S12XS128为核心,通过用线性CCD检测赛道两边的黑线来引导小车行驶,用编码器来检测小车的速度。使用陀螺仪和加速度计检测小车的直立信息,通过AD采样获得当前CCD在赛道上的位置信息,运用红外对管检测起跑线完成自动启停,使用PID算法控制小车方向和分段PID算法对小车进行速度控制,实现稳定快速的运行。
关键词:飞思卡尔智能车
MC9S12XS128
线性CCD
PID控制
3
目录
摘要III
目录IV
第一章
引言1
1.1
比赛背景介绍1
1.2技术报告内容安排说明1
第二章
系统整体方案设计2
2.1系统硬件设计方案概述2
2.2系统软件设计方案概述2
第三章
机械调整3
3.1车体调整3
3.2
CCD的安装与调整4
3.3
陀螺仪与角速度计的安装5
3.4
编码器的安装6
第四章
硬件电路设计7
4.1
电源模块设计7
4.2
最小系统……………………………………………………………………8
4.3
驱动电路设计9
4.4
红外对管设计11
第五章
软件设计12
第六章
智能车主要参数…………………………………………………………………….12
第七章
结论13
参考文献
附录
程序源代码
III
第一章
引言
1.1
比赛背景介绍
全国大学生“飞思卡尔”杯智能汽车竞赛是由教育部高等自动化专业教学指导分委员会(以下简称自动化分教指委)主办的一项具有导向性、示范性和群众性的全国竞赛活动。竞赛以智能汽车为研究对象的创意性科技竞赛,是面向全国大学生的一种具有探索性工程实践活动,是教育部倡导的大学生科技竞赛之一。全国大学生智能汽车竞赛由竞赛秘书处为各参赛队提供/购置规定范围内的标准硬软件技术平台,竞赛过程包括理论设计、实际制作、整车调试、现场比赛等环节,要求学生组成团队,协同工作,初步体会一个工程性的研究开发项目从设计到实现的全过程。该竞赛融科学性、趣味性和观赏性为一体,是以迅猛发展、前景广阔的汽车电子为背景,涵盖自动控制、模式识别、传感技术、电子、电气、计算机、机械与汽车等多学科专业的创意性比赛。全国大学生智能汽车竞赛以“立足培养,重在参与,鼓励探索,追求卓越”为指导思想,旨在加强大学生实践、创新能力和团队精神的培养,促进高等教育教学改革,促进高等学校素质教育,培养大学生的综合知识运用能力、基本工程实践能力和创新意识,激发大学生从事科学研究与探索的兴趣和潜能,倡导理论联系实际、求真务实的学风和团队协作的人文精神,为优秀人才的脱颖而出创造条件。
1.2技术报告内容安排说明
本文采用先总后分的结构,先对系统总体设计进行介绍,然后分别对各部分
进行介绍,突出强调了系统机械设计、硬件电路和软件编程。
第一章
引言:简单介绍了智能车比赛的一些情况;
第二章
系统设计:总体介绍了整个智能车各部分系统设计;
第三章
机械结构设计:详细介绍了本智能车机械结构设计;
第四章
智能车硬件系统:分模块详细介绍了小车硬件电路设计与制作;
第五章
软件系统设计:介绍了智能小车软件设计及算法实现;
第六章
智能车技术参数:智能车主要技术参数说明;
第七章
总结:主要说明一下我们在设计过程中遇到的问题和解决办法,以
及还存在的问题;
第二章
系统整体方案设计
2.1系统硬件设计方案概述
首先将弄清直立车运行方式,需要接收哪些数据能够使小车实现直立,直立有需要哪些条件,逐个把小车分解成一个个小模块。开始是电源模块,我们要理清需要哪些电压电源,给哪部分供电,对电源稳定性与失真的要求,还有功率的要求。对一些不确定的模块,可选择可调电源。其次是单片机的确定,我们要保证它有足够的运行速度来处理所采集的数据,还能准确的输出控制信号。接着就是驱动电路的设计,驱动芯片的选择,我们要确保能够输出足够的功率去控制电机,因为驱动功率大,电流大,我们还要采取一些保护措施。最后是陀螺仪和加速度的设计,我们要确保输出数据准确快速。根据智能车设计要求,设计合理的电路实现小车的功能,注意负载的电流,并着重考虑电路的稳定性。上面一切电路设计好后就能够为将来小车平稳运行打好坚实的基础。
2.2系统软件设计方案概述
软件是给智能车实现控制的执行语言,软件控制着智能车的一切行动,通过对软件的编写可以让智能车按照你的思路去实现个个路段的完美赛跑。软件控制其实就是把自己的思想灌输到单片里面,并让其高速有序的执行,实现对智能车的精确控制。软件又细分为主程序、小车直立控制子程序、小车速度控制子程序、小车转向控制子程序、循环子程序等等。
主程序:程序的主体采用顺序结构。为了方便控制,Main函数里面除了初始化程序
就是液晶显示程序,而所有的核心操作放在定时中断中。同时为了细分每一时
刻的任务,我们对中断进行了计数,使得每一个时刻单片机需要处理什么数据
可以简单明了。
小车直立控制子程序:我们通过陀螺仪和加速度计采集小车的倾斜角度和小车转动的角速度来反映小车的直立情况,然后通过处理实现对电机的控制来消除小车的倾斜角,从而达到小车直立控制。利用倾角传感器来检测车模此时刻的状态,然后调节电机的转速,让车模整体可以跟得上车模的倾角变化,在车模发生更大幅度的倾斜之前将车模的状态维持到平衡。如果在PID调节中不是很顺利,可以适当的添加一些I项的系数,这样会使得调节顺利不少。当车模顺利的维持直立姿态之后,也就意味着我们的后续的速度控制以及转向控制就可以开始开展了!
小车速度控制子程序:我们给小车设定一个速度,通过编码器采集回来的数据计算出小车实际的速度,然后形成一个闭环控制,这样就可以保证小车实现恒速与时刻可以准确改变小车的运行速度,即使是在干扰的情况下也能够迅速返回设置的速度并稳定下来。
第三章
机械调整
3.1
车模调整
一辆车的好坏不仅仅由软件跟硬件决定,机械对智能车的影响也是十分重要的。一辆智能车的机械做的好,它就能更加稳定,速度也能挺高的更多。
(1)车模底盘的加固与电池卡槽的安装
在不断的测试中我们总结出,重心的位置对平衡车的稳定性能影响十分的大,重心相对较低比较好,但也不能太低,太低了对电机的要求就更高了。经过不断的测试与调试,我们决定下来电池的安装位置,电池的安装也可以改变车模的倾斜角度。同时电池的卡槽角要磨段一点,只要不要与车轮想接触就可以了。
(2)车轮的调整
刚买回来的车轮会有些晃动,这对车的影响是有的,我们的减小一切给小车带来的影响。经过一次次的实验,我们最后选定了一块小铁片安装在车轮的一侧。铁皮的厚度要求要很精确,太厚了会造成两轮太卡,要是太薄了就会跟没有安装一样,这要不断实验才能确定铁片的厚度。
图3-1
车模固定与电池安装
3.2
CCD的安装与调整
CCD可以说是光电平衡车的眼睛,可见CCD的安装是多么的重要,CCD的安装位置要能够确保CCD的视野宽广,能够扫描到整个跑到,但也不能够太过于宽广,这样它会扫描到另外的跑到上,这样就给数据处理带来麻烦。同时还要确保CCD的前瞻足够的符合你的要求,一辆车CCD前瞻调的好坏往往影响你小车的整体速度。CCD前瞻调的好腻弯道的处理也会更好。大家都总结出,前瞻决定速度,当能这是相对而言的。装CCD的支架一定要保证安装在车模的正中间,这装的准确可以给你调整CCD减少很多麻烦。其次两边的支架可有可无,这得看你试验的结果,我们是确保小车在运行中CCD支架不晃动。
图3-2
CCD的安装
3.3陀螺仪与加速度计的安装
陀螺仪跟角速度计都是用来检测车模的倾斜角度,我们将这块带有陀螺仪和加速度计的电路板固定在整个车模中间质心的位置。这样可以最大程度减少车模运行时前后振动对于测量倾角的干扰,同时陀螺仪一定要安装水平,因为陀螺仪安装的不水平,就会使得小车转弯出现突然加速减速的情况,只要陀螺仪安装的水平就不会出现这样的情况。这要在不断测试中调整陀螺仪位置。
图3-3
陀螺仪与加速度计的安装
3.4
编码器的安装
编码器的齿轮我们选择与电机齿轮想接触,这样可以更加准确的测出电机的转速从而转换为小车的速度。
图3-4
编码器的安装
第四章
硬件电路设计
4.1
电源模块设计
根据不同的要求我们选择了几种不同电源电路的设计:
1.LM2940-s(5v)低压降线性(LDO)-固定式稳压器,最大输出电流>1A;压降0.5V,电压调整率20mv;电流调整率35mv;静态电流10mA;PSRR72dB;噪音电压150uA。(单片机,陀螺仪模块供电)
2.TPS7350QD超低压降线性(VLDO)一固定式稳压器最大输出电流500mA;压降35mA;有延时复位功能(200ms低电平)输出电压误差2%;静态电流340uA(与负载无关);待机电流0.5uA;噪音电压300uA,PSRR:50dB(120KHz),(20-80KHz左右时最小,只有5dB)(CDD,红外对管供电)。
3.LM2596S-ADJ降压式开关-固定式稳压器,最大输出电流3A;有断电保护功能,输出电压误差4%;饱和电压1.16V;静态电流5mA;待机电流80Ua(编码器供电).
图4-1
电源电路图
图4-2
电源板实物图
4.2
最小系统
单片机最小系统为本智能车系统的核心。为了稳定和可重复使用,我们购买了单片机最小系统板。这个最小系统板引出了几乎所有功能引脚,板上自带晶振电路、复位电路、单片机电源电路。单片机我们选择的是MS12SX128,其主要特性:S12X
CPU,
最高总线速度
40MHz;64KB、128KB
和
256KB
闪存选项,均带有错误校正功能(ECC);带有
ECC
的、4KB
至
8KB
DataFlash,用于实现数据或程序存储;可配置
8-
、10-
或
12-
位模数转换器(ADC),转换时间
3μs;支持控制区域网(CAN)、本地互联网(LIN)和串行外设接口(SPI)协议模块;带有
16-位计数器的、8-通道定时器;出色的
EMC,及运行和停止省电模式。
图4-3
最小系统板电路
4.3
驱动电路设计
我们智能车中采用4片BTS7970搭载成两个H桥来驱动机器人的两个电机,具有输出功率大,稳定性好,保护措施好等优点。
图4-4
驱动电路图
图4-5
驱动电路板实物图
4.4
红外对管设计
红外对我们用于专门检测起跑线,这样检测的结果很准确,但是用CCD检测会用一定概率性,就是不能够确保每次都能检测到,但是用3个红外对管就可以实现,红外对管的电路也十分的简单。
图4-6
红外对管实物电路板
第五章
软件设计
小车的控制归根决地是对两个驱动电机的精确控制,通过电机的正转反转控制小车的平衡。通过同样转速控制小车的运行速度,通过对两个电机的差速控制来控制小车的转向。能而这些都是需要算法处理采集的数据来控制电机。平衡我们采用了卡尔曼滤波来实现,速度和转向控制采用了PID来处理。详情请参考附录程序源代码的注释,上面注释的很清楚。
第六章
智能车主要参数
车模长、宽、高(毫米)
165*85*430
电路功耗(w)
10.5w
所以电容总量(uF)
1650.54
传感器个数(个)
8
陀螺仪(个)
2
加速度计(个)
1
红外对管(个)
3
编码器(个)
2
外加电机,舵机(个)
0
赛道信息检测精度(毫米)
5
赛道信息检测频率(次/秒)
200
第七章
结论
记得刚接触智能车这个名词的时候感觉很神奇,我们3人热血沸腾的组队参加了第八届的飞思卡尔智能车大赛。当时我们抱着的只是一腔热血,什么都不懂,只是稍微看了点质料。当接触了才知道是那么的难,刚开始走了很多很多的弯路,经常一两个月的坚持摸索之后,我们开始慢慢的上路。越到后面越是难熬,感觉一切的冲劲到覆灭在了前几个月,开始有人放弃了,我们开始争吵了,一段静心之后我们开始重新振作,把放弃的重新请了回来,我们又开始没日没夜的摸索。时间渐行渐远我们开始摸索到了一些门道,事事开始尽心尽愿,我们开始在智能车的大道上奔跑。
经过一学期的摸索,做智能车首先得先去收集有关质料报告,把他们摸懂搞透,这样做事就有头有系了,可以走很多的弯路,同时也可以多吸取他们的优点,看到别人犯过的错误。选择正确的器件也是非常重要的,也不要太在意钱,该花的还是要花,条件好的情况下可以多买点不同的,融合一下各个的优点。再次就是团队很重要,不要把自己看的太重,不要什么事都自己去插下手,相信队友,给他们点空间。
在这我们要谢谢我们的指导老师在背后一直给我们支持,给我们提供一个做车的环境。在此感谢组委会给我们这样一个展现的平台,也感谢各个举办学校各个志愿者为我们付出的辛劳。
参考文献
【1】使久贵
编著
《基于
Altium
Designer
的原理图与
PCB
设计》
机械工业
出版社,2010.
【2】
乐山师范学院__明星电缆
2
队技术报告.
【3】
野火
三天入门
Cortex-M4——Kinetis
系列.pdf
【4】
薛涛、邵贝贝等
《单片机与嵌入式系统开发方法》
清华大学出版社,
2009.10.
【5】张肃文
主编
《高频电子线路》
高等教育出版社
2010.5.
【6】谭浩强?C
程序设计?北京:清华大学出版社,2001
【7】电磁组直立车模参数整定与调试指南手册
【8】陶永华,新型
PID控制及其应用,机械工业出版社,2005
【9】胡寿松,自动控制原理,科学出版社,2007
附录
程序源代码
#include
“include.h“#define
TSL_SI
PORTA_PA7
#define
TSL_CLK
PORTA_PA6
#define
coder1
PORTE_PE7
#define
coder2
PORTE_PE6
#define
coder3
PORTE_PE5
#define
coder4
PORTE_PE4
#define
speedcoder1
PORTE_PE2
#define
speedcoder2
PTM_PTM5
#define
speedcoderp1
PTM_PTM4
#define
speedcoderp2
PTM_PTM3
#define
open1
PTS_PTS2
#define
open2
PTS_PTS3
#define
open3
PTJ_PTJ6
#define
open4
PTJ_PTJ7
/*******************************9600串口数据***************************************/
int
OutData[4]={0};
/*******************************中断计数数据***************************************/
byte
EventCount=0;
/*****************************加速度和陀螺仪采集需要的数据*************************/
float
adValue[2]=0;
//读取陀螺仪和加速度计的值
/*****************************角度和陀螺仪的值*************************************/
float
acceler=0;
//加速度计的角度值
float
gyro=0;
//陀螺仪的值
float
ACCELERSET=1459,GYROSET=0,DIRECTIONGYROSET=0;
//加速度计和陀螺仪的0偏值
float
Angle_P=8.3888889999,Angle_D=0.2199999999;
float
ZHILI=0;
/*******************************卡尔曼滤波用到的数据*******************************/
float
angle=0,angle_dot=0;
float
C_0=1;
float
Q_angle=0.001;
float
Q_gyro=0.003;
float
R_angle=0.5;
float
dt=0.005;
//卡尔曼采样时间
float
P[2][2]={{1,0},{0,1}};
float
Pdot[4]={0,0,0,0};
float
q_bias=0,angle_err=0,PCt_0=0,PCt_1=0,E=0,K_0=0,K_1=0,t_0=0,t_1=0;
/*******************************小车转速的数据*************************************/
float
LeftSpeedPulse=0;
//20次左轮的转速之和
float
RightSpeedPulse=0;
//20次右轮的转速之和
/*******************************电机输出用到的数据*********************************/
byte
Judje[2]={1,1};
/*******************************速度控制用到的数据*********************************/
unsigned
char
SpeedControlPeriod=0;
//速度控制的周期
unsigned
char
SpeedControlCount=0;
float
SpeedControlOutNew=0,SpeedControlOutOld=0,SpeedControlOut=0;
float
CarSpeedSet=0,CarSpeed=0;
float
CarSpeedSet1=0;
float
SpeedP=5.011,SpeedI=0.15;
float
SpeedPSet=0;
float
SpeedControlIntegral=0;
/******************************10ms采集CCD用到的数据*******************************/
unsigned
char
TimerCnt10ms=0;
//计时10ms中断中计数
unsigned
char
TimerFlag10ms=0;
//10ms进行一次方向控制
/******************************采集CCD用到的数据***********************************/
unsigned
char
Pixel[128]=0;
//现在的128个点
float
pixelleftplace=0;
//本次左边黑线位置
float
pixelrightplace=127;
//本次右边黑线位置
float
pixelview=94;
float
pixelmax=110;
float
pixelmin=94;
float
pixelmiddle=0;
float
pixelleftview;
float
pixelrightview;
float
piancha=0;
float
prepiancha=0;
float
directionout=0;
float
directionp=188.9989789,directiond=0.045787999999;
/********************************转向陀螺仪的的数据******************************/
float
directionanglevalue=0,directionanglepluse=0,directionspeed=0;
/********************************设置起跑时平衡数据************************************/
float
second=0;
//记录时间
byte
flag=0;
//标志零点采集
byte
secondflag=0;
byte
pa_flag=0;
byte
bar=0;
float
secondbar=0;
byte
end=0;
float
speedpcount=0;
int
pianchacount=0;
/********************************9600串口发送函数********************************/
unsigned
short
CRC_CHECK(unsigned
charBuf,unsigned
char
CRC_CNT)
{
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);
}
void
uart_putchar(unsigned
char
c)
{
while(!(SCI0SR1
//keep
waiting
when
not
empty
SCI0DRL=c;
}
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=154
||acceler=0){
LeftMotorOut
+=5;
}
else{
LeftMotorOut
-=5;
}
if(RightMotorOut>=0){
RightMotorOut+=5;
}
else{
RightMotorOut-=5;
}
if(LeftMotorOut>=250){
LeftMotorOut
=
250;
}
else
if(LeftMotorOut=250){
RightMotorOut
=
250;
}
else
if(RightMotorOut10){
SpeedControlIntegral=10;
}
if(SpeedControlIntegral>4);
//AD采集
directionanglepluse+=directionanglevalue;
TSL_CLK=1;//上升沿
SamplingDelay();
//合理延时
}
}
/*************************小车运行时加速度计的值和转向陀螺仪的值得函数************/
void
directionSpeed(void){
directionspeed=directionanglepluse/128-DIRECTIONGYROSET;
directionanglepluse=0;
}
/************************找黑线的函数********************************************/
void
findpixel(unsigned
char
findplace){
unsigned
char
i;
byte
leftflag=0;
byte
rightflag=0;
for(i=findplace;i>1;i--){
//向左寻找黑线
if(Pixel[i]==0){
if(Pixel[i-1]==0){
//找到黑线
//
if(Pixel[i-2]==0){
leftflag=1;
pixelleftplace=i-1;
Pixel[i-1]=250;
break;
//
}
}
}
}
for(i=findplace;i=pixelmax){
//进行限制pixelview的范围
需要进行测定
pixelview=pixelmax;
}
else
if(pixelview=63){
pixelleftview=pixelleftplace-63+pixelmiddle;
piancha=pixelleftview/pixelview;
}
else{
pixelleftview=63-pixelleftplace;
piancha=(pixelmiddle-pixelleftview)/pixelview;
}
}
else
if(leftflag==0
pixelleftplace=0;
if(pixelrightplace=10||Pixel[i]-Pixel[i+1]-10)){
Pixel[i+1]=(Pixel[i]+Pixel[i+2])/2;
}
if((Pixel[i]-Pixel[i+1]>=10||Pixel[i]-Pixel[i+1]=10||Pixel[i]-Pixel[i+2]-10)){
Pixel[i+1]=Pixel[i+2]=(Pixel[i]+Pixel[i+3])/2;
i=i+1;
}
}
for(i=3;i50){
//寻找障碍
需要进行测试