超声波测试源码及原理


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

演示网址

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

单片机代码(注意:这里需要引入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>

&lt;div class="panel panel-default"&gt;
    &lt;div class="panel-body"&gt;
        &lt;span class="showtext"&gt;距离:&lt;/span&gt;&lt;span class="text1"  id="text1"&gt;000&lt;/span&gt;&lt;span class="showtext"&gt;cm&lt;/span&gt;
        &lt;div class="progress"&gt;
            &lt;div id="text3" class="progress-bar progress-bar-success" role="progressbar"
                 aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"
                 style="width: 0%;"&gt;
                &lt;span class="sr-only"&gt;40% 完成&lt;/span&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;div class="panel panel-default"&gt;
    &lt;div class="panel-body"&gt;
        &lt;span class="showtext"&gt;速度:&lt;/span&gt;&lt;span class="text2" id="text2"&gt;000&lt;/span&gt;&lt;span class="showtext"&gt;cm/s&lt;/span&gt;
        &lt;div class="progress"&gt;
            &lt;div id="text4" class="progress-bar progress-bar-info" role="progressbar"
                 aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"
                 style="width: 0%;"&gt;
                &lt;span class="sr-only"&gt;40% 完成&lt;/span&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;div class="panel panel-default"&gt;
    &lt;div class="panel-heading"&gt;
        &lt;h3 class="panel-title"&gt;
            实时距离显示
        &lt;/h3&gt;
    &lt;/div&gt;
    &lt;div class="panel-body"&gt;
        &lt;img id="img1" /&gt;
    &lt;/div&gt;
&lt;/div&gt;

</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


文章作者: 小游
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小游 !
  目录