HC-SR04超声波模块接Arduino:从接线到读数

2026-11-09 20:19:00 26阅读 所属项目:ESP32 开发板
HC-SR04超声波模块与Arduino点亮LCD实时显示测距读数

HC-SR04 大概是所有超声波模块里出现频率最高的一颗:四根引脚、几块钱一颗、量程标称 2cm 到 400cm,标称测距精度可达 3mm。它不需要任何总线协议,靠一个 Trig 触发脉冲和一个 Echo 回波电平就能工作,几乎任何单片机都能驱动。这篇把它的原理、接线、代码和几个容易踩的坑一次讲清楚,代码搬运自 How To Mechatronics 的实测教程,逐字符未改动。

HC-SR04 的引脚与测距原理

模块一共四个引脚:VCC(5V 供电)、Trig(触发)、Echo(回波)、GND。两个金属罐状的部件,一个是 T 发射头,一个是 R 接收头,各对应一片超声波换能器。模块尺寸约 45mm × 20mm × 15mm,板中心距 40mm × 13mm,打安装孔时可以直接按这个尺寸来。

HC-SR04引脚图:VCC、Trig、Echo、GND四个引脚定义

工作过程分四步:Trig 收到 10 微秒高电平后,模块从发射头发出 8 个 40kHz 的超声波脉冲;声波碰到障碍物反射回来,接收头捕捉到回波;Echo 引脚随即输出一段高电平,其宽度等于声波往返的总时间;主控用 pulseIn() 之类的办法量出这个时间,再算出距离。

HC-SR04工作原理示意:发射超声波遇到障碍物反射被接收头捕获

计算公式很简单:距离 = 时间 × 声速 ÷ 2。声速取 340m/s,换算成 0.034cm/微秒,除以 2 是因为声波走了一个来回。

测距计算示意:声速乘以传播时间再除以二得到实际距离

还有一点容易被忽略:发射头和接收头的夹角很小,有效反射窗口其实比较窄,打斜的墙面可能漏测,这点选型一节还会提到。

四根线接 Arduino

接线没有任何难度,按下面这张表接即可:

HC-SR04Arduino Uno
VCC5V
TrigD9(任意数字脚)
EchoD10(任意数字脚)
GNDGND
HC-SR04与Arduino接线图:Trig接9脚、Echo接10脚、VCC接5V、GND接GND

Trig 和 Echo 用哪两个数字脚都行,代码里对应改一下就好。唯一要注意的是供电:模块按 5V 设计,接 3.3V 的板子(比如部分 ESP32 引脚逻辑)时电平匹配要另做处理,Uno 上直接插就行。

测距代码:从 Trig 脉冲到串口读数

核心代码如下,思路是「拉低归零 → 给 10 微秒触发脉冲 → pulseIn 量 Echo 高电平时长 → 换算距离」,完整可烧录:

/*
  Ultrasonic Sensor HC-SR04 and Arduino Tutorial

  by Dejan Nedelkovski,
  www.HowToMechatronics.com

*/
// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
// defines variables
long duration;
int distance;
void setup() {
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  Serial.begin(9600); // Starts the serial communication
}
void loop() {
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration * 0.034 / 2;
  // Prints the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.println(distance);
}

打开串口监视器(波特率 9600),把手掌放在探头前慢慢移动,就能看到 Distance 值实时跟着变。如果一直显示 0,先查 Echo 是否接对——pulseIn 一直等不到上升沿,返回值就是 0。

进阶:LCD 实时显示、NewPing 库与温度补偿

串口看数只能接着电脑玩,想脱离电脑,接一块 LCD1602 就够。原教程用 LiquidCrystal 库把厘米和英寸两行同时打到屏上:Trig 仍接 9、Echo 仍接 10,LCD 数据脚按 rs=1、enable=2、d4 到 d7 接 4 至 7 的顺序初始化,loop 里先照常量出 duration,再用 duration × 0.034 ÷ 2 算厘米、duration × 0.0133 ÷ 2 算英寸,两次 setCursor 分别写进第一行和第二行,每次打印后 delay(10) 给屏留刷新时间。完整代码在原教程页面可整段复制,这里不重复占篇幅。

Arduino驱动LCD1602实时显示HC-SR04测得的厘米与英寸读数

如果项目里传感器多了、不想自己管触发时序,可以直接上 NewPing 库。它把触发和回波读数封装成一行,还内置了防串扰的中值滤波:

#include "NewPing.h"

#define TRIGGER_PIN  9
#define ECHO_PIN     10
#define MAX_DISTANCE 400 // Maximum distance we want to measure (in centimeters).


NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  Serial.begin(9600);
}

void loop() {
  delay(50);                    // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.

  int distance = sonar.ping_cm(); // Send ping, get distance in cm and print result (0 = outside set distance range)

  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println("cm");
}

再较真一点,可以做温度补偿。声速并非恒定 340m/s,而是随温度变化:0°C 约 331.4m/s,30°C 能到 350m/s 左右,温差大时误差肉眼可见。教程里用一颗 DHT22 读环境温度,按 331.4 + 0.6×T(°C)修正声速再算距离,实测精度确实比固定声速好一截:

在HC-SR04基础上增加DHT22温度传感器做声速补偿提高测距精度

选型与使用注意

最后从器件角度给几条实用提醒。第一,标称 3mm 精度是理想条件,实际普通白墙环境下 ±1cm 左右更常见,做避障够用,做精确测量要上 ToF 激光类方案。第二,HC-SR04 的探测波束角约 15 度,软布、海绵这类吸声材料基本测不到,大面积斜面也可能回波丢失,返回 0 要想到这一层。第三,同型号兼容板鱼龙混杂,3.3V 逻辑的 RCWL-9610、防水的一体化 JSN-SR04T 是常见替代,选型时按供电和封装需求挑,别只看名字带 SR04 就下单。第四,两次测量之间至少留 60ms 间隔,间隔太近上一轮回波会串进下一轮,NewPing 示例里的 delay(50) 加上 ping 本身耗时正好在这个量级。

整套东西一颗模块、一块 Uno、四根杜邦线就能跑通,适合作为给机器人加避障感知的第一课。代码里的引脚号、声速系数都留了注释,换成自己的引脚布局改动量很小。


作者:电机传感器师
链接:https://www.aiddithome.com/p/d00fd11c80be.html
本作版权归作者所有,未经允许请勿转载。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
6条评论
电烙铁爱好者
1楼 · 3小时前

请问Trig和Echo能不能接其他引脚?比如11和12,代码里改const int那两行就行了吗?

深圳打工人Alan
2楼 · 3小时前

温度补偿那段很实用,夏天空调房和冬天室温差十几度,固定340算出来确实飘

第三次终于亮了
3楼 · 3小时前

这个模块测软的东西基本没戏,试过对着窗帘一直回0,换成硬纸板立马正常

拆开看看再说
4楼 · 3小时前

pulseIn等不到上升沿返回0这个坑我踩过,Echo线接反了查了一下午,看到这篇直接泪目

修啥都行二哥
5楼 · 3小时前

几块钱的芯片能玩出这么多花样,建议人手一颗

1 2