首页 > 其他分享 >基于FPGA的超声波(HC-SR04)测距系统设计---第一版

基于FPGA的超声波(HC-SR04)测距系统设计---第一版

时间:2024-06-19 17:21:12浏览次数:19  
标签:15us SR04 FPGA 高电平 测量 --- 数码管 000 模块

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的超声波(HC-SR04)测距系统设计---第一版

 

功能说明:

 1. 利用HC-SR 04超声波模块进行测距。

 2. 在数码管上面显示测量出来的距离。

 3. 数码管显示精度为cm。 

 4. 测量结果进行滑动均值处理(窗口长度为:4)

 5. 由于HC-SR 04模块限制,测量范围:2cm-400cm,测量频率:                100ms测量一次。

 6. 如果实际距离大于400cm,会出现测量不准确的情况。

 7. 如果测量距离大于400cm,数码管显示E。   

使用平台:本次设计应用Altera的平台设计(芯片:EP4CE10F17C8N)。

仿真平台:Modelsim。

作者QQ:746833924

说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;

 

HC-SR04模块简介:

 

VCC为5V电源;GND为地线;TRIG为触发信号输入;ECHO为回响信号输出。

 

HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达到3mm。

 

基本工作原理:

1. 给TRIG端口一个至少10us的高电平信号(建议给15us)。

2. 模块自动发送8个40Khz的方波,自动检测是否有信号返回(模块自动完成,不需要外部干预)。

3. 有信号返回时,模块会给ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。

 

 

 

测量距离时,要求被测量的物体为一个平面,否则会影响测量结果。

 

模块将声波发出去,到达物体表面,反射回来到模块。所以ECHO输出高电平的时间是测量物体与模块之间声波往返的时间。

 

测量距离=(高电平时间 x 声速(340m/s))/2;(需要注意单位,一般FPGA测量的时间单位为ns)

 

设计思想如下:

 

 

ultrasonic_drive模块负责产生触发trig信号,接收并且判断echo信号高电平的时间长度,然后计算距离,并且将距离换算成为BCD输出。

seven_tube_drive模块负责将距离的BCD码显示出来。

 

ultrasonic_drive模块设计思路:

 

产生trig信号思路:每100ms产生15us的高电平。

a. 计数器记录100ms。

b. 达到100ms后,启动15us计时器。

