超声波测试源码及原理

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

演示网址

总原理
后台原理
前端原理
前端界面演示
电路图
实物图

单片机代码(注意:这里需要引入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 Workerman\Worker;
use Workerman\Lib\Timer;
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 GlobalData\Server('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 \GlobalData\Client('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 \GlobalData\Client('120.79.4.151:2207');
};


$tcp_worker->onConnect = function($connection)
{
    global $db;
    $db = new \Workerman\MySQL\Connection('127.0.0.1', '3306', '数据库用户名', '数据库密码', '数据库名字');
    echo "new connection from ip " . $connection->getRemoteIp() . "\n";
    $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\r"){$connection->send("3333\r");}
    //echo $data;
    if(substr($data,0,1)=="1"){$global->v=substr($data,1,3);$connection->send("ok\r");echo $data."\r";}
    if(substr($data,0,1)=="2"){$global->a=substr($data,1,3);$connection->send("ok\r");echo $data."\r";}

};




$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

点赞
  1. 攻城狮icolf说道:

    知乎来的,坚持下去!

  2. jy说道:

    老哥,坚持下去,五体投地膜拜

  3. Link说道:

    很优秀~~
    坚持下去~~

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像

Title - Artist
0:00