超声波测试源码及原理

因为时间原因这里只是贴一下代码,代码里面是有注释的,所以应该是看的懂具体原理的。 

演示网址



总原理



后台原理


前端原理


前端界面演示


电路图


实物图


单片机代码(注意:这里需要引入OLED的头文件,后面会贴源码下载地址)

#include "reg52.h"
#include "oled.h" 
#include"intrins.h" //包涵了_nop_()函数声明
typedef unsigned int unint;
typedef unsigned char unchar;
//TRG 为控制端 sbit TRIG = P2^0; //超声波的 TRIG端 插在了P1.6口 //ECHO 为接收端 sbit ECHO = P2^1; //超声波的 ECHO端 插在了P1.7口 sbit right=P0^0; sbit beep=P2^2; /*还有vcc,gnd 就直接插在了单片机 vcc 和gnd 端口了 *也可以将其插在I/O引脚中 将插 vcc的引脚置高电平,gnd置低电平*/ unchar flag = 0; //标志定时器是否溢出 unint length[10]={0};//用于滤波 unchar issend=0; code unchar wifi[]={'3','0','0','0','a'}; code char tcp[5]={'3','0','0','1','a'}; code char ip[5]={'3','0','0','2','a'}; unchar senddata[5]={'1','0','0','0','a'};
void delayed(unsigned int x); //延时xmS void delay_20us(); // 延时20ms void init_time(); //初始化定时器的函数 void display(int num,position); //数码管显示函数 char changechar(unchar i); int averge();
void delay300ms(void) //误差 -0.000000000068us { unsigned char a,b,c; for(c=157;c>0;c--) for(b=6;b>0;b--) for(a=145;a>0;a--); }
//蜂鸣器报警 void beepsound(){ unint j=5000; while(j--){ if(j%7==0) beep=~beep; }
} //串口发送数据 void Send_Byte(unchar c[])//UART Send a byte { unchar i=0; for(i=0;i<5;i++){ SBUF =c[i]; while(!TI); TI = 0; } } //接受数据 unsigned char UART_Receive_Byte()//UART Receive a byteg { unsigned char dat; issend=1; while(!RI); dat = SBUF; RI = 0; issend=0; return (dat); } unsigned char UART_Receive_Byte1()//UART Receive a byteg { unsigned char dat; unint i=10000; issend=1; while(!RI && i>10){i--;} if(!RI) return ' '; dat = SBUF; RI = 0; issend=0; return (dat); } //显示ip地址 void ipadress(){ unchar ip2[15],i; Send_Byte(ip); // UART_Receive_Byte(); for(i=0;i<15;i++){ ip2[i]=UART_Receive_Byte1(); } for(i=0;i<15;i++){ //Send_Byte(ip2); OLED_ShowChar(i*8,6,ip2[i],16); } } unchar send(int choose){ switch(choose){ //1是查看wifi是否连接 2是tcp 3是ip地址 case 1: Send_Byte(wifi);return UART_Receive_Byte();break; case 2: Send_Byte(tcp);return UART_Receive_Byte();break; default:Send_Byte(senddata);break; } } void timeinit(){ TH0 = 0; //装初值0 TL0 = 0; TF0 = 0; //中断溢出标志位(打开就是需要由硬件使TF0位1) ET0 = 1; //开定时器中断 }
void client(){ int dat; OLED_ShowString(0,0,"wait wifi..",16); //dat=send(1); while(send(1)=='0') delayed(10); OLED_ShowString(0,0," ",16); OLED_ShowString(0,0,"wait tcp..",16); while(send(2)=='0') delayed(10); OLED_ShowString(0,0," ",16); OLED_ShowString(0,0,"get ip..",16); ipadress(); OLED_ShowString(0,0," ",16); OLED_ShowString(0,0,"linkstart!",16); delayed(100); }
void main() { int x; //用到就知道干什么用了 unchar d; int num=0,v=0,vi; int vg[2]={0,0}; unint time_data,out_TH0,out_TL0; init_time(); OLED_Init(); //初始化OLED OLED_Clear(); client(); TRIG = 0; // 先给控制端初始化为0 //默认显示速度距离 OLED_ShowCHinese(0,0,0);//距 OLED_ShowCHinese(16,0,1);//离 OLED_ShowString(32,0,":",16); OLED_ShowString(64,0,"cm",16); OLED_ShowCHinese(0,3,2);//速 OLED_ShowCHinese(16,3,3);//度 OLED_ShowString(32,3,":",16); OLED_ShowString(64,3,"cm/s",16); while(1) { beep=0; right=0; timeinit(); //init_time(); //初始化定时器 flag = 0; //置溢出标志位为0 //控制口发一个10US 以上的高电平 TRIG = 1; delay_20us(); TRIG = 0; //等待接收端出现高电平 while(!ECHO); TR0 = 1; //启动计时器 开始计时 while(ECHO); //等待高电平结束 TR0 = 0; //关闭低电平 out_TH0 = TH0; //取定时器的值 out_TL0 = TL0; out_TH0 <<= 8; //右移8位 time_data = out_TH0 | out_TL0; //合并为16位的值 time_data /= 58; // 微秒/58 = 厘米 /* 为什么微秒/58 = 厘米 * Y米 = (X秒 * 344) 2 * X秒 = (2 * Y米) / 344 * X秒 = 0.0058*Y米 * 厘米 = 微秒/58 */ if(flag == 1) //如果定时器溢出 则超出超声波测量范围 { display(-1,0); right=1; } else { length[num]=time_data; num++; if(num==9){//多次计算取平均值 display(averge(),0); vg[vi]=averge(); vi++; delay300ms(); //delay500ms(); if(vi==2){ if((vg[1]-vg[0])>0){v=vg[1]-vg[0];} else{ v=vg[0]-vg[1];} vi=0; display(v*3,3); } num=0; } } } } void timer0() interrupt 1 //中断函数 { flag=1; //溢出标志位置1
}
void delayed(unsigned int x) //延时xmS { unsigned int i,j; for(i = x; i > 0; i--) { for(j = 113; j >0; j--); } } //定时器初始化 void init_time() { TMOD =0x21; //选择定时器0工作 工作方式为方式1 TH1 = 0xfd;//装初值 TL1 = 0xfd; TR1 = 1;//开启定时器 REN = 1;//允许串行口接受 SM0 = 0;//方式1 SM1 = 1; ES = 1;//串行口中断打开 EA = 1; // 开总中断 } //字符串转换函数 char changechar(unchar i){ switch(i){ case 0: return '0'; case 1: return '1'; case 2: return '2'; case 3: return '3'; case 4: return '4'; case 5: return '5'; case 6: return '6'; case 7: return '7'; case 8: return '8'; case 9: return '9'; }
} void display(int num,position) //显示函数 { unchar t[3],i; if(num == -1) //当超出范围 显示999 { OLED_ShowString(40,0,"999",16); beepsound(); senddata[0]='9'; senddata[1]='9'; senddata[2]='9'; } else //显示到前三个数码管上 因为测距范围为2-400cm 故3位即可 { t[0] = num / 100; //取百位 OLED_ShowChar(40,position,changechar(t[0]),16); t[1]= num/10%10; //取十位 OLED_ShowChar(48,position,changechar(t[1]),16); t[2]= num %10; OLED_ShowChar(56,position,changechar(t[2]),16); } if(position) senddata[0]='2'; else senddata[0]='1'; for(i=0;i<3;i++){ senddata[i+1]=changechar(t[i]); } send(3);
}
//快速求平均值 int averge(){ int max=0,min=900,i,sum=0; for(i=0;i<10;i++){ if(length[i]>max) max=length[i]; if(length[i]<min) min=length[i]; } for(i=0;i<10;i++){ if(length[i]!=max || length[i]!=min) sum+=length[i]; } return sum/8;
} void delay_20us() //延时20us { _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); } void ser() interrupt 4 { if(!issend) RI = 0; }

