自动往返电动小汽车附源代码.docx
《自动往返电动小汽车附源代码.docx》由会员分享,可在线阅读,更多相关《自动往返电动小汽车附源代码.docx(36页珍藏版)》请在冰豆网上搜索。
自动往返电动小汽车附源代码
《自动往返电动小汽车》论文
学校:
华侨大学
学院:
信息科学与工程学院
组别:
自控06组
组员:
********
摘要.............................................................................................3
第一章总体设计方案……………………………………...…4
1.1系统方案选择………………………………………………….4
1.车体的选择……………………………………………………….4
2.方向控制的选择…………………………………………………...4
3.路程测量方案的选择……………………………………..……….5
1.2、总体方案框图……………………………………………….5
第二章硬件设计……………………………………………...5
2.1黑线识别探测器……………………………………………...5
2.2、直流电机驱动电路.................................................................6
2.3测速模块………………………………………………………6
第三章软件设计……………………………………………...7
3.1小车车体调整的程序设计……………………………………7
3.2寻黑线的程序设计…………………………………………….7
3.3系统整体流程图……………………………………………...8
第四章系统测试……………………………………………...9
4.1.测试方法:
……………………………………………………9
第五章总结与体会…………………………………………...9
摘要
单片机技术已经十分普及,在实时检测和自动控制的单片机应用系统中,单片机往往是作为核心部件来使用。
我们本次设计的自动往返电动小汽车,是以STC89C52单片机为控制核心,辅以传感器、控制电路、显示电路等外围器件,构成了一个车载控制系统。
电动小汽车能够根据题目要求在规定的轨道上完成调速、停车、调头返回等运动形式;这辆小车还可以自动记录、显示一次往返时间、行驶距离及检测到的黑线条数,当检测到黑线时蜂鸣器发出报警,并用PWM脉宽调制技术实现降速的功能。
关键字:
自动往返STC89C52单片机PWM脉宽调制
Abstract
SCMtechnologyhasbecomeverypopular,inreal-timedetectionandautomaticcontroloftheSCMapplicationsystem,themicrocontrollerisoftenasacorecomponenttouse.
Wepresentthedesignoftheautomaticmotor-drivencar,isSTC89C52SCMasthecontrolcore,supplementedbythesensor,thecontrolcircuit,displaycircuitandotherperipheraldevices,consistingofavehiclecontrolsystem.Electriccarswillaccordingtotherequirementofthequestionintermsoftheorbitspeed,stop,turnroundandgobacktocompletetheformofmotion;thecarcanautomaticallyrecord,displayaroundtriptime,distanceandthedetectedlinenumber,whenthedetectedlinebuzzeralarm,andusePWMtechnologytorealizespeedreductionfunction.
第一章总体设计方案
1.1系统方案选择:
1.车体的选择
方案一:
用玩具车改造。
成本较低,且省去很多制作上的麻烦,但是由于其是已经设计好的产品,扩展性差,许多方面很难达到我们需要的要求。
方案二:
自己做车体。
这样可以制作出完全符合我们要求的小车车体,各部分可以进行专门的设计,但是制作方面费时费力,在整个题目中将占据较多的时间和精力,成本较高。
综上考虑,采用方案二,由于这只是练习,我们有多余的时间来自己设计一个比较有个性的车板,同时能根据自己的需要来不断的进行改造。
2.方向控制的选择:
为设计要求小车要在特定的跑道内做往返运动,并且根据不同的黑线条数来进行不同前进速度,但同时跑道两侧也是黑线,这就要求小车能够“识别”出是跑道边沿线还是中间的黑线。
方案一:
在小车两侧加上红外避障模块,让小车卡在特定的跑道前进,但由于黑线是在地上,红外传感必须固定在车上,这使得不仅不好固定红外传感模块,同时也不能良好测到跑道边沿线。
方案二:
在小车车头装四个黑线识别小模块,位置如下图。
小车前进时,如果是正对中间黑线,即2、3探测器先碰见黑线,随即便关闭1、4探测器,让小车通过黑线后在开启,在这之中还可以判断2、3探测器是否同时通过黑线,并做出调整。
当小车是倾斜时,便是1、4探测器先碰见黑线,随即控制小车转向,使小车不跑出跑道。
但当小车倾斜到垂直跑道时,小车就会跑出跑道。
考虑到小车跑道宽只有0.5m,因此垂直于跑道的情况会很小,所以我们选择了第二种方案。
3.路程测量方案的选择
方案一:
采用U型光电开关。
当光电开关导通时产生高电平,反之则产生低电平,通过对脉冲的计数获得速度信息,实现对速度的检测。
U型光电开关的最大优点是测量精度高,简单方便,而且成本也很低。
方案二:
采用红外探测模块,固定在直流电机上,并在车轮上装上黑白色的码盘,通过对脉冲的计数来计算路程。
1.2、总体方案框图:
第二章硬件设计:
2.1黑线识别探测器
黑白线检测模块采用了ST188红外反射型对管作为传感器,发射接收集成在一起,使用方便。
由于采用红外光,因此受可见光影响较小,在其输出端接比较器,能得到更稳定的波形。
应用电路图如下
2.2、直流电机驱动电路
直接选用L298N驱动直流电机,由单片机给它PWM波控制其驱动电机。
原理图如下:
2.3测速模块
测速模块采用的原理图和黑线检测的原理图一样,本次设计采用的码盘如下图。
车轮每转一转产生4个脉冲,记为n,车轮每转一周的周长为35cm。
那么S=35n/4cm。
第三章软件设计
3.1小车车体调整的程序设计
头安装的4个黑线识别传感器传来的数据来进行小车的转向控制,以保证小车能过顺利跑完全程且不超出跑道.(0表示没检测到黑线,1表示检测到黑线)
1
2
3
4
行为
0
0
0
0
前进
0
0
0
1
左转
1
0
0
0
右转
0
1
1
0
前进
0
1
0
0
左转(调整方向),前进
0
0
1
0
右转(调整方向),前进
1
1
0
0
左转
0
0
1
1
右转
x
x
x
x
后退
3.2寻黑线的程序设计
采用的是扫描I/O口的方法来寻找黑线,当黑线检测模块在没检测到黑线时输出的高电平,检测到黑线时会产生一个低电平,形成一个下降沿,同时设定中断的触发方式为下降沿触发。
3.3系统整体流程图
第四章系统测试
4.1.测试方法:
时间的测量直接用秒表测量,距离固定值,用米尺来测量,与单片机测量出的距离进行比较,小车的中心与起点线和终点线的偏差。
测量次数
系统时间
(s)
实际时间
(s)
系统距离
(m)
实际距离(m)
时间差(s)
距离差(cm)
与终点偏差(cm)
与起点偏差(cm)
1
33
33
8.00
7.2
0
80
1
0
2
36
36
7.95
7.2
1
75
2
1
3
32
32
7.5
7.2
1
30
3
1
4
32
32
7.7
7.2
0
50
1
1
第五章总结与体会
通过参与这次电子设计大赛,我们遇到了很多实际问题,这加深了对课堂知识的印象,也体会到了实际工作中的很多困难,从中领会了科学研究中所需的严谨求实态度,增强了与队友间的团结协作精神,并学会了一些基本的实践技能,使我们获益非浅。
#include
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
//停车
#definestop();{IN31=0;IN32=0;IN33=0;IN34=0;}
//后退
#defineback();{IN31=0;IN32=1;IN33=0;IN34=1;}
//前进
#definego();{IN31=1;IN32=0;IN33=1;IN34=0;}
//前进时左转
#defineleft_g();{IN31=0;IN32=0;IN33=1;IN34=0;}
//前进时右转
#defineright_g();{IN31=1;IN32=0;IN33=0;IN34=0;}
//后退时左转
#defineleft_b();{IN31=0;IN32=1;IN33=0;IN34=0;}
//后退时右转
#defineright_b();{IN31=0;IN32=0;IN33=0;IN34=1;}
//原地打转180
#defineturn_round();{IN31=1;IN32=0;IN33=0;IN34=1;}
sfrT2MOD=0xc9;//使用定时器2时必须
sbitIN31=P2^0;//直流电机输入端IN1
sbitIN32=P2^1;//直流电机输入端IN2
sbitIN33=P2^2;//直流电机输入端IN3
sbitIN34=P2^3;//直流电机输入端IN4
sbitEN12=P2^4;//直流电机输入端IN3
sbitEN34=P2^5;//直流电机输入端IN4
sbitrw=P3^1;//1602端口定义
sbiten=P3^0;//1602端口定义
sbitrs=P3^7;//1602端口定义
sbitTest_Black_tape=P3^3;//小车车轮检测黑带条纹数
sbitbing=P3^6;//蜂鸣器
sbitTest_left=P0^0;//黑线左检测端口定义
sbitTest_Middle_left=P0^1;//黑线中检测端口定义
sbitTest_Middle_right=P0^2;//黑线右检测端口定义
sbitTest_right=P0^3;//黑线右检测端口定义
ucharPWM12=47,PWM34=49;//PWM12控制EN12,PWM34控制EN34
ucharPWM_i=0;//调速脉冲进行计时
ucharTest_flag=0;//低四位表黑线情况,第四,三,二,一位表示左,左中,右中,右侧探测结果,1表示在黑线上
uchardetector=8;//4-左侧探测器,2-中间探测器,1-右侧探测器
ucharleft_flag=0;//首先检测到黑线时被标记为1;
ucharright_flag=0;//首先检测到黑线时被标记为1;
ucharcount=0;//对黑条进行计数
ucharcorrection_flag=0;//方位矫正函数标志位,为1时可执行矫正函数
ucharControl_rotation_angle=0;//控制矫正函数转角大小
ucharControl_bing=0;//控制蜂鸣器位,为1时蜂鸣器按一定频率响
ucharbing_i=0;//控制蜂鸣器频率
ucharflag=1;//控制两边边ST188开关,flag为1时开
uintTiming=0;//控制两边边ST188开关,Timing(定时器中)等于300时(600ms),flag置为1
uintmstcnt=0;//定时器重时间计数,每1ms加1
uinttime=0;//全程时间
uintTime_delay=0;//延时时间(2ms)
ucharTime_delay_flag=0;//启动延时计时的标志位,1时启动
uintTime_interval=0;//中间两个传感器检测的黑线相差的时间(ms)
ucharTime_interval_flag=0;//启动中间两个传感器检测的黑线相差的时间(ms)的标志位,1时启动
ucharControl_count=1;//为1时允许flag开始计时
ucharturn_round_flag=1;//转弯标志位
uintdistance=0,Subsection_distance=0;//全程,每一段时间所行使的路程
uintcycle_number=0;//记录小车车轮的圈数
ucharopen_interrupt0=0;//当Close_interrupt=1时,外部中断1s后打开
uintinterrupt0_i=0;//1s打开中断进行计时
ucharstop_flag=0;//终点起点停车标志位
uchardisbuf[4]={0};//存放路程
ucharseconde[3]={0};//存放时间
ucharnumber[2]={0};//存放黑条数目
ucharcodetable1[]={"S:
0.0mt:
0s"};
ucharcodetable2[]={"count:
00"};
/***************延时子函数1us*******************/
voiddelay1us(uintus)
{
while(us--);
}
/***************延时子函数1ms*******************/
voiddelay1ms(uintms)
{
ucharj;
while(ms--)
{
for(j=0;j<120;j++);
}
}
voidwrite_com(ucharcom)//1602写指令
{
rs=0;
P1=com;
delay1us(4);
en=1;
en=0;
}
voidwrite_data(uchardata0)//1602写数据
{
rs=1;
P1=data0;
delay1us(4);
en=1;
en=0;
}
voiddisplay1()//显示时间路程程序
{
disbuf[0]=((distance/1000)%10)+0x30;//路程(cm)千位
disbuf[1]=((distance/100)%10)+0x30;//路程(cm)百位
disbuf[2]=((distance/10)%10)+0x30;//路程(cm)十位
disbuf[3]=(distance%10)+0x30;//路程(cm)个位
seconde[0]=(time/100)+0x30;//时间百位
seconde[1]=((time%100)/10)+0x30;//时间十位
seconde[2]=(time%10)+0x30;//时间个位
if(disbuf[0]==0x30)
{
disbuf[0]=0x20;//如果百位为0,不显示(显示空格)
}
if(seconde[0]==0x30)
{
seconde[0]=0x20;//如果百位为0,不显示(显示空格)
if(seconde[1]==0x30)
{
seconde[1]=0x20;//如果百位为0,十位为0也不显示(显示空格)
}
}
write_com(0x80+2);//显示路程十位
delay1us
(2);
write_data(disbuf[0]);
delay1us
(2);
write_com(0x80+3);//显示路程个位
delay1us
(2);
write_data(disbuf[1]);
delay1us
(2);
write_com(0x80+5);//显示路程十分位位
delay1us
(2);
write_data(disbuf[2]);
delay1us
(2);
write_com(0x80+6);//显示路程百分位
delay1us
(2);
write_data(disbuf[3]);
delay1us
(2);
write_com(0x80+12);//显示时间百位
delay1us
(2);
write_data(seconde[0]);
delay1us
(2);
write_com(0x80+13);//显示时间十位
delay1us
(2);
write_data(seconde[1]);
delay1us
(2);
write_com(0x80+14);//显示时间个位
delay1us
(2);
write_data(seconde[2]);
delay1us
(2);
}
voiddisplay2()//显示黑带函数
{
number[0]=(count/10)+0x30;//黑带数目十位
number[1]=(count%10)+0x30;//黑带数目个位
if(number[0]==0x30)
{
number[0]=0x20;//如果十位为0,不显示(显示空格)
}
write_com(0x80+0x40+10);//显示黑条数目十位
write_data(number[0]);
delay1us
(2);
write_com(0x80+0x40+11);//显示黑条数目个位
delay1us
(2);
write_data(number[1]);
}
/**************计算路程,并把结果放入lcd1602缓冲区**************/
voidcount_distance()
{
Subsection_distance=cycle_number*5;
distance=distance+Subsection_distance;
cycle_number=0;
}
/*************小车前进转弯函数*********************/
voidsearch_back_small()//后退小步,缓冲作用
{
back();
Time_delay_flag=1;
while(Time_delay<130);//定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_back()//后退
{
back();
Time_delay_flag=1;
while(Time_delay<200);//定时器2延时200x2=400ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_right_g_5()//前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<30);//定时器2延时30x2=60ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_right_g_10()//前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<70);//定时器2延时70x2=140ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_right_g_20()//前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<100);//定时器2延时100x2=200ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_right_g_30()//前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<130);//定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_right_g_40()//前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<170);//定时器2延时170x2=340ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_right_b()//后退实现右转
{
right_b();
Time_delay_flag=1;
while(Time_delay<105);//定时器2延时105x2=210ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_left_g_5()//前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<25);//定时器2延时25x2=50ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
voidsearch_left_g_10()//前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<45);//定时器2延时45x2=90ms
Time_delay_flag=0;
Time_delay=0;
stop()