综合设计实验报告
实验名称:超声波测距系统
班级:6
组员: 1142
11420511
摘要--------------------------------------------------------------------------------------------------- - 1 -
第一章 绪论----------------------------------------------------------------------------------------- - 1 -
1.1 系统总体介绍----------------------------------------------------------------------------- - 1 -
1.2 超声波测量原理--------------------------------------------------------------------------- - 1 -
第二章 方案拟定------------------------------------------------------------------------------------ - 2 -
2.1 系统控制模块----------------------------------------------------------------------------- - 2 -
2.2 距离测量模块----------------------------------------------------------------------------- - 2 -
2.3 温度测量模块----------------------------------------------------------------------------- - 2 -
2.4 实时显示模块----------------------------------------------------------------------------- - 3 -
第三章 硬件电路设计------------------------------------------------------------------------------ - 3 -
3.1 超声波收发电路--------------------------------------------------------------------------- - 3 -
3.2 蜂鸣器报警电路--------------------------------------------------------------------------- - 4 -
3.3 温度补偿电路----------------------------------------------------------------------------- - 4 -
3.4 数码管显示电路--------------------------------------------------------------------------- - 5 -
第四章 软件设计------------------------------------------------------------------------------------ - 7 -
第五章 功能测试及性能指标---------------------------------------------------------------------- - 8 -
第六章 问题解决及总结--------------------------------------------------------------------------- - 9 -
附件-------------------------------------------------------------------------------------------------- - 10 -
进度分工表------------------------------------------------------------------------------------ - 10 -
电路原理图------------------------------------------------------------------------------------ - 10 -
PCB原理图------------------------------------------------------------------------------------ - 11 -
程序代码--------------------------------------------------------------------------------------- - 11 -
摘要
本系统是一个以单片机技术为核心,实现实时测量并显示距离的超声波测距系统,系统主要由4部分组成:超声波收发电路、温度补偿电路、LED显示电路、CPU处理电路。系统测量距离的原理是先通过单片机发出40KHz方波串,然后检测超声波接收端是否接收到遇到障碍物反射的回波,得到来回路程的时间计算距离,同时测温装置检测环境温度来校准速度。单片机利用收到回波所用的时间和温度补偿得到的声速计算出距离,显示当前距离与温度。由于利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制,并且在测量精度方面能达到工业实用的要求,因此超声测距在工业上得到广泛的应用,例如在自动避障机器人、汽车倒车雷达、汽车追尾报警等,具有重大的现实社会意义。
第一章 绪论
1.1 系统总体介绍
超声波测距仪主要由超声波收发装置、单片机、测温装置、报警装置、LCD显示等组成。系统检测距离的原理是通过单片机发出40 kHz的方波脉冲信号后, 检测接收端是否能够接收到遇障碍物反射的回波,同时,测温装置检测环境温度。单片机利用收到回波所用的时间和温度补偿得到的声速计算出距离,同时显示出当前距离与温度。测量距离范围为2~400cm。可测量温度范围为-30~150°C。有温度与距离显示,误差小,精度高。蜂鸣器预警和距离采样频率动态变化,距离越远,采样越慢。
1.2 超声波测量原理
超声波传感器分机械方式和电气方式两类,它实际上是一种换能器,在发射端它把电能或机械能转换成声能,接收端则反之。本次设计超声波传感器采用电气方式中的压电式超声波换能器,它是利用压电晶体的谐振来工作的。它有两个压电晶片和一个共振板。当它的两极外加脉冲信号频率等于压电晶片的固有振荡频率时,压电晶片将会发生共振,并带动共振板振动,产生超声波。反之,如果两电极间没有外加电压,当共振板接收到超声波时,将压迫压电晶片作振动,将机械能转换为电信号,就成为超声波接收器。在超声波电路中,发射端输出一系列脉冲方波,脉冲宽度越大,输出的个数越多,能量越大,所能测的距离也越远。
超声波测距的原理有很多种,本次实验采用往返时间计算法。由于超声波指向性强,能量消耗缓慢,在空气中传播的距离较远,因而超声波经常用于距离的测量。利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制,并且在测量精度方面能达到工业实用的要求。
超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。超声波在空气中的传播速度为C,根据计时器记录的时间t,就可以计算出发射点距障碍物的距离(s),即:s=Ct/2 。
从上面超声波特性可以知道:超声波在空气中的传播速度与温度有关:C=331.5+0.607t/0C (m/s),如果温度变化不大,则可认为声速是基本不变的,典型的环境温度与超声波的传播速度的关系为:
第二章 方案拟定
2.1 系统控制模块
采用AT89S52作为系统控制器。它的运算功能强,软件编程灵活,自由度大,可用软件编程实现各种算法和逻辑控制,并且其功耗低,成本低,技术成熟。控制,并且功耗低,成本低,技术成熟。其程序可以采用C语言编写,可读性强,烧写程序容易,这大大加快了系统的开发与调试。AT89S52有2个独立的定时器,两个独立的外部中断,IO足够,还可外拓功能,做冗余设计。可以达到要求。
2.2 距离测量模块
采用超声波传感器测距。由于超声波的波长短,超声波射线可以和光线一样,能够反射、折射、也能够聚焦,而且遵循几何光学上的定律。即超声波从一种物质表面反射时,反射角等于入射角。且超声波具有较好的指向性,频率越高,指向性越强,具有较高的分辨率,因而其测试精度也较其他方法高。而且超声波传感器具有体积小,结构简单,信号处理可靠性高的特点,且价格较便宜,成功案例较多,可行性很高。
本次实验采用的是超声波收发模块(HC-SR04),该模块收发一体,大大节约了硬件开销,
2.3 温度测量模块
温度测量模块采用数字温度芯片DS18B20测量温度,测温范围为-55—+125摄氏度,固有测温分辨率为1摄氏度,外围电路简单,输出信号为数字信号,便于数据处理。同时该芯片物理化学性质稳定,线性良好,能够满足此次测温要求。
2.4 实时显示模块
显示模块使用传统的数码管显示。数码管具有:低能耗、低损耗、寿命长,耐老化、对外界环境要求低,易于维护等特点,同时其精度比较高,操作简单。数码管采用BCD编码显示数字,程序编译容易,资源占用较少。
方案设计中采用电源接通或复位开关后先显示当前环境温度,停顿一秒然后显示测量距离。
第三章 硬件电路设计
3.1 超声波收发电路
HC-SR04特性:
ü 探测距离:2cm-400cm;
ü 测量精度:3mm;
ü 模块工作原理:
(1)采用IO触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO输出一高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2。
图1 HC-SR04电气参数
图2 HC-SR04实物正反两面图
图3 HC-SR04连接电路
3.2 蜂鸣器报警电路
蜂鸣器报警用S8550三极管驱动蜂鸣器报警,P1.0口控制蜂鸣器,具体电路如下所示:
图4 蜂鸣器报警电路
3.3 温度补偿电路
由于声音的速度在不同的温度下有所不同,为提高系统的精度,采用了温度补偿功能。这里采用的主要元器件是DS18B20芯片,DS18B20是美国DALLAS半导体公司生产的可组网数字式温度传感器,在其内部使用了在板(ON-B0ARD)专利技术。全部传感元件及转换电路集成在形如一只三极管的集成电路内。与其它温度传感器相比,DS18B20具有以下特性:
(1)独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。
(2)DS18B2支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现多点测温。
(3)DS1820在使用中不需要任何外围元件。
(4)温范围-55℃~+125℃,固有测温分辨率1℃。
(5)测量结果以9位数字方式串行传送。
DS18B20内部结构框图如图4所示:
图5 DS18B20内部结构图
本系统中DS1820由单片机P2.0控制,由LED显示电路动态显示温度。电路原理图如图:
图6 DS18B20电路
3.4 数码管显示电路
数码管由7个发光二极管组成,行成一个日字形,通过解码电路得到的数码接通相应的发光二极管而形成相应的字,这就是它的工作原理。数码管按各发光二极管电极的连接方式分为共阳数码管和共阴数码管两种,如图7。
数码管的显示方式可以分为静态显示与动态显示两类。其中动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8 个显示笔划“a, b, c, d, e, f, g, dp“的同名端连在一起,其余的为每个数码管的公共极COM 由位选通控制电路控制,位选通由各自独立的I/O 线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM 端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM 端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,但是能够节省大量的I/O 端口,功耗更低。
本系统的显示电路采用简单实用的4位共阳数码管,段码输出端口为单片机的P0口,位码输出端口分别为单片机的P2.1、P2.3、P2.5、P2.7口。为了减少硬件开销,提高系统可靠性并降低成本,此超声波测距的单片机控制系统采用动态扫描显示,并且软件消影。显示电路如图8所示。
图7 数码管
图8 数码管电路
第四章 软件设计
下图示意了超声波测距的原理,即超声波发射器在某一时刻发出一个超声波信号,当超声波遇到物体后反射回来,就被超声波接收器所接到。这样,只要计算出从发出超声波信号到接收到返回信号所用的时间,就可以算出超声波发生器与反射物体的距离。距离的计算公式为:
d=s/2=(c*t)/2
其中d为被测物与测距器的距离,s为声波的来回路程,c为声速,t为声波来回所用的时间。
图9 超声波测距原理
超声波测距的软件设计主要由主程序、超声波发射子程序及显示子程序,报警子程序组成。由于C语言程序有利于实现较复杂的算法,所以采用C语言来实现软件部分。具体流程图如下所示:
图10 程序流程图
详细程序见附件。
第五章 功能测试及性能指标
为了验证系统的测量精度,在宿舍进行了实地测量。我们选取墙面为被测对象,利用本系统对2-400cm范围进行了多次测试,随机抽取3次测量结果,求平均值,其中2-350cm精度达到±1cm,大于350cm误差变大,根据多次的测量与计算,本系统经补偿后,线性度、稳定性和重复性都比较好。
系统具有结构简单、体积小、实时LED显示、带温度补偿、抗干扰性能好等优点。系统的误差主要来自于发射探头发出的超声波是呈喇叭状扩散传播、被测物的表面不光滑且不一定垂直于两探头的轴线而导致所反射回来的超声波也许是从不同点获得,此外电子元器件自身的时延、干扰等也造成一定影响。可以根据具体场合,选择合适功率的探头,以及调整程序中脉冲的频率、宽度和个数等提高精度或测量距离,扩大系统的应用范围。
第六章 问题解决及总结
在实验方案确定之后,我们先买好器件在万用板上面焊接调试电路,成功符合要求之后才做的电路板。在万用板上面实验的时候由于温度测量模块正负反接,导致模块烧毁,但是一开始不知道是什么原因,先是把距离部分程序烧进去,数码管可以显示程序设定的值,但是把温度显示部分程序烧进去数码管不能显示,经过多次检查,确定是温度测量模块有问题,换了一个新的DS18B20模块温度能正常显示。
蜂鸣器报警电路开始用的驱动三极管2N3904,发现NPN三极管电路设计不能报警,后来修改了电路设计,把NPN的2N3904改成PNP的S8550三极管,蜂鸣器能进行正常报警。
在确定万用板符合要求,电路无误之后,进行PCB设计环节,采用的设计软件是Altium Designer 10.0,设计的原理图时发现很多原件的封装都没有,然后查了资料自建封装库。由于是第一次正式的做PCB板,布局布线方面经验不够,导致前期线路交叉打了很多孔,后面做了很多优化把孔的数量减少到正常值。
画好之后联系了城隍庙的商家做板子,4天之后成功拿到板子,进行PCB板的焊接。在PCB焊接完成之后,发现不能烧程序进单片机,经过跟万用板的对比,发现是晶振震荡电路的电容有问题,PCB板设计的封装是贴片电容,万用板用的是瓷片电容,后来改用跟万用板一样的瓷片电容之后,该问题得到解决。
本次设计过程中花时间最多的是软件调试,根据老师提供的资料部分代码写完代码之后,发现温度一直不能正常显示,选用DS18B20的很大一部分原因就是其硬件开销小,但是软件开销较大,程序和硬件都检查了很多遍,最后查了大量资料才知道是温度模块DS18B20的复位函数有问题,DS18B20模块不能正常复位,因此也不能正常输出温度数值。修改时延函数之后问题得到解决。
附件
进度分工表
电路原理图
PCB原理图
程序代码
#include <reg52.h>
#include <intrins.h>
#define ulong unsigned long
#define uchar unsigned char
#define uint unsigned int
data ulong length,speed;
data uchar templ,temph;
sbit wendu = P2^0; //接收温度引脚
sbit fashe = P1^0; //产生脉冲引脚
sbit jshou = P1^1; //接收回波引脚
sbit S1 = P2^1;//led
sbit S2 = P2^3;//led
sbit S3 = P2^5;//led
sbit S4 = P2^7;//led
sbit beep=P1^3; //蜂鸣器
char idata disp [5]={0x00,0x00,0x00,0x00,0x00};
char idata number[5]={0x00,0x00,0x00,0x00,0x00};
uchar code shuma[11]=
{0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba, 0x20,0x28,0x7f}; // 0~9个数字和 —
const unsigned char tabl3[]=
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09}; //查表得温度小数位
void delay( int j)
{
int i;
for(i=0;i<j;i++) ;
}
void delayms(uint ms)
{
uchar a,b;
while(ms--)
{ _nop_();a=2;b=239;
do{
while(--b);
}
while(--a);
}
}
void delay20us()
{
uchar i; _nop_();i=7; while(--i);
}
void rest_ds18b20(void) //DS18B20复位函数
{
char pre=1;
while(pre)
{
while(pre)
{
wendu=1;_nop_();_nop_();
wendu=0;
delay(50);
wendu=1;
delay(6);
pre=wendu;
}
delay(45);
pre=~wendu;
}
}
void w_1byte_ds18b20(uchar value) //向DS18B20写一字节的数据
{
uchar i=0;
for(i=0;i<8;i++)
{
wendu=1;_nop_();_nop_();
wendu=0;_nop_();_nop_();_nop_();_nop_();_nop_();
wendu=value&0x01; //最低位移出
delay(6);
value>>=1;
}
wendu=1;
}
uchar r_1byte_ds18b20(void) //读一个字节
{
uchar i=0;
uchar value = 0;
for (i=0;i<8;i++)
{
value>>=1;
wendu=0;
_nop_();_nop_();_nop_();
wendu=1;
_nop_();_nop_();_nop_();_nop_();
if(wendu==1) value|=0x80;
delay(6);
}
wendu=1;
return value;
}
readtemp_ds18b20() //读取温度
{
rest_ds18b20(); //复位
w_1byte_ds18b20(0xcc); //跳过读序列号的操作
w_1byte_ds18b20(0x44); //启动温度转换
delay(6);
rest_ds18b20();
w_1byte_ds18b20(0xcc); //跳过读序列号的操作
w_1byte_ds18b20(0xbe); //读取温度寄存器
templ=r_1byte_ds18b20(); //温度低8位
temph=r_1byte_ds18b20(); //温度高8位
number[0]=tabl3[templ&0x0f];
number[4]=(((templ&0xf0)>>4)|((temph&0x0f)<<4));
if(number[4]>=-20){speed=319;}
else if(number[4]>=-10){speed=325;}
else if(number[4]>=0){speed=323;}
else if(number[4]>=10){speed=338;}
else if(number[4]>=20){speed=344;}
else if(number[4]>=30){speed=349;}
else if(number[4]>=100){speed=386;}
else {speed=313;}
number[3]=number[4]/100;
number[1]=number[4]%100;
number[2]=number[1]/10;
number[1]=number[1]%10;
}
void Timetojuli(void) //将测量的时间转换为距离
{
disp[4]=length/1000; //m
length=length-disp[4]*1000;
disp[3]=length/100; //dm
length=length-disp[3]*100;
disp[2]=length/10; //cm
length=length-disp[2]*10;
disp[1]=length;//mm
}
wendu_display(void) //温度显示函数
{ int j;
rest_ds18b20();
w_1byte_ds18b20(0xcc);
w_1byte_ds18b20(0x44);
readtemp_ds18b20();
for(j=0;j<5000;j++)
{
P0=shuma[number[0]];
S1=0;
delay20us();
S1=1;
P0=shuma[number[1]]&0xdf;
S2=0;
delay20us();
S2=1;
P0=shuma[number[2]];
S3=0;
delay20us();
S3=1;
}
}
void juli_display(void) // 距离显示函数
{
P0=shuma[disp[1]];
S1=0;
delay20us();
S1=1;
P0=shuma[disp[2]]&0xdf;
S2=0;
delay20us();
S2=1;
P0=shuma[disp[3]];
S3=0;
delay20us();
S3=1;
P0=shuma[disp[4]];
S4=0;
delay20us();
S4=1;
}
float meas()
{
uint time;
TH0=0;
TL0=0;
fashe=1;
delay20us();
fashe=0;
delay20us();
while(!jshou);
TR0=1;
while(jshou);
TR0=0;
time=TH0;
time=(TH0<<8)|TL0;
length = (speed)*time/2000;//计算长度,是扩大1000倍
if(length<=35)length=length;
else if(length<=77)length=length*1.053;
else if(length<=463)length=length*1.08;
else if(length<=790)length=length*1.076;
else if(length<=930)length=length*1.085;
else if(length<=1050)length=length*1.09;
else if(length<=1150)length=length*1.082;
else if(length<=1250)length=length*1.075;
else if(length<=1430)length=length*1.069;
else if(length<=1720)length=length*1.072;
else if(length<=2020)length=length*1.068;
//else if(length<=2310)length=length*1.07;
//else if(length<=2600)length=length*1.077;
else if(length<=2910)length=length*1.065;
else if(length<=3200)length=length*1.066;
else length=length*1.065;
return(length);
}
float disave()
{ uchar i,j;
float disdata[7],t;
for(i=0;i<7;i++)
{
disdata[i]=meas();
delayms(80);
}
for(j=0;j<=6;j++)
{
for(i=0;i<7-j;i++)
{
if(disdata[i]>disdata[i+1])
{
t=disdata[i];
disdata[i]=disdata[i+1];
disdata[i+1]=t;
}
}
}
return(disdata[2]+disdata[3]+disdata[4])/3;
}
//**************************主程序***********************************
void main()
{
TMOD = 0x21; //设CTC1工作于模式2 CTC0工作于模式1
ET0 = 0; //不允许CTC0中断
delay20us();
EA=1; //CPU中断控制位开
ET0=1; //定时器0溢出中断关
TR0=0; //计数器0关
wendu_display();
length=disave();
if(length<4000)
{
Timetojuli(); //更新一次数据
while(1)
{
juli_display();
}
}
else beep=0;
}