摘 要:针对小车在行驶过程中的寻迹要求,设计了以AT89C51单片机为核心的控制电路,采用模块化的设计方案,运用色标传感器、金属探测传感器、超声波传感器、霍尔传感器组成不同的检测电路,实现小车在行驶中轨迹、探测预埋金属铁片、躲避障碍物、测量车速等问题检测,并对设计的电路进行了理论分析和实际测试。结果表明,该智能小车具有很好的识别与检测的能力,具有定位精度、运行稳定可靠的特点。
0 引 言
自主寻迹电动小车是一个运用传感器、单片机、信号处理、电机驱动及自动控制等技术来实现环境感知和自动行驶为一体的高新技术综合体,它在军事、民用和科学研究等方面已获得了应用。本文研究的电动小车是在给定的区域内沿着轨迹完成对各个目标点的访问,主要指标有行驶距离、时间、探测物计数、障碍物躲避等。本文采用AT89C51单片机作控制,针对小车在行驶过程中的不同要求,采用模块化设计方案,进行了各部分电路的设计。 1 智能小车控制的基本要求 小车必须沿规定路线行驶,控制部分设计不能采用无线遥控,具体控制要求如下:
(1)电动车从起跑线出发,沿规定引导直线行驶到达B点。在“直道区”下沿引导线埋有1一3块宽度为15cm、长度不等的薄铁片。电动车在行驶中检测到薄
铁片时需立即发出声光指示信息,并实时存储、显示在“直道区”检测到的薄铁片数目。电动车在“直道区”行驶过程中,存储并显示每个薄铁片(中心线)至起跑
线间的距离; (2)电动车到达B点以后进人“弯道区”,沿圆 弧引导线到达C点。C点下埋有边长为 15cm的正方形薄铁片,要求电动车到达C点检测到薄铁片后在C点处停车5秒,停车期间发出断续的声光信息;
(3)电动车在光源的引导下,通过障碍区进人停车区并到达车库。电动车必须在两个障碍物之间通过且不得与其接触;
(4)电动车完成上述任务后应立即停车。停车后,能准确显示电动车全程行驶时间。 2 方案的选择与实现
2.1 系统方案的确定
根据题目要求,将控制对象及检测目标划分为不同模块,即障碍物检测、路面铁片检测、路面轨迹检测、光源检测、速度路程检测等模块。针对不同模块的控制要求分别采用不同的设计方案实现。系统组成及原理框图如图1所示。其中色标传感器用来检测小车的运行轨迹,金属探测传感器用来检测路迹下薄铁片的数目,超声波传感器用来检测小车前进方向的障碍物,霍尔传感器用于检测小车行驶的速度及距离。 2.2 各部分硬件电路设计 (1)电动机PWM驱动电路
小车控制的主电路采用由达林顿管组成的H型PWM电路。用单片机控制达林顿管使之工作在占空比可调的开关状态,精确调整电动机转速。在这种电路中,管子始终工作在饱和与截止模式下,转换速度快,效率高。H型电路可以实现转速和方向的控制,是一种广泛采用的PWM调速技术。其电路图如图2。 (2)路面黑线检测电路
采用两个色标传感器组成检测电路。探测路面黑线的大致原理是:光线照射到路面并反射,由于黑线
和白纸的反射系数不同,根据接收到的反射光强弱判断是否沿黑线前进。在车底中部安装了两个GDK一Znw型色标传感器,将两个色标传感器探头置于运行轨迹中间,其间距调整为大于黑线的宽度。色标传感器接受到不同的颜色后会有不同的电平输出。本电路中当色标传感器检测到黑色,③脚输出为高电平;检测到白色,③脚输出为低电平。实际行驶时,只有当两个色标传感器同时检测为高电平,小车才直线运行,否则运用差步原理,调整方向。检测电路如图3。 色标传感器工作电流大,抗干扰能力强,检测精度高,在 黑色引导线两侧检测,可使小车沿运行轨迹精确行 驶。
(3)路面下金属片检测电路 在车底中部安装了一个金属探测传感器,将其检测面对准运行路面,当小车通过金属铁块时,传感器给出电平信号,送单片机Pl端口,通过对脉冲计数可知金属片数目。 (4)障碍物检测电路的设计
采用超声波传感器探测障碍物。超声波传感器安装于小车前端,在规定的检测距离内,当探测到障碍
物时,超声波传感器给出脉冲信号至单片机,单片机检测到该信号后,调整小车方向,以控制小车准确的
绕过障碍物。
(5)光源检测电路的设计
利用光敏电阻值随光强弱变化的特性组成光控开关电路,如图4。当无光照射时,光敏电阻阻值很大,
三极管处于截止状态,集电极输出高电平;当有光照射时,光敏电阻阻值变小,三极管饱和导通。将检测到
的高低电平信号送单片机,依此调整车头方向,使其 沿光源方向行驶。检测电路安装在小车车头位置。 (6)显示电路的设计
为了减少外部锁存器和译码模块,使功耗最小,数码管全部使用软件进行静态显示。在直道区内,
数码管显示铁片数量和起跑线到铁片中心的距离;在行驶到终点后,显示全程所用时间。用CD45fl驱动四
位数码管,一位显示铁片的数目,三位分别显示行驶的距离与时间。
(7)车速及距离检测
采用霍尔传感器检测小车速度及距离。在车后轮上安装两片磁钢,将霍尔传感器安装在固定轴上,通
过对脉冲的计数进行车速及距离的测量。霍尔传感器的使用原理如图5,汽车后轮每转一圈,霍尔元件产生
两个脉冲,将其送人单片机的TO口进行计数,同时完成脉冲数和距离的计算。
(8)小车进车库停车电路设计
当小车车体完全进人车库后,应立即停车。为了准确得到停车信号,利用光敏电阻两端电压随光的强弱变化的规律来设计电路。用200W白炽灯对准光敏电阻,当光敏电阻距离光源不同位置时,其两端的电
压按表1规律变化。 用ADC0809的INO端采集其变化电压,在3.SV时给出停车指令,完成停车任务。 3 系统的软件设计
控制电路主要由一片89c51单片机组成。89c51主要实现对路面黑线的检测,以纠正小车的行走方向;负责车速检测、铁片检测、障碍物检测、光源检测、光强度检测、电动机驱动、数据显示等功能。主程序流程如图6。 (1)直道检测。在小车的中部平行装有两个色标传感器,采用查询检测的方法对黑线进行检测。89C51
在检测到黑线信号后,通过89C51的PI.5和Pl.6口得知是哪一个传感器检测到黑线,以此作为调整小车方向的基准。在程序方面,我们采用了差补控制算法。在校正服务程序中通过检测PI.5和Pl.6口的状态,运用差补算法,精确调节左右前轮的方向,达到使小车稳定沿黑线行走的目的。为了保证程序的准确性,服务程序中设置了2重黑线检测,有效的防止了小车冲出跑道。在直道上的铁片,我们使用金属探测传感器来检测。通过计算小车开始检测到铁片与离开铁片时的圈数之差,乘以车轮的周长,我们可以得到铁片的长度以及铁片一半的长度,由此可以得到起跑线到铁片中央的距离。当车轮转动时,安装在轮胎上的磁钢使霍尔元件产生电平变化。因此只需记录电平变化的次数,便能得到实际转速。为了提高准确度,减少误差,我们安装了两块磁钢。 (2)转弯检测。为了防止小车冲出跑道以及按照黑线转弯,需要在进人弯道之前降低速度。因此我们采用了高效的H型PWM电路调节转速。在进人转弯之前,我们通过提前减速程序使小车降低速度。通过跟随黑线行驶和检测最后一片铁片的位置,我们可以得到准确的停车位置和车头方向。在铁片上停留55的期间,驱动声光报警系统,发出声光报警信号;同时,由累计脉冲的总数便可得到全程行驶的时间。
(3)障碍检测。首先我们通过寻找Zoow灯泡的光源,来校正小车的方向。然后通过超声波对障碍物进行距离检测,以此为基准,绕过障碍物。再通过检测光源找到小车与车库之间的距离,并由此引导小车准确进入车库。
4 结束语
从测试结果来看,PWM技术能够极大地提高电动机的驱动效率;双色标传感器解决了小车严格按照轨迹(黑线)运行的问题;超声波传感器能够精确测量小车与障碍物之间的距离,为躲避障碍物提供了较好的测量方法;霍尔传感器可精确测量运行中的转速。从运行情况看,采用本方案设计制作的智能小车,系统可靠性较高,运行稳定,定位准确,达到了设计要求。
单片机源程序如下:
- //========================================================
- // 工程名称: Car_Demo
- // 功能描述: 实现DIY竞赛小车的语音控制
- // 涉及的库: CMacro1016.lib
- // bsrv222SDL.lib
- // sacmv26e.lib
- // 组成文件: main.c
- // Flash.asm, hardware.asm,ISR.asm
- // hardware.h,s480.h, hardware.inc
- // 硬件连接: IOA0-----KEY1
- // IOA1-----KEY2
- // IOA2-----KEY3
- // IOB10----MOTOR1A
- // IOB11----MOTOR1B
- // IOB12----MOTOR2A
- // IOB13----MOTOR2B
- // 维护记录: 2007-06 v1.0
- // 本代码在原凌阳小车代码上修改而成,版权原作者所有!
- //========================================================
- #include "s480.h"
- #include "bsrsd.h"
- #define P_IOA_Data (volatile unsigned int *)0x7000
- #define P_IOA_Dir (volatile unsigned int *)0x7002
- #define P_IOA_Attrib (volatile unsigned int *)0x7003
- #define P_IOB_Data (volatile unsigned int *)0x7005
- #define P_IOB_Dir (volatile unsigned int *)0x7007
- #define P_IOB_Attrib (volatile unsigned int *)0x7008
- #define P_TimerA_Data (volatile unsigned int *)0x700A
- #define P_TimerA_Ctrl (volatile unsigned int *)0x700B
- #define P_TimerB_Data (volatile unsigned int *)0x700C
- #define P_TimerB_Ctrl (volatile unsigned int *)0x700D
- #define P_Watchdog_Clear (volatile unsigned int *)0x7012
- #define P_INT_Mask (volatile unsigned int *)0x702D
- #define P_INT_Clear (volatile unsigned int *)0x7011
- #define NAME_ID 0x100
- #define COMMAND_GO_ID 0x101
- #define COMMAND_BACK_ID 0x102
- #define COMMAND_LEFT_ID 0x103
- #define COMMAND_RIGHT_ID 0x104
- #define S_NAME 0 //给我取个名字吧
- #define S_ACT1 1 //前进
- #define S_ACT2 2 //倒车,请注意
- #define S_ACT3 3 //左拐
- #define S_ACT4 4 //右拐
- #define S_RDY 5 //Yeah
- #define S_AGAIN 6 //请再说一遍
- #define S_NOVOICE 7 //没有听到任何声音
- #define S_CMDDIFF 8 //说什么暗语呀
- #define S_NOISY 8 //说什么暗语呀
- #define S_START 9 //准备就绪,开始辨识
- #define S_GJG 10 //拐就拐
- #define S_DCZY 11 //倒车,请注意
- extern unsigned int BSR_SDModel[100]; //外部变量BSR_SDModel[100],辨识器自带
- extern void F_FlashWrite1Word(unsigned int addr,unsigned int Value);
- extern void F_FlashErase(unsigned int sector);
- unsigned int uiTimeset = 3; //运行时间定时,调整该参数控制运行时间
- unsigned int uiTimecont; //运行时间计时
- //=============================================================
- // 语法格式: void Delay();
- // 实现功能: 延时
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void Delay()
- {
- unsigned int i;
- for(i=0;i<0x3Fff;i++)
- {
- *P_Watchdog_Clear=0x0001;
- }
- }
- //=============================================================
- // 语法格式: void PlaySnd(unsigned SndIndex,unsigned DAC_Channel);
- // 实现功能: 语音播放函数
- // 参数: SndIndex-播放语音资源索引号
- // DAC_Channel-播放声道选择
- // 返回值: 无
- //=============================================================
- void PlaySnd(unsigned SndIndex,unsigned DAC_Channel)
- {
- BSR_StopRecognizer(); //停止识别器
- SACM_S480_Initial(1); //初始化为自动播放
- SACM_S480_Play(SndIndex, DAC_Channel, 3); //开始播放一段语音
- while((SACM_S480_Status()&0x0001)!= 0) //是否播放完毕?
- {
- SACM_S480_ServiceLoop(); //解码并填充队列
- *P_Watchdog_Clear=0x0001; //清看门狗
- }
- SACM_S480_Stop(); //停止播放
- BSR_InitRecognizer(BSR_MIC); //初始化识别器
- }
- //=============================================================
- // 语法格式: int TrainWord(int WordID,int SndID);
- // 实现功能: 训练一条指令
- // 参数: WordID-指令编码
- // SndID-指令提示音索引号
- // 返回值: 无
- //=============================================================
- int TrainWord(unsigned int WordID,unsigned int SndID)
- {
- int Result;
- PlaySnd(SndID,3); //引导训练,播放指令对应动作
- while(1)
- {
- Result = BSR_Train(WordID,BSR_TRAIN_TWICE); //训练两次,获得训练结果
-
- if(Result==0)break;
- switch(Result)
- {
- case -1: //没有检测出声音
- PlaySnd(S_NOVOICE,3);
- return -1;
- case -2: //需要训练第二次
- PlaySnd(S_AGAIN,3);
- break;
- case -3: //环境太吵
- PlaySnd(S_NOISY,3);
- return -3;
- case -4: //数据库满
- return -4;
- case -5: //检测出声音不同
- PlaySnd(S_CMDDIFF,3);
- return -5;
- case -6: //序号错误
- return -6;
- default:
- break;
- }
- }
- return 0;
- }
- //=============================================================
- // 语法格式: void TrainSD();
- // 实现功能: 训练函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void TrainSD()
- {
- while(TrainWord(NAME_ID,S_NAME) != 0) ; //训练名称
- while(TrainWord(COMMAND_GO_ID,S_ACT1) != 0) ; //训练第1个动作
- while(TrainWord(COMMAND_BACK_ID,S_ACT2) != 0) ; //训练第2个动作
- while(TrainWord(COMMAND_LEFT_ID,S_ACT3) != 0) ; //训练第3个动作
- while(TrainWord(COMMAND_RIGHT_ID,S_ACT4) != 0) ; //训练第4个动作
- }
- //=============================================================
- // 语法格式: void StoreSD();
- // 实现功能: 存储语音模型函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void StoreSD()
- { unsigned int ulAddr,i,commandID,g_Ret;
- F_FlashWrite1Word(0xef00,0xaaaa);
- F_FlashErase(0xe000);
- F_FlashErase(0xe100);
- F_FlashErase(0xe200);
- ulAddr=0xe000;//********
- for(commandID=0x100;commandID<0x105;commandID++)
- {
- g_Ret=BSR_ExportSDWord(commandID);
- while(g_Ret!=0) //模型导出成功?
- g_Ret=BSR_ExportSDWord(commandID);
- for(i=0;i<100;i++) //保存语音模型SD1(0xe000---0xe063)
- {
- F_FlashWrite1Word(ulAddr,BSR_SDModel[i]);
- ulAddr+=1;
- }
- }
- }
- //=============================================================
- // 语法格式: void StoreSD();
- // 实现功能: 装载语音模型函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void LoadSD()
- { unsigned int *p,k,jk,Ret,g_Ret;
- p=(int *)0xe000;
- for(jk=0;jk<5;jk++)
- {
- for(k=0;k<100;k++)
- {
- Ret=*p;
- BSR_SDModel[k]=Ret; //装载语音模型
- p+=1;
- }
- g_Ret=BSR_ImportSDWord();
- while(g_Ret!=0) //模型装载成功?
- g_Ret=BSR_ImportSDWord();
- }
- }
- //=============================================================
- // 语法格式: void GoAhead();
- // 实现功能: 前进子函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void GoAhead() //前进
- {
- PlaySnd(S_ACT1,3); //提示
- *P_IOB_Data=0x1400; //前进
- *P_INT_Mask |= 0x0004; //以下为中断定时操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 语法格式: void BackUp();
- // 实现功能: 后退子函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void BackUp() //倒退
- {
- PlaySnd(S_DCZY,3); //提示
- *P_IOB_Data=0x2800; //倒退
- *P_INT_Mask |= 0x0004; //以下为中断定时操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 语法格式: void TurnLeft();
- // 实现功能: 左转子函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void TurnRight() //右转
- {
- PlaySnd(S_GJG,3);
- *P_IOB_Data=0x1800; //右转
- Delay(); //延时
- *P_IOB_Data=0x2400; //左转
- *P_INT_Mask |= 0x0004; //以下为中断定时操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 语法格式: void TurnRight();
- // 实现功能: 右转子函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void TurnLeft() //左转
- {
- PlaySnd(S_GJG,3); //语音提示
- *P_IOB_Data=0x2400; //左转
- Delay(); //延时
- *P_IOB_Data=0x1800; //右转
- *P_INT_Mask |= 0x0004; //以下为中断定时操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 语法格式: void Stop();
- // 实现功能: 停车子函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void Stop() //停车
- {
- *P_IOB_Data=0x0000; //停车
- PlaySnd(S_RDY,3); //语音提示
- }
- //=============================================================
- // 语法格式: void BSR(void);
- // 实现功能: 辨识子函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void BSR(void)
- {
- int Result; //辨识结果寄存
- Result = BSR_GetResult(); //获得识别结果
- if(Result>0) //有语音触发?
- {
- *P_IOB_Data=0x0000; //临时停车
- switch(Result)
- {
- case NAME_ID: //识别出名称命令
- Stop(); //停车待命
- break;
- case COMMAND_GO_ID: //识别出第一条命令
- GoAhead(); //执行动作一:直走
- break;
- case COMMAND_BACK_ID: //识别出第二条命令
- BackUp(); //执行动作二:倒车
- break;
- case COMMAND_LEFT_ID: //识别出第三条命令
- TurnLeft(); //执行动作三:左转
- break;
- case COMMAND_RIGHT_ID: //识别出第四条命令
- TurnRight(); //执行动作四:右转
- break;
- default:
- break;
- }
- }
- }
- //=============================================================
- // 语法格式: void IRQ5(void);
- // 实现功能: 中断服务子函数
- // 参数: 无
- // 返回值: 无
- //=============================================================
- void IRQ5(void)__attribute__((ISR)); //运动定时控制
- void IRQ5(void)
- {
- if(uiTimecont++ == uiTimeset)
- {
- *P_IOB_Data = 0x0000;
- }
- *P_INT_Clear = 0x0004;
- }
- //=============================================================
- // 语法格式: int main(void);
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
单片机智能小车.rar
(387.98 KB, 下载次数: 10)
|