深色模式
第 10 章:看懂超声波测距代码
本章任务
看懂 HC-SR04 超声波测距的代码——对应第一册第 10 章的实验。这是六个实验里代码最"绕"的一个,但拆开看每一步都很直白。
接线回顾
| HC-SR04 | Pico | 说明 |
|---|---|---|
| VCC | 3V3 (Pin 36) | 3.3V 供电 |
| Trig | GP16 (Pin 21) | 触发信号(输出) |
| Echo | GP17 (Pin 22) | 回波信号(输入,需分压) |
| GND | GND (Pin 23) | 共地 |
Echo 输出 5V 电平,Pico 只耐受 3.3V,所以接线里有分压电阻(Echo → 1kΩ → GP17,GP17 → 2kΩ → GND)。
Mind+ 生成的典型代码
python
from machine import Pin # 引脚控制工具
import time # 时间工具
trig = Pin(16, Pin.OUT) # GP16:触发引脚,输出模式
echo = Pin(17, Pin.IN) # GP17:回波引脚,输入模式
def measure(): # 定义一个叫 measure(测量)的函数
# 第一步:发一个 10 微秒的高电平,通知模块"开始测距"
trig.value(0) # 先确保触发脚是低电平
time.sleep_us(2)
trig.value(1) # 拉高(发信号)
time.sleep_us(10) # 保持 10 微秒
trig.value(0) # 拉低,触发完成
# 第二步:等回波开始,记下开始时刻
while echo.value() == 0: # 只要回波还没来(低电平)……
pass # ……就原地等着
start = time.ticks_us() # 回波开始了!记下这一刻的时间
# 第三步:等回波结束,记下结束时刻
while echo.value() == 1: # 只要回波还在持续(高电平)……
pass # ……继续等
end = time.ticks_us() # 回波结束了!记下这一刻
# 第四步:用"持续时间"算距离
duration = time.ticks_diff(end, start) # 高电平持续了多久(微秒)
distance = duration * 0.0343 / 2 # 换算成厘米
return distance # 把结果交出去
while True: # 主循环:每秒测一次
d = measure() # 调用上面的函数,拿到距离
print(f"距离:{d:.1f} cm") # 打印出来,保留 1 位小数
time.sleep(1) # 等 1 秒再测下一次代码讲解
测距的原理(第一册 10.1):Trig 发信号 → 模块发出超声波 → 波撞到障碍物弹回来 → Echo 脚高电平的持续时间 = 波的往返时间。
代码就是这四步的忠实翻译:
- 触发:
trig拉高 10 微秒——等于对模块喊"开始!" - 等回波开始:第一个
while循环里只有一个pass(什么都不做),就是干等 - 等回波结束:第二个
while同样干等,结束瞬间记下时间 - 算距离:距离 = 时间 × 声速 ÷ 2。除以 2 是因为声波走了"去 + 回"两趟
ticks_us() 是"微秒级秒表",ticks_diff(end, start) 算两个时刻的差。def measure(): 把这一大段打包成一个函数,主循环里一句 measure() 就能测一次——这就是第 6 章说的函数的好处。
运行效果
程序运行后,每秒打印一次当前距离。把手放在传感器前由远及近移动,数值会跟着变小。
常见坑
- 读数始终是 0 或固定值:检查代码里 Trig 和 Echo 的编号有没有写反(Trig=16 是发、Echo=17 是收)
- 程序像"卡住"不打印:两个
while都在等回波,如果接线松了或 Echo 分压没接,就会一直等下去 - 读数忽大忽小:让模块对准平整的墙面测,斜面、海绵、布料会让回波不稳定
想一想
distance = duration * 0.0343 / 2里的/ 2如果去掉,显示的距离会偏大还是偏小?💡 查看答案
偏大,而且是整整一倍。因为声音从传感器出发、撞到物体、再弹回来,走的是"来回"两段路,除以 2 才是单程距离。去掉
/ 2,20cm 会显示成 40cm。找到代码里的
time.sleep(1),改成 0.2 会怎样?💡 查看答案
每秒从测 1 次变成测 5 次,屏幕上的距离刷新更快、跟手更灵敏;但数字也会跳得更快,看起来没那么稳。
