ESP32连接WiFi时HC-SR04传感器读数异常问题求助
ESP32开启WiFi后HC-SR04传感器读数不稳定问题
我正在开发一个ESP32连接Web服务器并上传HC-SR04超声波传感器数据的项目。单独测试传感器时(代码如下),读数完全正常:
/* * HC-SR04 example sketch */ const int trigPin = 4; const int echoPin = 2; const int ledPin = 0; bool ledState = false; float duration, distance; void setup() { pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(ledPin, OUTPUT); Serial.begin(115200); } void loop() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = (duration*.0343)/2; if (distance < 50 && !ledState){ Serial.println("ON"); ledState = true; digitalWrite(ledPin, HIGH); } else if (distance > 50 && ledState){ Serial.println("OFF"); ledState = false; digitalWrite(ledPin, LOW); } Serial.print("Distance: "); Serial.println(distance); delay(2000); }
但添加WiFi连接后(代码如下),传感器读数变得毫无意义且不稳定,最终项目中也出现同样问题:
/* * HC-SR04 example sketch * * by Isaac100 */ #include <WiFi.h> const int trigPin = 4; const int echoPin = 2; const int ledPin = 0; bool ledState = false; // WIFI LOGIN const char* ssid = "**"; const char* password = "**"; float duration, distance; void setup() { pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(ledPin, OUTPUT); WiFi.begin(ssid, password); Serial.begin(115200); } void loop() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = (duration*.0343)/2; if (distance < 50 && !ledState){ Serial.println("ON"); ledState = true; digitalWrite(ledPin, HIGH); } else if (distance > 50 && ledState){ Serial.println("OFF"); ledState = false; digitalWrite(ledPin, LOW); } Serial.print("Distance: "); Serial.println(distance); delay(2000); }
已用万用表检测供电电压,两种情况电压一致,暂不认为是WiFi信号干扰导致。请问问题可能出在哪里?
可能的原因及解决方法
1. WiFi启动导致的电源波动
ESP32在连接WiFi时会产生瞬间电流尖峰,虽然万用表测得的是平均电压,但这种尖峰会导致HC-SR04的供电不稳定,进而影响传感器的信号输出。
- 解决方法:
- 在HC-SR04的VCC与GND引脚之间并联一个100uF电解电容和一个100nF陶瓷电容,用于滤波稳压;
- 条件允许的话,给传感器单独使用一个5V电源模块供电,避免与ESP32共享电源。
2. pulseIn函数受系统任务干扰
ESP32开启WiFi后,后台会运行WiFi维护等任务,这些任务会抢占CPU时间。而pulseIn是阻塞式函数,依赖精确的时序捕获脉冲,一旦CPU被抢占,就会导致脉冲测量不准确。
- 解决方法:改用中断+定时器的方式测量脉冲宽度,示例代码如下:
#include <WiFi.h> const int trigPin = 4; const int echoPin = 2; const int ledPin = 0; bool ledState = false; const char* ssid = "**"; const char* password = "**"; volatile uint32_t pulseStart = 0; volatile uint32_t pulseEnd = 0; volatile bool pulseCaptured = false; void IRAM_ATTR echoInterrupt() { if (digitalRead(echoPin) == HIGH) { pulseStart = micros(); } else { pulseEnd = micros(); pulseCaptured = true; } } void setup() { pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(ledPin, OUTPUT); attachInterrupt(digitalPinToInterrupt(echoPin), echoInterrupt, CHANGE); WiFi.begin(ssid, password); Serial.begin(115200); } void loop() { // 触发传感器 digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // 等待脉冲捕获完成 unsigned long timeout = millis(); while (!pulseCaptured && (millis() - timeout) < 100) { yield(); // 让出CPU给后台任务,避免WiFi断开 } if (pulseCaptured) { float duration = pulseEnd - pulseStart; float distance = (duration * 0.0343) / 2; if (distance < 50 && !ledState){ Serial.println("ON"); ledState = true; digitalWrite(ledPin, HIGH); } else if (distance > 50 && ledState){ Serial.println("OFF"); ledState = false; digitalWrite(ledPin, LOW); } Serial.print("Distance: "); Serial.println(distance); pulseCaptured = false; // 重置捕获标记 } else { Serial.println("Timeout: No pulse detected"); } delay(2000); }
注意:IRAM_ATTR修饰中断函数,确保函数存放在IRAM中,避免WiFi运行时的Flash访问冲突;yield()函数用于在等待时让出CPU,保证WiFi连接稳定。
3. 引脚功能冲突
虽然GPIO4和GPIO2通常可以正常使用,但GPIO2是ESP32的Boot引脚,部分开发板在启动时会对该引脚有操作,可能影响后续的输入捕获。
- 解决方法:更换传感器引脚,比如将trig改为GPIO14,echo改为GPIO15,重新测试。
4. 信号传输干扰
即使排除了WiFi直接干扰,传感器的echo信号线如果没有屏蔽,也可能受到ESP32其他电路的干扰。
- 解决方法:给echo引脚的连接线添加屏蔽层,屏蔽层一端连接到GND;同时尽量缩短传感器与ESP32之间的连线长度。
内容的提问来源于stack exchange,提问作者Pinguiz
相关产品推荐
相关产品推荐

