(6)ESP32+Python 做一个超声波探测器

我们经常在智能小车上都能看到一个长这么样得一个东西。

这个东西就是一个超声波测距模块,一共有4个引脚VCC,Trig,Echo,Gnd。
VCC:接VCC电源,一般都是5V,但是现在市面上也有支持3.3V的
Trig: 给这个引脚输入一个10us的高电平,就可以触发测距。
Echo: 在测距结束时,这个引脚会输出一个高电平。电平的宽度经过计算的后,就是测距的距离
GND:接地
这里有一个计算公式:
测距距离 = (高电平的时间 * 音速【340M/S】/2)
简单的来讲实现原理是当我们需要测试距离时,

  1. 把Trig输入10us的高电平,然后拉低。测距开始。
  2. 当Echo收到发出的信号后,会把引脚的电平拉高。
  3. 计算第一步和第二步的时间差。
  4. 套入公式,计算距离(音速的时间是340米每秒,第一步和第二步的时间是US,所以计算时要用10000计算回来)
    注意,超声波是一种波,并不是百分之百的和下面的图一样,发送的是直线。

在了解好原理后,把传感器和硬件进行连接,然后开始写代码吧。
第一个实现,我们还是采用原生的写法。


from machine import Pin
import utime

class ORGHCSR04:

    trig = None
    echo = None

    def __init__(se
<think>我们正在处理一个关于ESP8266连接超声波传感器(HC-SR04)测距始终显示0的问题。根据用户提供的引用信息,特别是引用[2]和引用[3]中的代码,我们可以分析可能的原因和解决方法。 首先,回顾超声波测距模块HC-SR04的工作原理: 1. 触发引脚(Trig)接收一个至少10微秒的高电平信号。 2. 模块自动发射8个40kHz的超声波脉冲,并检测回波信号。 3. 回波引脚(Echo)会输出一个高电平,其持续时间等于超声波从发射到返回的时间。 4. 距离计算公式为:距离 = (高电平时间 * 声速340m/s) / 2 (单位:米,但通常转换为厘米)。 用户代码(参考引用[3])如下: ```python import machine from machine import Pin import time Trig = Pin(5, Pin.OUT) # 触发引脚 Echo = Pin(4, Pin.IN) # 回波引脚 while True: Trig.value(1) time.sleep_us(20) Trig.value(0) while (Echo.value() == 0): # 如果没有收到信号,再触发一次?这里可能有问题 Trig.value(1) time.sleep_us(20) Trig.value(0) if (Echo.value() == 1): ts = time.ticks_us() while (Echo.value() == 1): pass te = time.ticks_us() tc = te - ts distance = str(int((tc * 0.034) / 2)) print('Distance:', distance, 'cm') ``` 现在,问题是一直显示0。可能的原因及解决方法如下: ### 1. **硬件连接问题** - **原因**:超声波模块的VCC、GND、Trig、Echo与ESP8266连接不正确。 - **解决方法**: - 检查VCC是否接3.3V(虽然HC-SR04通常标称5V,但很多模块在3.3V下也能工作,但需注意有的模块可能需要5V,此时需要电平转换)。 - 检查GND是否共地。 - 检查Trig和Echo引脚是否连接到正确的GPIO引脚(在代码中Trig是GPIO5,Echo是GPIO4,对应NodeMCU的D1和D2)。 - 注意:不同ESP8266开发板的GPIO编号与板载引脚标记可能不同(例如NodeMCU的D4对应GPIO2,D1对应GPIO5,D2对应GPIO4)。请确保物理连接与代码中定义的引脚一致。 ### 2. **模块供电问题** - **原因**:超声波模块供电不足。如果使用ESP8266的3.3V供电,可能不足以驱动超声波模块(尤其是当多个传感器时)。 - **解决方法**:尝试使用外部5V电源给超声波模块供电,同时确保GND与ESP8266共地。注意:Echo引脚返回的是5V信号,不能直接接到ESP8266(3.3V逻辑电平),否则可能损坏ESP8266。因此,需要分压电路(例如两个电阻:1kΩ和2kΩ组成分压器)将Echo引脚电压降至3.3V以下。但有些模块内部已经了电平转换,可以输出3.3V,具体看模块型号。 ### 3. **代码逻辑问题** - **原因**:用户代码中有一个循环等待Echo为0,然后再次触发,这可能导致问题。原版代码应该是发送触发信号后等待Echo引脚变为高电平(即等待回波)。但用户代码在等待Echo为0的过程中又发送了一次触发信号,这可能会干扰正常的测距过程。 - **解决方法**:修改代码,去掉内层的触发。参考标准代码: ```python while True: # 发送触发信号 Trig.value(1) time.sleep_us(20) Trig.value(0) # 等待Echo引脚变为高电平(即开始接收回波) while Echo.value() == 0: pass # 等待直到Echo变高 ts = time.ticks_us() # 记录开始时间 # 等待Echo引脚高电平结束 while Echo.value() == 1: pass te = time.ticks_us() # 记录结束时间 # 计算时间差 tc = te - ts # 计算距离(单位:厘米) distance = (tc * 0.034) / 2 print('Distance: {:.2f} cm'.format(distance)) ``` 注意:原代码中在等待Echo为0的时候又触发了一次,这是不正确的,应该去掉。 ### 4. **超声波模块本身问题** - **原因**:模块可能损坏或者有缺陷(如引用[2]中提到,两个模块中有一个不能正常工作)。 - **解决方法**:尝试更换超声波模块,或者用已知可以工作的模块(如用Arduino测试)来验证模块是否正常。 ### 5. **环境因素** - **原因**:超声波在空旷环境中可能没有回波(比如被测物体太远、太近、或者表面不反射超声波)。 - **解决方法**:确保被测物体在有效范围内(通常HC-SR04的有效距离是2cm-400cm),并且物体表面能够反射超声波(避免太柔软或太小)。 ### 6. **引脚配置问题** - **原因**:引脚配置错误,比如将输出模式用于Echo引脚(应该是输入),或者输入模式用于Trig引脚(应该是输出)。 - **解决方法**:检查引脚初始化代码,确保Trig是输出,Echo是输入。 ### 7. **时间测量问题** - **原因**:如果Echo高电平时间非常短(比如低于测量精度),则计算出的距离可能为0。另外,如果时间差计算溢出(`time.ticks_us()`返回的是微秒计数,可能会循环)也可能导致问题。 - **解决方法**:增加超时判断,避免无限等待。例如,等待Echo变高时设置一个超时时间(如100ms),超过则认为无回波。 ### 改进后的代码示例 结合以上分析,这里提供一个改进的代码版本,包括超时处理: ```python import machine from machine import Pin import time import utime Trig = Pin(5, Pin.OUT) # 触发引脚,例如GPIO5(D1) Echo = Pin(4, Pin.IN) # 回波引脚,例如GPIO4(D2) def measure_distance(): # 发送触发信号 Trig.value(1) utime.sleep_us(20) Trig.value(0) # 等待回波开始(Echo变高),设置超时 timeout = 100000 # 100ms超时(以微秒计) start = utime.ticks_us() while Echo.value() == 0: if utime.ticks_diff(utime.ticks_us(), start) > timeout: return -1 # 超时返回-1 ts = utime.ticks_us() # 回波开始时间 # 等待回波结束(Echo变低),同样设置超时 while Echo.value() == 1: if utime.ticks_diff(utime.ticks_us(), ts) > timeout: return -1 # 超时返回-1 te = utime.ticks_us() # 回波结束时间 # 计算时间差(微秒) tc = te - ts # 计算距离(厘米) distance = (tc * 0.034) / 2 return distance while True: dist = measure_distance() if dist >= 0: print('Distance: {:.2f} cm'.format(dist)) else: print('Measurement timed out') time.sleep(1) # 每秒测量一次 ``` ### 总结 可能的原因按优先级排序: 1. 硬件连接错误(特别是引脚和供电)。 2. 代码逻辑问题(在等待Echo为0时重复触发)。 3. 模块损坏或需要5V供电(以及电平转换)。 4. 环境因素(没有回波信号)。 建议用户先检查硬件连接,然后使用改进后的代码(带超时处理)进行测试。 ### 相关问题 1. 如何为ESP8266的GPIO引脚添加保护电路以防止5V信号损坏? 2. 超声波测距传感器在哪些环境下使用效果不佳? 3. 除了超声波传感器,还有哪些常用的距离测量传感器?</think>### ESP8266超声波测距显示0的可能原因及解决方法 #### 1. **硬件连接问题** - **原因**:引脚连接错误或接触不良是常见原因。HC-SR04模块的VCC、GND、Trig、Echo必须正确连接ESP8266。 - **解决方法**: - 确认接线: - VCC → 3.3V或5V(需电平转换) - GND → GND - Trig → GPIO5(D1) - Echo → GPIO4(D2)[^1][^3] - 使用万用表检测供电电压是否稳定(3.3V-5V) - 检查杜邦线是否松动,建议直接焊接或使用面包板固定 #### 2. **供电不足或电平问题** - **原因**: - ESP8266的3.3V供电可能不足(HC-SR04需5V) - Echo返回5V信号会损坏ESP8266(仅支持3.3V输入) - **解决方法**: - 方案1:使用外部5V电源供电,GND与ESP8266共地 - 方案2:添加电平转换电路(电阻分压): ```plaintext Echo → 1kΩ电阻 → GPIO4 ↓ 2kΩ电阻 → GND ``` - 方案3:更换支持3.3V的超声波模块(如HY-SRF05)[^2] #### 3. **代码逻辑错误** - **问题代码**: ```python while (Echo.value() == 0): # 此循环内重复触发会导致信号混乱 Trig.value(1) # 错误操作 time.sleep_us(20) Trig.value(0) ``` - **修复方案**(参考标准时序): ```python Trig.value(1) time.sleep_us(20) # 维持20μs高电平触发信号 Trig.value(0) # 等待Echo变高(添加超时保护) timeout = 3000 # 3ms超时 start = time.ticks_us() while Echo.value() == 0: if time.ticks_diff(time.ticks_us(), start) > timeout: return 0 # 超时处理 # 测量高电平持续时间 ts = time.ticks_us() while Echo.value() == 1: pass te = time.ticks_us() ``` #### 4. **模块或环境问题** - **原因**: - 模块故障(不同批次质量差异,如引用[2]所述) - 被测物体过近(<2cm)或表面不反射超声波 - 环境噪声干扰 - **解决方法**: - 测试模块:用Arduino或厂家测试板验证模块是否正常[^2] - 调整距离:确保被测物在2-400cm范围内 - 添加延迟:测量间隔≥60ms(防止声波干扰) - 避开强噪声源(如电机、风扇) #### 5. **ESP8266配置问题** - **原因**:GPIO引脚配置错误或电源不稳定 - **解决方法**: - 确认引脚初始化: ```python Trig = Pin(5, Pin.OUT) # GPIO5 = D1 Echo = Pin(4, Pin.IN) # GPIO4 = D2 ``` - 使用独立电源供电(避免USB供电不足) - 添加100μF电容到VCC/GND滤波电源噪声 ### 推荐完整代码 ```python import machine, time Trig = machine.Pin(5, machine.Pin.OUT) # D1 Echo = machine.Pin(4, machine.Pin.IN) # D2 def get_distance(): Trig.value(0) time.sleep_us(5) Trig.value(1) time.sleep_us(20) Trig.value(0) # 等待回波信号(带超时) timeout = 5000 # 5ms超时 start = time.ticks_us() while Echo.value() == 0: if time.ticks_diff(time.ticks_us(), start) > timeout: return -1 # 超时错误 ts = time.ticks_us() while Echo.value() == 1: pass te = time.ticks_us() # 计算距离(单位:厘米) return (te - ts) * 0.034 / 2 while True: dist = get_distance() print("距离:" + ("超范围" if dist<0 else str(round(dist,1)) + "cm")) time.sleep(0.5) # 每次测量间隔≥500ms ``` ### 调试步骤 1. 用万用表检测Trig是否有20μs脉冲 2. 观察Echo引脚是否输出高电平 3. 替换模块测试硬件兼容性 4. 添加串口调试输出时间差`te-ts` > 若以上方法无效,可能是模块与ESP8266不兼容(如早期HC-SR04版本),建议更换模块或使用专用测距芯片如VL53L0X[^1]。 ### 相关问题 1. 如何提高超声波测距在高速场景下的精度? 2. ESP8266的GPIO引脚最大输入电压是多少? 3. 除了分压电阻,还有哪些保护ESP8266 GPIO的方法? 4. 超声波测距与激光测距在物联网应用中的优劣比较?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炒陈饭老司机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值