c. 在启动15us计时器期间,拉高trig信号。

  // 计数器记录100ms。
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      cnt_100ms <= 23'd0;
    else
      if (cnt_100ms < T_100ms - 1'b1)
        cnt_100ms <= cnt_100ms + 1'b1;
      else
        cnt_100ms <= 23'd0;
  end

// 达到100ms后,启动15us计时器。
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      cnt_15us <= 10'd0;
    else
      if (cnt_100ms == T_100ms - 1'b1 && cnt_15us == 10'd0)
        cnt_15us <= cnt_15us + 1'b1;
      else
        if (cnt_15us > 10'd0 && cnt_15us < T_15us)
          cnt_15us <= cnt_15us + 1'b1;
        else
          cnt_15us <= 10'd0;
  end

// 在启动15us计时器期间,拉高trig信号。

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      ultrasonic_trig <= 1'b0;
    else
      if (cnt_15us > 10'd0 && cnt_15us < T_15us)
        ultrasonic_trig <= 1'b1;
      else
        ultrasonic_trig <= 1'b0;
  end

 

记录echo信号的高电平的周期数。

 

a. 高电平期间计数,低电平清零。

b. 下降沿检测。

c. 检测到下降沿进行存储。

 

外部echo信号为异步信号,需要同步处理。并且下图时序也表明在下降沿时,正好可以保存记录的高电平的周期数。

 

 

// 同步
  always @ (posedge clk) echo_r <= ultrasonic_echo;
  always @ (posedge clk) echo_rr <= echo_r;

// 边沿检测  
  always @ (posedge clk) echo_rrr <= echo_rr;
  assign flag_neg = echo_rrr & (~echo_rr);
  assign flag_pos = (~echo_rrr) & echo_rr;
  
// 记录高电平的周期数
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      echo_high_cnt <= 32'd0;
    else
      if (echo_rr == 1'b1)
        echo_high_cnt <= echo_high_cnt + 1'b1;
      else
        echo_high_cnt <= 32'd0;
  end

// 存储记录的周期数
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      echo_high_cnt_0 <= 32'd0;
    else
      if (flag_neg == 1'b1)
        echo_high_cnt_0 <= echo_high_cnt;
      else
        echo_high_cnt_0 <= echo_high_cnt_0;
  end

 

a. 存储四次。

b. 假设最开始为0, 所以和的结果为0;以后都是减去最早的,加上最新的。

c. 和除以四,得到均值

// 存储四次测量的结果
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      echo_high_cnt_0 <= 32'd0;
    else
      if (flag_neg == 1'b1)
        echo_high_cnt_0 <= echo_high_cnt;
      else
        echo_high_cnt_0 <= echo_high_cnt_0;
  end
  
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      echo_high_cnt_1 <= 32'd0;
    else
      if (flag_neg == 1'b1)
        echo_high_cnt_1 <= echo_high_cnt_0;
      else
        echo_high_cnt_1 <= echo_high_cnt_1;
  end
  
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      echo_high_cnt_2 <= 32'd0;
    else
      if (flag_neg == 1'b1)
        echo_high_cnt_2 <= echo_high_cnt_1;
      else
        echo_high_cnt_2 <= echo_high_cnt_2;
  end
  
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      echo_high_cnt_3 <= 32'd0;
    else
      if (flag_neg == 1'b1)
        echo_high_cnt_3 <= echo_high_cnt_2;
      else
        echo_high_cnt_3 <= echo_high_cnt_3;
  end
  
// 默认前四次结果为0,和也为0,所以最新的四次的和计算方式为加上最新的,减去最早缓存的距离。

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      echo_high_cnt_sum <= 32'd0;
    else
      if (flag_neg == 1'b1)
        echo_high_cnt_sum <= echo_high_cnt_sum + echo_high_cnt - echo_high_cnt_3;
      else
        echo_high_cnt_sum <= echo_high_cnt_sum;
  end
  
// 除以4,等于右移两位

  assign result_echo_high_cnt = echo_high_cnt_sum >> 2;

根据均值,计算距离。

 

 计算公式:  result_echo_high_cnt * 20 *340/2/1_000_000_000

 周期为20ns,声速为340m/s,需要换算统一单位为ns

 除以1_000_000_000是将s换位ns,但是结果为m

 

 再将结果乘以100,即:除以10_000_000 则结果为cm。

 最终计算公式:result_echo_high_cnt * 20 *340/2/10_000_000

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      distance <= 32'd0;
    else
      distance <= result_echo_high_cnt * 20 * 340/20_000_000;
  end

    将数字的每一位计算出来(BCD码表示),用于显示。

    测量距离大于400cm,最后一个数码管显示E。

//计算每一个数码管应该亮什么  
//距离大于400cm,数码管最后一个显示E.
// 输出F时,数码管不亮。

  initial show_data = 24'hffffff;
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      show_data <= 24'hffffff;
    else
      if (distance > 400)
        show_data <= 24'hfffffe;
      else begin
        show_data[23:12] <= 12'hfff;
        show_data[11:8] <= distance/100;
        show_data[7:4] <= distance/10 % 10;
        show_data[3:0] <= distance % 10;
      end
  end

 

以上就是ultrasonic_drive的设计原理。

 

七段数码管为普通六位一体的共阳极数码,采用动态驱动的方式,在此不再赘述。


    下板后,我们就可以看到超声波测量的运行情况。

 

 


利用卷尺测量的结果和超声波测量的结果基本相同。
注:测量时,a.测量物体是平面,b.测量时,测量路径上不要有干扰的东西(路径方圆20cm之内不要有东西)。
  讲解和演示视频(链接)如下:
https://www.bilibili.com/video/BV1MS421o7FL/?spm_id_from=333.999.0.0&vd_source=b5405faeab8632f02533bcbfc5e52e55
     本设计所有内容(设计代码、设计工程)链接为:

     

链接:https://pan.baidu.com/s/1BfPVHx_8VSTeebRwxzd61A

提取码:ctqe

 

  本篇内容中有部分资源来源于网络,如有侵权,请联系作者。

 

  如果您觉得本公众号还不错的话,可以推给身边的朋友们,感谢并祝好!

标签:15us,SR04,FPGA,高电平,测量,---,数码管,000,模块
From: https://www.cnblogs.com/fendoudexiaohai/p/18256720

相关文章

  • DevOps学习回顾02-实践的通用路径-需求分析的拆解-CI的理解-质量体系的实践路径
    参考来源:极客时间专栏:DevOps实战笔记,作者:石雪峰课程链接:https://time.geekbang.org/column/intro/235DevOps学习回顾02-实践的通用路径-需求分析的拆解-CI的理解-质量体系的实践路径DevOps实践的通用路径第一步:寻找合适的试点项目一个合适的项目应该具备以下几个特......
  • Boosting Weakly-Supervised Temporal Action Localization with Text Information
    标题:利用文本信息增强弱监督时间动作定位源文链接:https://openaccess.thecvf.com/content/CVPR2023/papers/Li_Boosting_Weakly-Supervised_Temporal_Action_Localization_With_Text_Information_CVPR_2023_paper.pdfhttps://openaccess.thecvf.com/content/CVPR2023/papers/......
  • R语言中的偏最小二乘回归PLS-DA|附代码数据
    原文链接:http://tecdat.cn/?p=8890原文出处:拓端数据部落公众号最近我们被要求撰写关于偏最小二乘回归PLS-DA的研究报告,包括一些图形和统计输出。主成分回归(PCR)的方法本质上是使用第一个方法的普通最小二乘(OLS)拟合来自预测变量的主成分(PC)。这带来许多优点:预测变量的数量实际......
  • 【Ubuntu开发入门之“悟空派wukongpi/香橙派orangepi H3 linux开发②u-boot移植“】
    Ubuntu开发入门之"orangepiH3linux开发@u-boot移植"问题描述解决方法获取u-boot源码编译配置u-boot制作并烧录TF卡结束语郑重声明:本人原创博文,都是实战,均经过实际项目验证出货的转载请标明出处:攻城狮2015Platform:AllwinnerH3OS:Linuxubunt......
  • 内存管理-6-虚拟内存相关结构体
    基于msm-5.4一、structmm_struct1.简介内嵌在task_struct结构中,表示一个进程虚拟地址空间。2.成员介绍//include/linux/mm_types.hstructmm_struct{struct{structvm_area_struct*mmap;/*listofVMAs*/structrb_rootmm_rb;......
  • MBR60200PT-ASEMI逆变箱专用MBR60200PT
    编辑:llMBR60200PT-ASEMI逆变箱专用MBR60200PT型号:MBR60200PT品牌:ASEMI封装:TO-247最大平均正向电流(IF):60A最大循环峰值反向电压(VRRM):200V最大正向电压(VF):0.85V~0.90V工作温度:-40°C~175°C反向恢复时间:5ns芯片个数:2芯片尺寸:72mil引脚数量:3正向浪涌电流(IFMS):500A包装方式:5......
  • MBR60100PT-ASEMI逆变焊机专用MBR60100PT
    编辑:llMBR60100PT-ASEMI逆变焊机专用MBR60100PT型号:MBR60100PT品牌:ASEMI封装:TO-247最大平均正向电流(IF):60A最大循环峰值反向电压(VRRM):100V最大正向电压(VF):0.70V~0.90V工作温度:-65°C~175°C芯片个数:2芯片尺寸:mil正向浪涌电流(IFMS):400AMBR60100PT特性:低正向压降低功率损......
  • nginx增加 nginx-vod-module模块实现MP4视频点播
    一、安装Nginx需要提前以预编译方式安装好Nginx具体安装步骤点击下面链接:预编译方式安装nginx二、下载nginx-vod-module模块nginx-vod-module模块是基于nginx来提供VOD(videoondemand)服务的第三方模块,它支持基于DASH、HDS、HLS、MSS的点播服务搭建。nginx-vod-module下......
  • DeepSeek-Coder-V2: Breaking the Barrier of Closed-Source Models in Code Intellig
    DeepSeek-Coder-V2:BreakingtheBarrierofClosed-SourceModelsinCodeIntelligence相关链接:arxivgithub关键字:开源、代码智能、混合专家模型(MoE)、编程语言支持、上下文长度扩展摘要我们介绍了DeepSeek-Coder-V2,这是一个开源的混合专家(MoE)代码语言模型,其性......
  • mysql-connector-java 驱动jar包下載
    地址MySQL::MySQLDownloads,点击网址,进入mysql官网首页,我们点击downloads(下载)然后将页面往下拉,点击如图所画的选择,进入点击Connector/J,表示的java语言连接的数据库驱动器,如果是Python则选择下面Python为后缀的Connector,同理其他语言则选择对应的即可。因为我用的是Java,......