NodeMCU上传HC-SR04+SinricPro代码后出现WDT复位问题求助
HC-SR04 + SinricPro 运动检测NodeMCU异常排查与修复
问题现象
将合并后的代码上传至NodeMCU后,串口监视器输出看门狗复位日志及乱码:
14:55:28.265 -> 14:55:36.662 -> 14:55:36.662 -> ets Jan 8 2013,rst cause:4, boot mode:(3,6) 14:55:36.662 -> 14:55:36.662 -> wdt reset 14:55:36.662 -> load 0x4010f000, len 3424, room 16 14:55:36.662 -> tail 0 14:55:36.662 -> chksum 0x2e 14:55:36.662 -> load 0x3fff20b8, len 40, room 8 14:55:36.662 -> tail 0 14:55:36.662 -> chksum 0x2b 14:55:36.662 -> csum 0x2b 14:55:36.662 -> v00065ae0 14:55:36.662 -> ~ld 14:55:36.727 -> ����n��r��n|�$�$`#��|r�l�o��N�l`��r�d����
问题定位
- 看门狗(WDT)复位:
handleMotionsensor()中的delay(500)和无超时的pulseIn()是阻塞函数,会导致ESP8266主循环长时间无法执行,触发看门狗强制复位。 - 引脚配置错误:NodeMCU需使用GPIO编号而非板上丝印数字,原代码中
trigPin=6、echoPin=5对应错误硬件引脚,导致HC-SR04无法正常工作。 - 逻辑错误:
actualMotionState始终被初始化为false,即使检测到距离小于13cm也未更新,导致SinricPro事件永远无法触发。 - 串口乱码:看门狗复位后的硬件状态异常+波特率同步问题导致输出乱码,修复阻塞问题后可自动解决。
修复后的代码
#ifdef ENABLE_DEBUG #define DEBUG_ESP_PORT Serial #define NODEBUG_WEBSOCKETS #define NDEBUG #endif #include <Arduino.h> #if defined(ESP8266) #include <ESP8266WiFi.h> #elif defined(ESP32) || defined(ARDUINO_ARCH_RP2040) #include <WiFi.h> #endif #include "src/SinricPro.h" #include "src/SinricProMotionsensor.h" // 填写你的WiFi和SinricPro信息 #define WIFI_SSID "你的WiFi名称" #define WIFI_PASS "你的WiFi密码" #define APP_KEY "你的SinricPro APP_KEY" #define APP_SECRET "你的SinricPro APP_SECRET" #define MOTIONSENSOR_ID "你的运动传感器设备ID" #define BAUD_RATE 115200 // NodeMCU正确GPIO引脚(D6=GPIO12,D5=GPIO14) #define trigPin 12 #define echoPin 14 bool lastMotionState = false; unsigned long lastDetectionTime = 0; const unsigned long DETECT_INTERVAL = 500; // 500ms检测一次 const unsigned long PULSE_TIMEOUT = 20000; // 20ms超时,对应最大检测距离~3.4m void handleMotionsensor() { unsigned long currentMillis = millis(); // 非阻塞式检测间隔控制 if (currentMillis - lastDetectionTime < DETECT_INTERVAL) return; lastDetectionTime = currentMillis; long duration; int distance; // HC-SR04标准触发时序 digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // 添加超时的pulseIn,避免无限阻塞 duration = pulseIn(echoPin, HIGH, PULSE_TIMEOUT); if (duration == 0) { distance = 999; // 超时标记为远距离 } else { distance = (duration / 2) / 29.1; } // 正确更新运动状态 bool actualMotionState = (distance < 13); Serial.print("Distance: "); Serial.print(distance); Serial.println(" CM"); // 状态变化时触发SinricPro事件 if (actualMotionState != lastMotionState) { Serial.printf("Motion %s\n", actualMotionState?"detected":"not detected"); lastMotionState = actualMotionState; SinricProMotionsensor &myMotionsensor = SinricPro[MOTIONSENSOR_ID]; bool success = myMotionsensor.sendMotionEvent(actualMotionState); if(!success) { Serial.printf("Failed to send motion event to SinricPro!\n"); } } } void setupWiFi() { Serial.printf("\r\n[Wifi]: Connecting"); #if defined(ESP8266) WiFi.setSleepMode(WIFI_NONE_SLEEP); WiFi.setAutoReconnect(true); #elif defined(ESP32) WiFi.setSleep(false); WiFi.setAutoReconnect(true); #endif WiFi.begin(WIFI_SSID, WIFI_PASS); while (WiFi.status() != WL_CONNECTED) { Serial.printf("."); delay(500); // 短延迟不影响看门狗 } IPAddress localIP = WiFi.localIP(); Serial.printf("connected!\r\n[WiFi]: IP-Address is %d.%d.%d.%d\r\n", localIP[0], localIP[1], localIP[2], localIP[3]); } void setupSinricPro() { SinricProMotionsensor& myMotionsensor = SinricPro[MOTIONSENSOR_ID]; SinricPro.onConnected([](){ Serial.printf("Connected to SinricPro\r\n"); }); SinricPro.onDisconnected([](){ Serial.printf("Disconnected from SinricPro\r\n"); }); SinricPro.begin(APP_KEY, APP_SECRET); } void setup() { Serial.begin(BAUD_RATE); Serial.printf("\r\n\r\n"); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); setupWiFi(); setupSinricPro(); } void loop() { handleMotionsensor(); SinricPro.handle(); }
修复说明
- 引脚修正:将trigPin和echoPin改为NodeMCU对应的GPIO编号,确保硬件连接正确。
- 非阻塞逻辑:用
millis()替代delay()控制检测间隔,给pulseIn()添加超时时间,避免主循环阻塞触发看门狗复位。 - 逻辑修复:正确根据距离值设置
actualMotionState,确保状态变化时能触发SinricPro事件。 - 时序优化:调整HC-SR04的触发时序为标准10us脉冲,提升检测稳定性。
内容的提问来源于stack exchange,提问作者Jayman
相关产品推荐
相关产品推荐

