当前位置:   article > 正文

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

基于fpga超声波测距系统仿真图

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

记录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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

滑动均值滤波(四次平均)。

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;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

根据均值,计算距离。

计算公式: 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

将数字的每一位计算出来(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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

以上就是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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/749775
推荐阅读
相关标签
  

闽ICP备14008679号