第二章 智能寻迹避障小车寻迹系统设计
1.任务
任务一:产生智能寻迹避障小车沿黑线转圈的控制程序;
任务二:产生智能寻迹避障小车带状态显示沿黑线转圈的控制程序;
2.要求
〔1〕能控制智能寻迹避障小车沿黑线实现转圈功能;
〔2〕行走过程中小车一直压着黑线走,不得冲出黑线圆圈之外或之; 〔3〕智能寻迹避障小车可以从小于90度的任意方向寻找到黑线圆圈;
2.1 项目描述
该项目的主要容是:在智能寻迹避障小车电机控制系统之上扩展寻迹电路,然后运用C语言对系统进展编程,使智能寻迹避障小车实现沿黑线转圆圈的功能,并且在行走过程中小车一直压着黑线走,不得冲出黑线圆圈之外或之;当人为将小车拿开,再从小于90度的任意方向放置小车,小车应能重新找回轨道,并沿黑线继续转圈。通过该项目的学习与实践,可以让读者获得如下知识和技能: 继续掌握单片机I/O端口的应用;
掌握红外线收、发对管的工作原理与控制方法; 掌握数码管的工作原理与控制方法; 掌握单片机C语言的编程方法与技巧;
能够编写出智能寻迹避障小车沿黑线实现转圈功能的控制函数;
2.1必备知识
2.1.1关于红外线传感器
红外线定义:在光谱中波长自0.76至400微米的一段称为红外线,红外线是不可见光线。所有高于绝对零度〔-273.15℃〕的物质都可以产生红外线。现代物理学称之为热射线。医用红外线可分为两类:近红外线与远红外线。
红外线发射器:红外线发射管在LED封装行业中主要有三个常用的波段,如下850NM、875NM、940NM。根据波长的特性运用的产品也有很大的差异,850NM波长的主要用于红外线监控设备,875NM主要用于医疗设备,940NM波段的主要用于红外线控制设备。如:红外线遥控器、光电开关、光电计数设备等。
红外线对管应用:本项目中,小车的寻迹功能采用红外线收、发对管实现。具体工作过程如下:两对红外线收、发对管安装在智能寻迹避障小车底盘正前方,红外发射管一直发射信号,接收管时刻准备接收信号。两对对着地的红外管发射红外信号,信号在白色的地面上反射回接收管,通过接收管把信号送回单片机进展处理,完成相应的动作。假设在黑色的地面上,信号被地面吸收,就无信号返回,单片机检测到无信号,根据程序也会做出相应的动作。如图2.1所示为红外线收、发对管外型示意图。
1 / 16
. . . .
图2.1 红外收、发对管外形图
2.3案例设计
2.3.1 系统设计方案
本项目采用单片机最小系统+红外寻线传感器来实现小车寻线功能。系统设计框图如图2.2所示。
单片机最小系统复位电路P0口电机驱动芯片直流电机STC89C52P3口时钟电路红外寻迹传感器
图2.2系统设计框图
2.3.2硬件电路设计
智能寻迹避障小车寻线电路原理图如图2.3所示:它是在单片机最小系统的根底上直接由单片机的P3连接红外线收、发对个构成的,其中单片机的P3.5端口控制左边寻线电路模块,右边寻线电路模块由P3.6控制。为了保准巡线信号的准确度,一般要求左、右红外发射对管安装时离地面高度控制在0.5cm比拟理想,距离太大,可能造成信号不灵敏,巡线不够准确,距离太小,也可能造成小车前进会与地面产生刮擦,从而损坏器件;另外,左、
2 / 16
. . . .
右收、发对管安装的距离应保持在比黑线条的宽度多一点,做到夹在黑线条,并处于黑线条的边缘,不能压在黑线上。这样巡线才能准确。
电源电路BT1C110uF+C4104C9104GNDP1.0P1.1P1.2寻线模块电路VCCBATP1.3P1.4VCCBATP1.5P1.6R3R422015KVCCBATV3V4V6V5R5R622015KP1.7RESETP3.0P3.1P3.2P3.3P3.4R1510KP3.5GNDC730PC830PGNDP3.6P3.7复位电路Z111.0592XLA1XLA2GndIC11234567891011121314151617181920STC89C52时钟电路GND403938373635343332VCCBATGNDIC3S316V/1000uF+C17GNDINPUT1OUTPUT1C15INPUT2INPUT3OUTPUT2OUTPUT3C14104OUTPUT4GNDGNDM2DC104M1DCC2104VCCBATRM1跳线RX110K上拉电阻INPUT4VccP0.0P0.1P0.2P0.3P0.4P0.5P0.6P0.7小车行走状态显示电路VCCBATVCCBATDPgfedcbaAAV2S8550R14220D2VCCBATR7560D1电机控制模块电路ENAENBGNDGNDL293DGND+C631EA30ALE29PSENP2.728P2.627P2.526P2.425P2.324P2.223P2.122P2.02110uFR2560寻线传感器LED指示电路
图2.3智能寻迹避障小车寻线电路原理图
2.3.3系统软件设计
任务一:产生智能寻迹避障小车沿黑线转圈的控制程序; 1、源程序
#include #define uint unsigned int #define uchar unsigned char #define out P2 sbit zuo1=P0^1; sbit zuo2=P0^0; sbit you1=P0^3; sbit you2=P0^2; sbit zuod=P3^5; sbit youd=P3^6; sbit qiand=P3^7; //左 右 前 3个红外传感器 3 / 16 . . . . sbit jiao=P0^6; sbit D1=P2^0; sbit D2=P0^7; void delay(uint x) { uchar i; while(x--) for(i=0;i<123;i++); } void qian() { zuo1=0; zuo2=1; //左边往前 you1=0; you2=1; //右边往前 } void hou() { zuo1=1; zuo2=0; //左边往后 you1=1; you2=0; //右边往后 } void zuo() { zuo1=1; zuo2=0; //左边往后 you1=0; you2=1; //右边往前 } void you() { zuo1=0; zuo2=1; //左边往前 you1=1; you2=0; //右边往后 } void main() { while(1) { 4 / 16 . . . . if(zuod==0&youd==0) //如果左右两个传感器没有检测到黑线 { qian(); //直走 } if(zuod==1&youd==0) //如果左边的传感器检测到黑线 { while(1) { zuo();//左转 D1=0; if(zuod==0) //一直左转到传感器检测不到为止 { D1=1; break; //跳出循环 } } } if(youd==1&zuod==0) { while(1) { you(); D2=0; if(youd==0) { D2=1; break; //道理同上 } } } } } 2、程序运行与调试 按图2.3连接智能寻迹避障小车控制电路,编译以上程序,将产生的可执行文件烧写到智能寻迹避障小车的单片机程序存储器,然后将小车放置在黑线圆圈的任意位置,开启电源,小车会沿着黑线不断转圈;将小车从黑线上拿走,然后再放放置黑线旁边,只要小车与黑线不成90度放置,那么小车通过自我修正,会重新找到黑线轨迹,继续转圈。 3、程序设计思路 根本思路是:先判断智能寻线小车左、右寻线传感器是否夹在黑线边缘,如果是说明寻线传感器处于白色区域,那么小车前进;如果不是,那么再判断左、右传感器所处的位置,如果左边传感器压到黑线,左传感器指示灯D1亮,说明小车已经偏右,那么应调左转函数修正,使左边传感器退出黑色区域;当退出黑色区域后,左传感器指示灯D1灭;当右边传感器压到黑是,方法跟左边处理类是:调用右转函数修正,同时D2亮,修正完,D2灭。 总之,小车在沿黑线转圈过程中,左、右寻线传感器始终是夹在黑线边缘〔即白色区域〕 5 / 16 . . . . 的,如果不在白色区域,就要根据情况调用左转、或右转函数进展修正。程序流程图如图2.4所示: 开始N是否在白色区域Y前进是否在左边Y左边LED灯亮N右边LED灯亮左转到无信号止,LED灭右转到无信号止,LED灭图2.4智能寻迹避障小车寻黑线转圈流程图 任务二:产生智能寻迹避障小车带状态显示沿黑线转圈的控制程序; 1、源程序 #include #define uint unsigned int #define uchar unsigned char #define out P2 sbit zuo1=P0^1; sbit zuo2=P0^0; sbit you1=P0^3; sbit you2=P0^2; sbit zuod=P3^5; sbit youd=P3^6; sbit qiand=P3^7; //左 右 前 3个红外传感器 sbit jiao=P0^6; sbit D1=P2^0; sbit D2=P0^7; uchar code ZM[]={ 6 / 16 . . . . 0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09, }; void delay(uint x) { uchar i; while(x--) for(i=0;i<123;i++); } void qian() { zuo1=0; zuo2=1; //左边往前 you1=0; you2=1; //右边往前 } void hou() { zuo1=1; zuo2=0; //左边往后 you1=1; you2=0; //右边往后 } void zuo() { zuo1=1; zuo2=0; //左边往后 you1=0; you2=1; //右边往前 } void you() { zuo1=0; zuo2=1; //左边往前 you1=1; you2=0; //右边往后 } void main() { while(1) { if(zuod==0&youd==0) //如果左右两个传感器没有检测到黑线 { qian(); //直走 out=ZM[1]; 7 / 16 . . . . } if(zuod==1&youd==0) //如果左边的传感器检测到黑线 { while(1) { zuo(); out=ZM[3]; //左转 D1=0; if(zuod==0) //一直左转到传感器检测不到为止 { D1=1; break; //跳出循环 } } } if(youd==1&zuod==0) { while(1) { you(); out=ZM[4]; D2=0; if(youd==0) { D2=1; break; //道理同上 } } } } } 2、程序运行与调试 程序的运行与调试与任务一一样,当程序下载到小车控制电路单片机中,开机运行,小车除完成任务一的动作外,还会在小车行进过程中在数码管上显示小车的状态,比如,小车前进,那么在数码管上显示“1〞;小车左转弯那么在数码管上显示“3〞;小车右转弯那么在数码管上显示“4〞。 3、程序设计思路 程序设计思路与任务一根本一样,只是在小车直行、左转、右转函数后面调用相应的状态显示字符。其程序流程图如图2.5所示。 8 / 16 . . . . 开始N是否在白色区域Y前进是否在左边Y左边LED灯亮N右边LED灯亮调用字符显示“1”左转到无信号止,LED灭右转到无信号止,LED灭调用字符显示“3”调用字符显示“4” 图2.5 带小车行走状态显示、转圈程序流程图 2.4 相关知识 2.4.1 显示模块 显示器是最常用的输出设备,其种类繁多,但在单片机系统设计中常用的是发光二极管显示器〔LED〕和液晶显示器〔LCD〕两种。由于这两种显示器结构简单,价格廉价,接口容易实现,因而得到广泛应用。下面介绍发光二极管显示器〔LED〕的结构、工作原理与其接口电路。 1、LED结构与原理 LED显示器又称为数码管,它主要由8个发光二极管组成,如图2.6〔a〕所示。图中,a~g为数字或字符显示段,h段为小数点显示,通过a~g为7个发光段的不同组合,可以显示0~9和A~F共16个数字和字母。例如,当a、b、g、e、d段亮时,显示数字“2〞,当a、f、e、g段亮时,那么显示字母“F〞。 LED可以分为共阴极和共阳极两种结构,如图2.6〔b〕和〔c〕所示。其中图〔b〕为共阴极结构。即把8个发光二极管阴极连在一起。这时如果需要点亮a~g中的任何一盏灯,那么只需要在相应端输入高电平即可;输入低电平那么截止。比如我们现在要显示数字“3〞,那么只要在对应的a、b、c、d、g段送入高电平,在其他端送入低电平即可,点亮为“3〞。图〔c〕为共阳极结构。其显示端输入低电平有效,高电平截止。 9 / 16 . . . . g f gnd a b 10 9 8 f e d 1 2 3 g c h 4 5 7 6 a b a b c d e f g h a b c d e f g h e d gnd c h 〔a〕引脚分布图 〔b〕共阴LED 〔c〕共阳LED 图2.6八段LED显示块 表2-1列出了共阳极与共阴极LED显示器显示数字、字母与显示代码之间的对应关系。 表2-1显示器显示数字、字母与显示代码之间的对应关系 显示字符 0 1 2 3 4 5 6 7 共阴极段码 3FH 06H 5BH 4FH 66H 6DH 7DH 07H 共阳极段码 C0 F9 A4 B0 99H 92H 82H F8 显示字符 8 9 A B C D E F 共阴极段码 7FH 6FH 77H 7CH 39H 5EH 79H 71H 共阳极段码 80H 90H 88H 83H C6 A1H 86H 8EH 2、LED显示器显示方式 点亮LED显示器有两种方式:一是静态显示;二是动态显示。 所谓静态显示,就是当显示器显示某一个字符时,相应的发光二极管恒定地导通或截止。如图2.7所示为4位静态LED显示器电路。该电路每一位可单独显示。只要在要显示的那位的段选线上保持段选码电平,该位就能保持显示相应的显示字符。这种电路的优点是:在同一瞬间可以显示不同的字符;但缺点就是占用端口资源较多。从图2.8可以看出,每位LED显示器需单独占用8根端口线,也就是说需要占用单片机的1个端口,而对于MCS—51单片机而言,端口资源是比拟少的。因而,在显示的数据位较多时往往不采用此种设计方法,而是采用动态显示方式。 所谓动态显示,就是将要显示的多位LED显示器采用一个8位的段选端口,然后采用动态扫描方式一位一位地轮流点亮各位显示器。如图2.8所示为4位LED动态显示电路。 10 / 16 . . . . P0口 P1口 P2口 P3口 8根段码线 8根段码线 8根段码线 8根段码线 GND GND GND GND 图2.7 4位静态LED显示器电路 P1.0 P1.1 P1.2 P1.3 P1.4 P1.5 P1.6 P1.7 段码口 5V AT89C51 位码口 P2.0 P2.1 P2.2 P2.3 图2.8 4位动态LED显示器电路 在此电路中,单片机的P1口用于控制4位LED的段选码;P2口的P2.0~P2.3用于控制4位LED位选码。由于所有的段选码连在一起,所以同一瞬间只能显示同一种字符。但如果要显示不同字符,那么要借助位选口来控制。〔如果LED为共阴,那么P2.0~P2.3输出高电平,为共阳那么P2.0~P2.3输出为低电平。〕例如,现在要显示5678四个数字,那么首先应该将“5〞的显示代码〔共阴LED的显示代码为6DH,共阳LED的显示代码为92H〕由P1.0送出。然后P2.0~P2.3输出相应位码〔共阴LED时P2.0~P2.3输出1000,共阳LED时P2.0~P2.3输出0111〕时,那么可以看到在数码管1上的显示数字“5〞。再将显示的数字“5〞延时5~10ms,以造成视觉暂留效果;同时代码由P1.0送出。用同样的方法将其余3个数字“678〞送数码管2、3、4显示,最后那么可以在4位LED上看到“5678〞四个数字。为了使显示效果稳定,可以使每个数码管显示的数字不断重复, 11 / 16 . . . . 当重复频率达到一定程度时,加之人眼视觉暂留作用,便可以看到相当稳定的“5678〞四个数字。表2-2为模拟以上显示的过程表〔以共阴LED设置显示代码,共阳与此相反。〕 表2-2 4位动态LED扫描显示状态 段选码 段选码 P1.7至P1.0 P2.3至P2.0 6DH 01H LED显示 数码管1 数码管2 数码管3 数码管4 7DH 02H 07H 04H 7FH 08H 3、LED显示器接口实例 实例1:用LED数码管显示数字“6〞 本例用LED数码管显示数字“6〞,接口电路如图2.9所示〔采用共阳极数码管〕。 实现方法:图2.9中数码的电源由单片机P2.0引脚控制,当P2.0为低电平时数码管被点亮,然后由P0控制数码管显示的数字,根据表2—1输出数字〞6〞。 U11918XTAL1XTAL2P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221222324252627281011121314151617+5VR7R0470RR1470RR2470RR3470RR4470RR5470RR6470R1kQ1PN41219RST293031AT89C51PSENALEEA12345678P1.0P1.1P1.2P1.3P1.4P1.5P1.6P1.7 图2.9数码与单片机的接口电路 12 / 16 . . . . 程序设计如下: //实例1:用LED数码管显示数字“6〞 #include P2=0xfe; //P2.0引脚输出低电平,数码显示器接通电源准备点亮 P0=0x82; //让P0口输出数字\"5\"的段码92H } 实例2:用4位数码管静态显示“1234〞 实现方法:图2.10为4位静态显示电路,在该电路中每一个数码管占用1个单片机并行端口,因而可以同时显示不同的数字,但这种方式由于过多地占用了单片机端口资源,故在实际设计中不实用,特别是显示数位数多时,不采用该种方式,而是采用动态方式实现。 R1470R2470R3470R4470R5470R6470R7470U119XTAL1P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221222324252627281011121314151617P2.0P2.1P2.2P2.3P2.4P2.5P2.6P2.7P3.0P3.1P3.2P3.3P3.4P3.5P3.6P3.7P0.0P0.1P0.2P0.3P0.4P0.5P0.6P1.0P1.1P1.2P1.3P1.4P1.5P1.6P2.0P2.1P2.2P2.3P2.4P2.5P2.6P3.0P3.1P3.2P3.3P3.4P3.5P3.618XTAL29RST293031PSENALEEAP1.0P1.1P1.2P1.3P1.4P1.5P1.6P1.712345678P1.0P1.1P1.2P1.3P1.4P1.5P1.6P1.7AT89C51 图2.10 4位数码管静态显示电路 程序设计如下: //实例2:静态显示数字“1234〞 #include ******************************************/ void main(void) { 13 / 16 . . . . P0=0x6d; //将数字5的段码送P0口 P1=0x7d; //将数字6的段码送P1口 P2=0x07; //将数字5的段码送P2口 P3=0x7f; //将数字6的段码送P3口 while(1) //无限循环,防止程序跑飞 ; } 实例3:用4位数码管动态显示“1234〞 实现方法:上例虽然实现同时显示不同数字的功能,但浪费端口资源严重,故在实现多位同时显示不同数字时多采用如图2.11所示的动态显示,这种方式能够利用较少的端口实现较多位的数字显示,因而得以实用。 87654321RN1220a9b10c11d12e13f14g15dp16C122pFU1X112M1819XTAL1P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221222324252627281011121314151617abcdefgdpQ1NPNQ2NPNQ3NPNQ4NPNC222pFXTAL2R110k9RSTC310uF293031PSENALEEA12345678P1.0P1.1P1.2P1.3P1.4P1.5P1.6P1.7AT89C51 图2.114位数码管动态显示 程序设计如下: //实例3:用4位数码管动态显示“1234〞 #include 14 / 16 . . . . uchar code DIS_SEG[4]={0xf9,0xa4,0xb0,0x99}; uchar code DIS_BIT[4]={0x01,0x02,0x04,0x08}; void delay(uint k) { uinti,j; for(i=0;i { for(cnt=0;cnt<4;cnt++) {P0=DIS_SEG[cnt]; P2=DIS_BIT[cnt]; } delay(100); P2=0X00; // 每开段位就关闭全部显示可以起到消影的作用。 } } 2.5 拓展提高 2.5.1 思考练习 1、本案例设计中智能巡迹避障小车的巡线功能与那些器件有关?如何保证巡线的准确性? 2、智能巡迹避障小车沿黑线转圈与沿黑线走“S〞型路线的控制程序是一样的吗?为什么? 3、数码管动态扫描如何实现?如何出现数码管显示出现“闪烁〞现象,应如何消除? 2.5.2 拓展训练 任务:在单片机的P2口扩展一片LCD1602作为显示器件,显示智能小车的行走状态。 要求: 15 / 16 . . . . 1、 设计满足任务要求的系统硬件电路。 2、 给出程序的设计思路,画出详细的程序流程框图。 3、 给出程序清单并加上必要的注释。 16 / 16 因篇幅问题不能全部显示,请点此查看更多更全内容