资源描述
小组名称(智能车组)
组长
张延聪
组员
李晖
组员
马力
指导人
万泉
三英卓越电子协会
比赛
论文
哈尔滨理工大学第五届“电子设计大赛”
技术报告
版本
修改日期
原因
作者
目 录
1. 摘要 1
2. 系统设计要求 1
3. 系统方案的选择与论证 2
4. 算法设计与分析 3
5. 系统设计 4
6. 系统调试 5
7. 系统测试结果分析 6
8. 参考文献. 7
9. 附录. 8
摘要
随着计算机和信息技术的飞速发展,智能技术的开发受到越来越广泛的重视,其开发速度也在快速增加。由于智能化的程度越来越高,使得其应用范围也在不断的扩展。与此同时,机器人技术的发展势头迅猛,其应用领域众多,智能循迹小车就是机器人技术与智能控制技术相结合的一个应用典范。通俗来讲,智能循迹小车就是智能机器人的另一种形式,它用轮子代替了机器人的双腿,因而在机械设计和电路方面都要比智能机器人简单,另外,其控制系统和智能机器人相比也较为简单,可是其对行车速度和行驶方向的配合则要求较严格,它首先通过传感器获取目标道路信息,然后结合智能车当前的行驶状态智能地做出决策,对其行驶方向与行车速度进行调整,从而达到准确快速跟踪道路的目的。下面将介绍了基于STC12c5a60s2单片机为控制核心的智能循迹小车的设计,该智能循迹小车是一种在控制系统的作用下,可以准确沿既定路线自动行驶的系统。本设计中,采用STC12c5a60s2单片机为主控制芯片,结合步进电机、传感器、电源电路及其他外围电路,设计实现了小车沿黑色轨迹行走的智能循迹小车,其中小车循迹功能由红外式光电传感器完成,小车的驱动功能由L298n驱动电路完成。
一、 系统设计要求
本设计中,循迹指的是小车在白色纸板上沿着2cm宽的黑线行走。红外传感器的发射管发出红外线,由接收管接收。同时,接收的物理量被转化成电信号,经过信号放大电路处理,将信息传递给单片机,进行一定的算法处理,最后根据处理过的信息通过驱动L298n芯片,来对小车的状态进行控制,从而达到驱动小车行走和循迹的目的。循迹时,由于红外线在白色地板和黑线上的反射系数不同,所以可以根据三极管接收红外线的强弱来决定小车的走向,以下是循迹小车可以实现的具体功能:
1、 在白色纸板上沿着2cm宽的黑线行走
2、 能排除中途十字线的干扰,并在终点停车
3、 可以识别并通过锐角弯、钝角弯、直角弯等
4、 可以圆滑的走过弧线形跑道
二、系统方案的选择与论证
1、方案选择
本设计采用五对红外传感器,采用“一字型”分布。中间传感器接收不到反射回来的红外线,而左右各两个传感器能接收到反射回来的红外线,则小车直线前进;当左边和中间(或只有左边)的传感器接收不到反射回来的红外线,只有右边传感器能接收到时,说明小车向右偏离黑色轨道,则小车向左转动;同理,当中间和右边(或只有右边)的传感器接收不到反射回来的红外线,只有左边传感器能接收到时,说明小车向左偏离黑色轨道,则小车向右转动,从而实现自动循迹。本设计中红外传感器离地面垂直距离为2cm,能在没有强烈日光干扰或在有日光灯的房间里,完全能满足探测要求,具有很好的可靠性与抗干扰能力。
2、模块选择
(1)单片机最小系统:
STC12C5A60S2/AD/PWM系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
(2)红外探测模块
本模块使用五个红外对管,成一字型排列,能够很好地对黑线进行检测并对小车的状态进行引导。
(3)电源模块
输入12V直流电,输出为5V、6V和12V。为单片机、红外探测模块、电机驱动模块和步进电机供电。
(4) 电机驱动模块
采用L298N芯片对步进电机进行控制,L298N有四个输入口IN1、IN2、IN3、IN4与单片机IO口相连,和四个输出口OUT1、OUT2、OUT3、OUT4分别于步进电机四线进行控制。
三、算法设计与分析
1.通过前置的一字型排列的5个红外传感器把小车此时的可能状态探测出来(探测到黑线返回低电平,否则为高电平)。定义最左边的红外对管为左1,左边第二个为左2,同理,右1,右2,中间的红外对管定义为中。
情况如下:(低—低电平,高—高电平)
(1)小左转的情况:左1(高)左2(低)中(低)右2(高)右1(高)
左1(高)左2(低)中(高)右2(高)右1(高)
(2) 小右转的情况:左1(高)左2(高)中(低)右2(低)右1(高)
左1(高)左2(高)中(高)右2(低)右1(高)
(3) 直线行走: 左1(高)左2(高)中(低)右2(高)右1(高)
左1(高)左2(低)中(低)右2(低)右1(高)
左1(低)左2(低)中(低)右2(低)右1(低)
左1(高)左2(高)中(高)右2(高)右1(高)
(4)大右转的情况:左1(高)左2(高)中(低)右2(低)右1(低)
左1(高)左2(高)中(高)右2(低)右1(低)
左1(高)左2(低)中(低)右2(低)右1(低)
左1(高)左2(低)中(低)右2(高)右1(低)
左1(高)左2(低)中(高)右2(高)右1(低)
左1(高)左2(低)中(高)右2(低)右1(低)
左1(高)左2(高)中(高)右2(高)右1(低)
(5)大右转的情况:左1(低)左2(低)中(低)右2(高)右1(高)
左1(低)左2(低)中(高)右2(高)右1(高)
左1(低)左2(高)中(高)右2(高)右1(高)
左1(低)左2(低)中(低)右2(低)右1(高)
左1(低)左2(高)中(低)右2(低)右1(高)
左1(低)左2(高)中(高)右2(低)右1(高)
左1(低)左2(低)中(高)右2(低)右1(高)
采用if语句对上述情况进行检测。
(1)(2)(3)情况下小车大致在沿直线行走或在过钝角弯,所以只对小车进行小幅度控制。采用一个轮前转,一个轮不转的方式。
(4)(5)情况下小车大致在过直角弯,锐角弯。所以需要对小车进行大幅度的调整。采用一个轮前转,一个轮后转的方式。
2.采用8拍控制2相4线步进电机,且采用总线的控制方式。这样电机在运转时相对比较稳定。
总线型8拍(双电机):0x11,0x33,0x22,0x66,0x44,0xcc,0x88,0x99
采用FOR循环驱动电机,例如:
前进函数:
Char bit[]={0x11,0x33,0x22,0x66,0x44,0xcc,0x88,0x99};
For(i=0;i<8;i++)
{
8_bit[i];
Delay();
}
这样通过不断地给电机送8拍信号就使电机前转了,而且可以通过控制给电机的8拍的数量来控制电机转动的角度。
四、 系统设计
(一)、硬件设计原理:
本系统采用STC12C5A60S2单片机为控制核心控制循迹模块及电机驱动模块。
循迹模块采用五个红外线发射管LTH-1550-01,当检测到黑线时,红外对管的接收端接收到黑白线返回来的红外光,其输出经LM358运放后传给单片机进行分析处理,然后将处理结果发送到电机驱动模块。
电机驱动模块采用L298N驱动芯片,由于单片机输出信号电压偏低,且负载能力不够,故不能用来直接驱动电机。L298N驱动芯片是性能优越的小型直流电机驱动芯片之一。它可以被用来驱动两个直流电机,或一个四线二相步进电机,在4V—6V电压下,可以提供2A驱动电流。
供电模块采用LM2596稳压。LM2596是3A电流输出降压开关型集成稳压芯片,它内含固定频率振荡器(150KHZ),和基准稳压器(1.23v),并具有完善的保护电路:电流限制、热关断电路等。利用该器件只需极少的外围器件便可构成高效稳压电路。可以实现对输出电压的调节。
(二)、硬件原理图:
1、红外探测模块原理图:
元件清单:LTH1550 5个、LM358 3个、滑动变阻器 5个、电阻若干
2、供电模块:
元件清单:LM2596 3个、LM1117 1个、滑动变阻器 3个、电感 3个、贴片led 1个、电阻若干、电容若干、二极管若干
3、电机驱动模块:
元件清单:L298N 2个、电阻若干
4、 控制核心——单片机
(三)、程序原理图:
(四)、程序设计原理:
************************以下为最终程序*********************
#include<STC12C5A60S2.H>
#define uint unsigned int
#define uchar unsigned char
//******************************************
sbit zuo_a=P2^0;
sbit zuo_b=P2^1;
sbit zuo_c=P2^2;
sbit zuo_d=P2^3;
//左右电机4线位声明
sbit you_a=P2^4;
sbit you_b=P2^5;
sbit you_c=P2^6;
sbit you_d=P2^7;
//******************************************
sbit zuo_1=P1^7;
sbit zuo_2=P1^6;
sbit zhong=P1^5; //5个红外对管位声明
sbit you_2=P1^4;
sbit you_1=P1^3;
//******************************************
sbit zuo_qian=P1^0;
sbit you_qian=P1^1;
//***************函数声明**************************
void delay(uint z);
void go();
void turn_zuo(uint a);
void turn_you(uint b);
void init();
void jiance();
void turn_big_zuo(uint big_zuo);
void go_(uint go);
void turn_big_you(uint big_you);
void time0_init();
//******************************************
uchar code date[]={0x11,0x33,0x22,0x66,0x44,0xcc,0x88,0x99};//前进码
uchar code date_zuo[]={0x10,0x30,0x20,0x60,0x40,0xc0,0x80,0x90};//小左转码
uchar code date_big_zuo[]={0x19,0x38,0x2c,0x64,0x46,0xc2,0x83,0x91};//大左转码
uchar code date_big_you[]={0x91,0x83,0xc2,0x46,0x64,0x2c,0x38,0x19};//大右转码
uchar code date_you[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//小右转码
//******************************************
uint c,turn_you_delay,turn_zuo_delay,small_zuo,small_you,shizi,num,shizi_float,shizi1,o,black;
void main()
{
delay(6000);
delay(6000);//延时大约3秒
delay(6000);
init();//初始化函数
while(1)
{
jiance();//检测函数
}
}
void init()
{
shizi1=0;
shizi_float=0;
shizi=0;
time0_init();
turn_zuo_delay=20;
turn_you_delay=20;
c=40;
small_zuo=20;
small_you=20;
num=0;
o=14;
black=2;
}
//**************定时器0初始化50ms*************************
void time0_init()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
//****************中断函数*******************
void time0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
//***************终点停止函数********************************
shizi++;
if(shizi==4)
{
shizi=0;
if(zuo_1==0&&zuo_2==0&&zhong==0&&you_1==0&&you_2==0)
{
go_(10);
num++;
}
if(num==2)
{
TR0=0;
num=0;
go_(20);
while(1);
}
//**********************************************
}
}
//******************延时函数***************************
void delay(uint z)
{
uint i ;
uchar j;
for(i=0; i<z; i++)
for(j=0; j<110; j++);
}
//******************前进函数**************************
void go()
{
uint i;
for(i=0;i<8;i++)
{
P2=date[i];
delay(c);
}
}
//********************可控前进函数************************
void go_(uint go)
{
while(--go)
{
uint i;
for(i=0;i<8;i++)
{
P2=date[i];
delay(c);
}
}
}
//*********************小左转函数***********************
void turn_zuo(uint a)
{
uint i;
while(--a)
{
for(i=0;i<8;i++)
{
P2=date_zuo[i];
delay(small_zuo);
}
}
}
//***********************大左转函数*******************
void turn_big_zuo(uint big_zuo)
{
uint i;
while(--big_zuo)
{
for(i=0;i<8;i++)
{
P2=date_big_zuo[i];
delay(turn_zuo_delay);
}
}
}
//************************小右转函数******************
void turn_you(uint b)
{
uint i;
while(--b)
{
for(i=0;i<8;i++)
{
P2=date_you[i];
delay(small_you);
}
}
}
//*************************大右转函数*****************
void turn_big_you(uint big_you)
{
uint i;
while(--big_you)
{
for(i=0;i<8;i++)
{
P2=date_big_you[i];
delay(turn_you_delay);
}
}
}
//**************************检测函数****************
void jiance()
{
if(zhong==0&&zuo_1==0&&zuo_2==0&&you_1==0&&you_2==0)
{
go();
}
if(zhong==0&&zuo_1==1&&zuo_2==1&&you_1==1&&you_2==1)
{
go();
}
if(zhong==0&&zuo_1==1&&zuo_2==0&&you_1==1&&you_2==0)
{
go();
}
if(zhong==1&&zuo_1==1&&zuo_2==1&&you_1==1&&you_2==1)
{
go();
}
if(zhong==0&&zuo_2==0&&zuo_1==1&&you_1==1&&you_2==1)
{
turn_you(4);
}
if(zhong==1&&zuo_2==0&&zuo_1==1&&you_1==1&&you_2==1)
{
turn_zuo(4);
}
if(zhong==0&&zuo_2==1&&zuo_1==1&&you_1==1&&you_2==0)
{
turn_you(4);
}
if(zhong==1&&zuo_2==1&&zuo_1==1&&you_1==1&&you_2==0)
{
turn_you(4);
}
//........................大左转.....................................
if(zhong==0&&zuo_2==0&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(black);
if(zhong==0&&zuo_2==0&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(o);
while(zhong)
{
turn_big_zuo(2);
}
}
}
if(zuo_1==0&&zuo_2==0&&zhong==0&&you_1==1&&you_2==0)
{
if(zuo_1==0&&zuo_2==0&&zhong==0&&you_1==1&&you_2==0)
{
go_(black);
go_(o);
while(zhong)
{
turn_big_zuo(2);
}
}
}
if(zhong==0&&zuo_2==1&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(black);
if(zhong==0&&zuo_2==1&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(o);
while(zhong)
{
turn_big_zuo(2);
}
}
}
if(zhong==1&&zuo_2==1&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(black);
if(zhong==1&&zuo_2==1&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(o);
while(zhong)
{
turn_big_zuo(2);
}
}
}
if(zhong==1&&zuo_2==0&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(black);
if(zhong==1&&zuo_2==0&&zuo_1==0&&you_1==1&&you_2==1)
{
go_(o);
while(zhong)
{
turn_big_zuo(2);
}
}
}
if(zuo_1==0&&zuo_2==1&&zhong==0&&you_2==0&&you_1==1)
{
go_(black);
if(zuo_1==0&&zuo_2==1&&zhong==0&&you_2==0&&you_1==1)
{
go_(o);
while(zhong)
{
turn_big_zuo(2);
}
}
}
//....................大右转........................
if(zuo_1==1&&zuo_2==0&&zhong==0&&you_1==0&&you_2==0)
{
go_(black);
if(zuo_1==1&&zuo_2==0&&zhong==0&&you_1==0&&you_2==0)
{
go_(o);
while(zhong)
{
turn_big_you(2);
}
}
}
if(zhong==0&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==0)
{
go_(black);
if(zhong==0&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==0)
{
go_(o);
while(zhong)
{
turn_big_you(2);
}
}
}
if(zhong==0&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==1)
{
go_(black);
if(zhong==0&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==1)
{
go_(o);
while(zhong)
{
turn_big_you(2);
}
}
}
if(zuo_1==1&&zuo_2==0&&zhong==0&&you_2==1&&you_1==0)
{
go_(black);
if(zuo_1==1&&zuo_2==0&&zhong==0&&you_2==1&&you_1==0)
{
go_(o);
while(zhong)
{
turn_big_you(2);
}
}
}
if(zhong==1&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==1)
{
go_(black);
if(zhong==1&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==1)
{
go_(o);
while(zhong)
{
turn_big_you(2);
}
}
}
if(zhong==1&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==0)
{
go_(black);
if(zhong==1&&zuo_2==1&&zuo_1==1&&you_1==0&&you_2==0)
{
go_(o);
while(zhong)
{
turn_big_you(2);
}
}
}
}
五、 系统调试
(一)、硬件调试:
1、红外探测模块的调试:
检测红外检测模块能否有效的探测到黑条,并返回有效的高低电平。
2、 单片机模块的调试:
检测打片机模块是否能输出有效的高低电平,并能实现相应的功能。
3、 电机驱动模块的调试:
检测L298N能否被单片机有效控制,并输出电机所需要的有效电压。
4、 电源模块:
检测电源模块能否在输入12V的情况下输出6V,12V的稳定电压。
(二)、软件调试:
初级调试:
1. 首先在LEIL上进行初步的程序编译,检查是否存在最基本的语法错误。
2. 检测程序能否对单片机进行有效的控制。
3. 检测电机驱动部分能否对步进电机进行有效的控制。
4. 检测程序能否对外检测模块反馈回来的信息作出正确的判断。
功能调试:
1. 检测程序控制小车走直线的效果。
2. 检测程序控制小车过直角弯,钝角弯,锐角弯,大圆弧,十字线的效果。
3. 检测终点停车函数是否有效。
(三)、整体调试:将小车各个模块组装起来,并将写好的程序下载到小车的单片机中。在跑道中进行整体的测试。
六、 测试结果与分析
(一) 、硬件调试结果:
1. 调试过程中发现红外探测模块受光线要求太大,很不稳定。最后我们把红外对管的高度放低,这样尽量减少光线对其的影响。效果比较好。
2. 电机驱动模块存在虚焊的情况,并且有的二极管方向反了。最后把焊点重新用焊锡焊一边把虚焊的情况解决了。然后将焊反的二极管换了新的二极管。
(二) 、软件调试结果:
1. 首先发现采用分步控制步进电机的方法时,电机状态不稳。通过采用总线控制将问题解决了。
2. 过干扰黑条是出现误判现象,原因是前方传感器不是平行进入黑条的,带有一定的角度,这样可能误判成过锐角弯。解决方法:在每个大角弯判断语句后加上前进的函数,前进一段距离后在进行判断。从而避免了误判。
3. 过锐角弯是转弯过早且角度不好。解决方法:过锐角弯的动作函数改为一个轮前进,一个轮后退,这样转弯速度,角度都变得更合适了。且在判断为锐角弯时命令车向前走适当的距离,解决转弯过早的问题。
4. 原终点停车方式容易造成误判。解决方法:使用中断,每0.2s对红外探测信号检测一次。如果同时为低,则计数一次,计数4次后停车。
5. 过圆弧弯不够圆滑,且又是错过大角度弯。原因分析:在做小角度调整是恰好经过大角度弯,将其错过。解决方法:将小转弯函数的转弯时间改短。
七、参考文献
(1)马忠梅.单片机的c 语言应用程序设计[M]. 北京:北京航空航天大学出版社,2007
(2) 阎石.数字电子技术基础[M].北京:高等教育出版社,1997年.
(3) 吴运昌.模拟电子线路基础著[M].广州:华南理工大学出版社,2004年.
(4)王晓明.电动机的单片机控制[M].北京:北京航空航天大学出版社,2002.
附录
展开阅读全文