红外自动循迹小车实验报告
摘要
本实验完成采用红外反射式传感器的自寻迹小车的设计与实现。采用与白色地面色差很大的黑色路线引导小车按照既定路线前进,在意外偏离引导线的情况下自动回位,并能显示小车停止的时间。
本设计采用单片机STC89C51作为小车检测、控制、时间显示核心,以实验室给定的车架为车体,两直流机为主驱动,附加相应的电源电路下载电路,显示电路构成整体电路。自动寻迹的功能采用红外对管LTH1550实现,信号经三极管9012放大,经LM339电压比较器比较之后将信号送给单片机,由单片机通过控制驱动芯片L298N驱动电动小车的电机,实现小车的动作。同时还可以将小车的停留时间通过四位数码管显示。
关键词:STC89C51单片机;红外对管LTH1550;红外传感器;寻迹
一、系统设计任务与要求
小车从上坡处开始行驶,到达坡顶停留5秒,由数码管显示停留时间,然后继续行驶,到达坡底开始沿黑线行驶,直到终点宽黑线停止。
二、 方案分析与论证
总体方案设计:
根据题目,我们设计了以下方案并进行了综合的比较论证,自动寻迹电动小车系统由小车主体部分、微控制器模块、寻迹传感器模块、电机驱动模块、显示模块、电源模块构成。
2.1 总体方案论证与比较
方案一:采用数字电路来组成小车的各部分系统,实现各部分功能。本方案电路复杂,灵活性不高,效率低,不利于小车智能化的扩展,设计困难。
方案二:采用单片机来作为整机的控制单元。黑线检测采用红外对管对光源信号进行采集,再经过三极管放大,电压比较使输出转化为数字信号送到单片机系统处理。此系统比较灵活,采用软件方法来解决复杂的硬件电路部分,使系统硬件简洁化,各类功能易于实现,能很好地满足题目的要求。
方案二简洁、灵活、可扩展性好,能达到题目的设计要求,因此采用方案二来实现。方案二的基本结构图如下:
图1 总体系统结构框图
2.2 寻迹检测方案的选择
方案一:采用CCD传感器。利用CCD传感器进行自动导航的机器人已得到初步应用。但CCD传感器价格较高,体积较大,数据处理复杂,不适合本次实验使用。
方案二:用红外对管作为寻迹传感器。红外反射式传感器由1个红外发射管(发射器)和1个光电二极管(接收器)构成。红外发射管发出的红外光在遇到反光性较强的物体(表面为白色或近白色)后被折回,被光电二极管接收到,引起光电二极管光生电流的增大。将这个变化转为电压信号,该电压通过比较器LM339后转换为高电平(单片机的有效电平),检测出白线;若接收不到发射管发出的光线则输出为低电压,该电压通过比较器LM339后转换为低电平(单片机的有效电平),检测出黑线。方案可行,且红外对管使用方便,所以选用方案二。
原理图见图2。
图2
正确选择检测方法和传感器件是决定循迹效果的重要因素,而且正确的器件安装方法也是循迹电路好坏的一个重要因素。从简单、方便、可靠等角度出发,同时在底盘装设5个红外探测头,进行两级方向纠正控制,将大大提高其循迹的可靠性。
2.3 电机驱动方案的选择
方案一:采用继电器对电动机的开或关进行控制,通过开关的切换对小车的进行调整.此方案的优点是电路较为简单,缺点是继电器的响应时间慢,易损坏,寿命较短,可靠性不高。
方案二:采用专用芯片L298N作为电机驱动芯片。L298N是一个具有高电压大电流的全桥驱动芯片,它相应频率高,一片L298N可以分别控制两个直流电机,而且还带有控制使能端。用该芯片作为电机驱动,操作方便,稳定性好,性能优良。
因此决定采用方案三.
2.4 电机的选择
方案一:采用步进电机,步进电机具有快速启动和停止能力,其转换灵敏度比较高,正转、反转控制灵活。但是步进电机的价格比较昂贵,且该实验对小车速度等没有特殊要求,因而,不选用该方案。
方案二:采用普通的直流电机。直流电机具有优良的调速特性,调速平滑、方便。调整范围广;过载能力强,能承受频繁的冲击负载,可实现频繁的无极快速启动、制动和反转。可以满足实验要求。
2.5 稳压模块的选择
7805稳压芯片使用方便,用很简单的电路即可以输入一个直流稳压电源,使其输出电压恰好为5v,达到逻辑电路电压要求,因此,直接选用7805作为稳压芯片,将电压稳压至5V给单片机系统和其他芯片供电。
2.6 显示模块方案的选择
方案一:使用液晶显示屏显示时间。液晶显示屏(LCD)优点是:低耗电量、无辐射危险,平面直角显示以及影象稳定不闪烁等优势,可视面积大,画面效果好,分辨率高,抗干扰能力强等。缺点是:液晶显示屏是以点阵的模式显示各种符号,需要利用控制芯片创建字符库。编程工作量大,控制器的资源占用较多,在使用时,不能有静电干扰,否则易烧坏液晶的显示芯片,不易维护,其成本也偏高。并且本系统只需要显示时间,信息量比较少,因此并不适于选用液晶显示屏。
方案二:使用数码管显示行驶时间。数码管具备数字接口,显示清晰,价格较低,作为时间显示的器件性价比非常高,方便易行。
决定采用数码管显示行驶时间.
三、 单元电路设计
3.1控制部分设计:
小车控制单元是整个小车运行的核心部件,起着控制小车所有运行的作用。本实验采用的是STC89C51单片机。控制部分设计包括单片机的复位电路及起振电路。单片机晶体振荡模块采用最常用的内部时钟方式,即用外接晶体和电容组成的并联谐振回路。振荡晶体选择11.0592MHz。具体电路见图3。单片机启动运行时,都需要先复位,单片机本身是不能自动进行复位的,必须配合相应的外部电路复位。复位电路采用按键手动复位,电路见图4。
图3 图4
3.2寻迹部分设计
题目要求小车要沿着画出的黑线运动,但在运动过程中,车体不可避免地会偏离运动轨迹,为了能使车体在偏离后可以自动调整方向,重新回到运动轨迹上,系统需要将车体的运动状态及时地以电信号的形式反馈到控制部分,控制部分控制两个电机的左转,右转,使小车重新回到轨迹上。
本设计中共使用5个集成的红外对管LTH1550装在车体的前方。
当检测到黑线时,红外对管的接收端接收到黑白线反射回来的红外光,其输出经LM339电压比较器后立即发生高低电平转换,该信号经9012放大后送到单片机进行分析处理。然后将处理后的结果发送到电机驱动模块,进行校正。电路见图5。
图5
3.3.驱动部分设计
由于单片机输出的信号不仅点压偏低,而且负载能力不够,不能用来直接驱动电机
L298N驱动芯片是性能优越的小型直流电机驱动芯片之一。它可被用来驱动二个直流电机。在4—6V的电压下,可以提供2A的驱动电流。L298N还有过热自动关断功能,并有反馈电流检测功能,符合电机驱动的需要。因此需要使用驱动芯片L298N,单片机输出的信号,经过L298N实现功率的放大,从而驱动电机工作。L298N芯片是一种高压,大电流双全桥式驱动器,其设计是为接受标准TTL逻辑
电平信号和驱动电感负载的.电路图见图6.
图6
3.4稳压部分设计
直流电机需要6V供电,但是单片机需要的电压是5V,这就需要稳压片将6V左右的电压较为准确的控制为5V,而6V的电压直接给直流电机供电,保证用一路信号实现两路功能。首先将电压源输出的6V转换为5V直流稳压电源,实现方法是应用滤波电路(电解电容)使电压变为平稳的直流电,然后通过稳压电路即7805使输出5V直流稳压供给单片机及驱动芯片的相应电压。电路见图7。
图7
3.5.显示部分设计
本实验采用四位共阳极数码管进行数码显示,它有四个位选,由于本实验只需显示小车停止行驶的时间,因而只需选通一位位选线,当各段阴极上的电平为“0”时,该段点亮,电平为“1”时,该段熄灭。数码管与单片机之间通过反相器74LS04连接,具体电路见图8。
图8
3.6下载电路设计
下载电路用来下载程序,其中用MAX232实现电平转化,将PC机输出的RS-232(12V)电平转化为标准的TTL电平(5V)。电路见图9。
图9
四、系统软件设计
4.1 主程序流程图
寻迹子程序中红外对管与小车偏转方向关系如表一.:
表一
五、 系统功能测试
5.1 测试仪器及设备
测试仪器及设备如表2:
5.2 安装调试及测量数据分析
整机焊接完毕,首先对硬件进行检查联线有无错误,再逐步对各模块进行调试。我负责的电源部分,驱动部分,黑线寻迹部分,具体测试过程如下:
1.电源测试过程
6V电压输入,经稳压片7805之后的电压为4.80V,电压在4.8~5.2V之间,所以该部分符合要求。
2.驱动部分测试过程
将驱动部分与单片机正确连接之后,在单片机中写入电机控制小程序,控制其转动与停止,用万用表测试输出电压正常。
3.黑线寻迹部分测试
首先,通过调每一路的电位器(50K),使9012的C管脚输出电压为4.7V~4.8V,然后调节10K的电位器,使其两端的电压为2.9V左右,作为阈值电压。设置好阈值电压之后,将电路板上有红外对管的那一面朝下,分别对着白纸和黑线,测每个红外对管的输出信号经电压比较器之后的电压,数据记录如表3:
表3
由测量结果可知,每个红外对管检测到白纸和黑线的输出电压均位于阈值电压两侧,且相差较大,经反相器比较后可以立即发生高低电平的转换,符合要求。
至此,这三部分硬件调试完毕。
整体综合调试
将所有模块连接(加入最小系统,显示部分),检查连接无误之后,写入总程序。开始整车测试,数码管有显示,但是小车电机不转,但有很轻的声音从电机中发出,想到可能是驱动电路部分电压不够,在输入电压加到6.4V后测试过程一切正常。
六.结论
完成了控制部分各模块的焊制及连接,以及51版的程序下载,数码管按照既定的计划轮换闪亮.
七:结束语
在实验过程中,由于焊接的工艺不是很到位,初次完成电路板的焊制并下载程序后,数码管并没有亮,通过检查焊点并更换排针排线,克服了接触不良的故障,由于是自己完成实验的控制部分,故小车实际上并没有真正按照设计目的行驶,但同样在这次实验中,熟悉了MCS51的功能及焊制方法,以及程序的下载方法,在老师的帮助下,感觉收获很大.
八.附录
1.总电路图(见图9,图10)
图9
图10
2.元件表(见表三)
表三 元件表
3.程序
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int //定义用uint表示无符号整形常量
sbit wei0=P2^0;
sbit wei1=P2^1;
sbit wei2=P2^2;
sbit wei3=P2^3;
/*****电机控制部分的数据定义********/
sbit a0=P1^0; //分别用a0,b0,a1,b1替代P1口的P0到
sbit b0=P1^1; //P3引脚
sbit a1=P1^2;
sbit b1=P1^3;
/*********寻迹部分的变量定义**********/
sbit lefter_det=P3^2; //最左边的红外信号传给P3^2
sbit left_det=P3^3; //左边的红外信号传给P3^3
sbit mid_det=P3^4; //中间的红外信号传给P3^4
sbit right_det=P3^5; //右边的红外信号传给P3^5
sbit righter_det=P3^6; //最右边的红外信号传给P3^6
bit mid,left,lefter,right,righter, stop; //一些标志位,用来表示偏向哪边,从而做出适当的调整
void status(void);
void run_forward(void);
void turn_left (void);
void turn_lefter(void);
void turn_righter(void);
void turn_right(void);
void stop_run(void);
uchar code dis_7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82, 0xF8,0x80,0x90};
/***********寻迹模块***************/
//
void status(void) //高电平说明检测到信号
{
if(lefter_det&&righter_det) //全都检测到信号,说明小车到达终点
{
left=0;
lefter=0;
mid=0;
right=0;
righter=0;
stop_run();
}
else if(mid_det)
{
left=0;
lefter=0;
mid=1;
right=0;
righter=0;
run_forward();
}
else if(left_det)
{
left=0;
lefter=0;
mid=0;
right=1;
righter=0;
turn_left();
}
else if(right_det)
{
left=1;
lefter=0;
mid=0;
right=0;
righter=0;
turn_right();
}
else if(lefter_det)
{
left=0;
lefter=0;
mid=0;
right=0;
righter=1;
turn_lefter();
}
else if(righter_det)
{
left=0;
lefter=1;
mid=0;
right=0;
righter=0;
turn_righter();
}
else
{
left=0;
lefter=0;
mid=1;
right=0;
righter=0;
run_forward();
}
}
void run_forward(void)
{P1=0xcc;}
void turn_left(void)
{P1=0x0c;}
void turn_right(void)
{P1=0xc0;}
void turn_lefter(void)
{P1=0x0c;}
void turn_righter(void)
{P1=0xc0;}
void stop_run(void)
{P1=0x00;}
void delay (uchar x)
{
uchar i,j,k;
for (i=0;i<x;i++)
{
for (j=0;j<100;j++)
for (k=0;k<100;k++);
}
}
void xianshi ()
{
uchar i;
wei0=1;
wei1=1;
wei2=1;
wei3=0;
for (i=1;i<6;i++)
{
P0=dis_7[i];
delay(20);
}
}
void xianshi2 ()
{
wei0=1;
wei1=1;
wei2=1;
wei3=1;
P0=0x00;
}
/*主函数*/
main()
{
run_forward() ;
delay (100);
stop_run() ;
xianshi ();
xianshi2 ();
while(1)
{
if (P3==0x00)
{
run_forward() ;
}
else
{
status();
}
}
}