树莓派与HC-SR04超声波测距实战指南 1. 项目概述与硬件准备第一次用树莓派玩超声波测距时我踩了不少坑。HC-SR04这个模块虽然便宜好用但引脚连接和代码逻辑对新手来说还是有点门槛。下面我就用最直白的方式把从硬件连接到代码实现的完整过程梳理一遍。先看硬件清单树莓派任何型号均可我用的是4BHC-SR04超声波模块某宝5块钱包邮母对母杜邦线4根面包板可选方便固定重点说下HC-SR04的四个引脚VCC接5V电源树莓派物理引脚2或4Trig触发信号输入接任意GPIO代码中我用的是BCM 23Echo回波信号输出接任意GPIO代码中我用的是BCM 24GND接地接树莓派物理引脚6/9/14等注意务必确认接线正确我有次把VCC接到3.3V导致测距不稳定后来发现HC-SR04需要5V供电才能达到标称的4米测距范围。2. 开发环境配置2.1 启用GPIO权限先给pi用户GPIO操作权限sudo usermod -a -G gpio pi2.2 安装wiringPi库虽然官方已停止维护但仍是最好用的C语言GPIO库sudo apt-get install wiringpi验证安装gpio -v gpio readall2.3 测试引脚电压用万用表确认5V引脚物理引脚2/4输出4.8-5.2V3.3V引脚物理引脚1/17输出3.2-3.4VGPIO引脚在输出高电平时应有3.3V3. 核心代码实现3.1 测距原理拆解HC-SR04的工作流程给Trig引脚10μs以上高电平模块自动发送8个40kHz超声波脉冲模块检测回波Echo引脚输出高电平高电平持续时间与距离成正比距离计算公式距离(cm) (高电平时间(μs) / 58) 或 距离(cm) (高电平时间(s) × 34000) / 23.2 完整代码实现#include wiringPi.h #include stdio.h #include sys/time.h #define TRIG_PIN 23 // BCM 23, 物理引脚16 #define ECHO_PIN 24 // BCM 24, 物理引脚18 void setup() { wiringPiSetupGpio(); // 使用BCM编号 pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT); digitalWrite(TRIG_PIN, LOW); delay(30); // 模块稳定时间 } float getDistance() { struct timeval start, stop; // 发送触发信号 digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(15); // 实测10μs有时不稳定 digitalWrite(TRIG_PIN, LOW); // 等待回波开始 while(digitalRead(ECHO_PIN) LOW); gettimeofday(start, NULL); // 等待回波结束 while(digitalRead(ECHO_PIN) HIGH); gettimeofday(stop, NULL); // 计算时间差微秒 long elapsed (stop.tv_sec - start.tv_sec) * 1000000 (stop.tv_usec - start.tv_usec); // 计算距离厘米 return (elapsed * 0.034) / 2; // 声速340m/s0.034cm/μs } int main() { setup(); while(1) { float dist getDistance(); if(dist 2 dist 450) { // 有效范围判断 printf(Distance: %.2f cm\n, dist); } else { printf(Out of range\n); } delay(200); // 建议测量间隔≥60ms } return 0; }3.3 关键点解析时间测量使用gettimeofday()而非delayMicroseconds()因为后者会阻塞进程引脚初始化必须设置Trig为输出Echo为输入防抖处理增加15μs触发信号确保稳定有效范围HC-SR04的2-450cm为理论值实际建议在3-400cm使用4. 编译与调试技巧4.1 编译命令gcc -o ultrasonic ultrasonic.c -lwiringPi4.2 常见问题排查现象可能原因解决方案返回0cmEcho未接收到信号检查接线确保VCC接5V数值波动大电源干扰给VCC和GND加104电容固定值28cm超出量程检查物体是否在有效距离内段错误GPIO权限不足使用sudo运行或配置用户组4.3 校准技巧在20cm距离放置标准物体记录10次测量值计算平均值修改公式中的声速系数0.034我的校准值通常是0.0335-0.0345之间5. 进阶优化方案5.1 多采样滤波#define SAMPLE_TIMES 5 float getFilteredDistance() { float sum 0; for(int i0; iSAMPLE_TIMES; i) { sum getDistance(); delay(10); } return sum / SAMPLE_TIMES; }5.2 温度补偿声速随温度变化float getTemperatureCompensatedDistance(float temp) { float speed 331.4 0.6 * temp; // m/s float dist getDistance(); return dist * 340 / speed; }5.3 中断方式优化避免忙等待void echoInterrupt() { static struct timeval start; if(digitalRead(ECHO_PIN) HIGH) { gettimeofday(start, NULL); } else { gettimeofday(stop, NULL); // 计算距离... } } // 在setup中添加 wiringPiISR(ECHO_PIN, INT_EDGE_BOTH, echoInterrupt);6. 项目扩展思路结合OLED显示实时距离添加报警功能距离小于阈值触发蜂鸣器通过WebSocket实现远程监控构建三维扫描系统配合舵机实际测试中发现在室内环境下HC-SR04在30-200cm范围内精度可达±0.5cm但潮湿环境会影响声速导致误差增大。建议在代码中加入环境湿度补偿系数这对需要高精度的应用场景尤为重要。