arduino源码(wifi模块)

#include "ESP8266WiFi.h"
#define AP_SSID "xiaoyou" //这里改成你的wifi名字
#define AP_PSW  "1806040103"//这里改成你的wifi密码
String data;
const uint16_t port = 2347;
const char * host = "120.79.4.151"; // ip or dns
WiFiClient client;//创建一个tcp client连接
int wifista=0,tcpsta=0;
//0.1秒执行这个用于发送数据和其他用法
//要使用Serial1,请调用Serial.begin(baudrate)。代码如下: void setup() { // 这里开始写初始化代码,只会执行一次 Serial.begin(9600); WiFi.mode(WIFI_STA); WiFi.begin(AP_SSID,AP_PSW); WiFi.setAutoConnect(true);//自动连接 WiFi.setAutoReconnect(true);//自动重连 while(WiFi.status() != WL_CONNECTED){ delay(500); } wifista=1; }
void loop() { // Serial.println(String(wifista)); //连接端口 delay(200); if (Serial.available()) { data=Serial.readStringUntil('a'); if(data=="3000"){ Serial.println(String(wifista)); }else if(data=="3001"){ Serial.println(String(tcpsta)); }else if(data=="3002"){ Serial.println(WiFi.localIP()); }else if(data.startsWith("1")){ client.println(data); }else if(data.startsWith("2")){ client.println(data); } } if(!client.connected()){ tcpsta=0; if(!client.connect(host, port)){ delay(2000); return; } } tcpsta=1; }

workman源码

<?php
use WorkermanWorker;
use WorkermanLibTimer;
require_once 'mysql/src/Connection.php';
require_once __DIR__ . '/GlobalData/src/Client.php';
require_once __DIR__ . '/GlobalData/src/Server.php';
require_once __DIR__ . '/Workerman/Autoloader.php';
// 创建一个Worker监听2347端口,不使用任何应用层协议 $tcp_worker = new Worker("tcp://0.0.0.0:2347"); $ws_worker = new Worker("websocket://0.0.0.0:2000");//创建一个websocket
//启动globaldata服务 $global_worker = new GlobalDataServer('0.0.0.0', 2207); // 启动4个进程对外提供服务 $tcp_worker->count = 4; $ws_worker->count = 4; //初始化创建一个globaldata数据 $tcp_worker->onWorkerStart = function() { // 初始化一个全局的global data client global $global; $global = new GlobalDataClient('120.79.4.151:2207'); $global->id=0; $global->v=000; $global->a=000; }; $ws_worker->onWorkerStart = function() { // 初始化一个全局的global data client global $global; $global = new GlobalDataClient('120.79.4.151:2207'); };
$tcp_worker->onConnect = function($connection) { global $db; $db = new WorkermanMySQLConnection('127.0.0.1', '3306', '数据库用户名', '数据库密码', '数据库名字'); echo "new connection from ip " . $connection->getRemoteIp() . " "; $time_interval = 1; $connect_time = time(); // 给connection对象临时添加一个timer_id属性保存定时器id $connection->timer_id = Timer::add($time_interval, function()use($connection, $connect_time) { global $db; global $global; $insert_id = $db->insert('xiaoyou_data')->cols(array( 'distance'=>$global->v, 'speed'=>$global->a, 'time1'=>date("H:i:s") ))->query(); $global->id=$insert_id; }); }; // 连接关闭时,删除对应连接的定时器 $tcp_worker->onClose = function($connection) { // 删除定时器 Timer::del($connection->timer_id); };

// 当客户端发来数据时 $tcp_worker->onMessage = function($connection, $data) { global $global; if($data=="3333 "){$connection->send("3333 ");} //echo $data; if(substr($data,0,1)=="1"){$global->v=substr($data,1,3);$connection->send("ok ");echo $data." ";} if(substr($data,0,1)=="2"){$global->a=substr($data,1,3);$connection->send("ok ");echo $data." ";}
};

$ws_worker->onMessage = function($connection, $data) { global $global; $connection->send($global->v.$global->a.$global->id); };
Worker::runAll();

前端源码

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="utf-8">
    <title>超声波测速</title>
    <!--移动设备优先-->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link href="http://apps.bdimg.com/libs/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="http://apps.bdimg.com/libs/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="font/css/font-awesome.min.css">
    <link rel="stylesheet" href="css/wifi.css" type="text/css"/>
</head>
<body>
<div class="container">
    <div class="page-header">
        <h1>超声波测速显示面板<i  class="fa fa-tachometer fa-1x" ></i>
            <small>电子电路创新大赛作品</small>
        </h1>
    </div>
<div class="panel panel-default"> <div class="panel-body"> <span class="showtext">距离:</span><span class="text1" id="text1">000</span><span class="showtext">cm</span> <div class="progress"> <div id="text3" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> <span class="sr-only">40% 完成</span> </div> </div> </div> </div> <div class="panel panel-default"> <div class="panel-body"> <span class="showtext">速度:</span><span class="text2" id="text2">000</span><span class="showtext">cm/s</span> <div class="progress"> <div id="text4" class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> <span class="sr-only">40% 完成</span> </div> </div> </div> </div>
<div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title"> 实时距离显示 </h3> </div> <div class="panel-body"> <img id="img1" /> </div> </div>
</div> <!--<div id="val"><p id="text1">消息</p></div> -->
<script type="text/javascript"> var wsClient=null; var obj1 = document.getElementById("text1"); var obj2 = document.getElementById("text2"); var obj3 = document.getElementById("text3"); var obj4 = document.getElementById("text4"); var img1 = document.getElementById("img1"); setInterval("senddata()","300"); //每隔0.5s秒执行一次test()函数,执行无数次。 wsClient=new WebSocket('ws://120.79.4.151:2000'); console.log(wsClient); console.log('ws客户端已经成功连接到服务器上');; function senddata(){ wsClient.send(100); wsClient.onmessage = function(e) { obj1.innerHTML=e.data.substring(0,3);//自动截取字符然后修改文本 obj3.style.width=Number(e.data.substring(0,3))/5+'%'; obj2.innerHTML=e.data.substring(3,6); obj4.style.width=Number(e.data.substring(3,6))/5+'%';//自动修改进度条 img1.src='example0.php?id='+e.data.substring(6); console.log('ws客户端收到一个服务器消息:'+e.data); //window.location.href="../wifi/"+e.data;//把数据发给PHP }
}
</script> </body> </html>

jPGraph源码

<?php // content="text/plain; charset=utf-8"
require_once ('jpgraph/jpgraph.php');
require_once ('jpgraph/jpgraph_line.php');
// 创建连接 $conn = new mysqli("127.0.0.1", "用户名", "数据库密码", "数据库名字"); // Check connection if ($conn->connect_error) { return ''; } $ydata = array();
$id=$_GET['id']; if($id==0){ $ydata[0]=0; }else { $id2 = $id - 20; for ($i = 0; $id > $id2; $id--) { $sql = "SELECT * FROM xiaoyou_data WHERE id=$id"; $result = $conn->query($sql); if ($result->num_rows > 0) { // 输出数据 while ($row = $result->fetch_assoc()) { $ydata[$i] = $row["distance"]; }
} else { $ydata[$i] = 0; } $i++; } }
$conn->close(); // Some data
// Create the graph. These two calls are always required $graph = new Graph(350,250); $graph->SetScale('textlin');
// Create the linear plot $lineplot=new LinePlot($ydata); $lineplot->SetColor('blue');
// Add the plot to the graph $graph->Add($lineplot);
// Display the graph $graph->Stroke(); ?>


下面是一些文件的源文件下载地址:

单片机源码

arduino的可以直接复制

workman的也可以直接复制,前提是你需要下载下面这几个组件

前端可以直接复制即可让

jpgraph的可以直接复制,前提是到官网下载核心文件

项目文件下载地址:https://pan.xiaoyou66.com/s/6j2rdkfa