NodeMCU ESP8266 Alexa控制GPIO无响应且触发Soft WDT Reset问题
问题背景
这段代码用于通过Alexa控制继电器,进而操控医疗椅的从属遥控器,基于ESP8266的Alexa控制示例开发,已安装Arduino IDE的ESP8266插件。
问题现象
代码可正常编译、连接WiFi,也能响应Alexa指令"recline on"(串口输出附后),但GPIO05(或其他引脚)状态无变化;接收指令2秒后触发Soft WDT Reset,设备断开网络。需求是让GPIO05保持高电平11秒,使椅子回到指定位置。
已尝试操作
- 更换过不同GPIO引脚测试
- 在3块同型号ESP8266板上测试,结果一致
- 目前未连接继电器,仅做调试,后续继电器将使用独立电源
代码
#include <Arduino.h> #include <ESP8266WiFi.h> // #define RF_RECEIVER 5 // Assign relay inputs from ESP8266 board GPIO's #define RELAY_PIN_1 5 //GPIO05 labeled D1 on NodeMCU 1.0 ESP-12E board #include "fauxmoESP.h" #define SERIAL_BAUDRATE 9600 #define ssid "************" #define password "************" WiFiClient client; // Assign Alexa 'commands' to ESP8266 board GPIO's #define RECLINE "recline" fauxmoESP fauxmo; /* * Connect controller to WiFi */ void connectToWiFi() { //Connect to WiFi Network Serial.println(); Serial.println(); Serial.print("Connecting to WiFi"); Serial.println("..."); WiFi.begin(ssid, password); int retries = 0; while ((WiFi.status() != WL_CONNECTED) && (retries < 15)) { retries++; delay(500); Serial.print("."); } if (retries > 14) { Serial.println(F("WiFi connection FAILED")); } if (WiFi.status() == WL_CONNECTED) { Serial.println(F("WiFi connected!")); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } Serial.println(F("Setup ready")); } void setup() { // Init serial port and clean garbage Serial.begin(SERIAL_BAUDRATE); Serial.println(); // Wi-Fi connection connectToWiFi(); //pinMode(RELAY_PIN_1, OUTPUT); digitalWrite(RELAY_PIN_1, HIGH); //Set remote commands to LOW ("OFF") position for safety // By default, fauxmoESP creates it's own webserver on the defined port // The TCP port must be 80 for gen3 devices (default is 1901) // This has to be done before the call to enable() fauxmo.createServer(true); // not needed, this is the default value fauxmo.setPort(80); // This is required for gen3 devices // You have to call enable(true) once you have a WiFi connection // You can enable or disable the library at any moment // Disabling it will prevent the devices from being discovered and switched fauxmo.enable(true); // You can use different ways to invoke alexa to modify the devices state: // "Alexa, turn lamp two on" // Add virtual devices fauxmo.addDevice(RECLINE); fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state, unsigned char value) { // Callback when a command from Alexa is received. // You can use device_id or device_name to choose the element to perform an action onto (relay, LED,...) // State is a boolean (ON/OFF) and value a number from 0 to 255 (if you say "set kitchen light to 50%" you will receive a 128 here). // Just remember not to delay too much here, this is a callback, exit as soon as possible. // If you have to do something more involved here set a flag and process it in your main loop. Serial.printf("[MAIN] Device #%d (%s) state: %s value: %d\n", device_id, device_name, state ? "ON" : "OFF", value); if ( (strcmp(device_name, RECLINE) == 0) ) { // this just sets a variable that the main loop() does something about Serial.println("RELAY 1 switched by Alexa"); digitalWrite(RELAY_PIN_1, HIGH); delay(11000); // turn on for 11 seconds Serial.println("RELAY_PIN_1, LOW"); } }); } void loop() { fauxmo.handle(); }
串口输出
Serial Monitor Output: 22:03:59.655 -> Connecting to WiFi... 22:04:00.255 -> ...........WiFi connected! 22:04:06.003 -> IP address: 22:04:06.003 -> 192.168.1.208 22:04:06.003 -> Setup ready 22:13:37.602 -> [MAIN] Device #0 (recline) state: ON value: 255 22:13:37.686 -> RELAY 1 switched by Alexa 22:13:40.469 -> 22:13:40.469 -> --------------- CUT HERE FOR EXCEPTION DECODER --------------- 22:13:40.532 -> 22:13:40.532 -> Soft WDT reset 22:13:40.532 -> 22:13:40.564 -> Exception (4): 22:13:40.564 -> epc1=0x40105d12 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000 22:13:40.661 -> 22:13:40.661 -> >>>stack>>> 22:13:40.661 -> 22:13:40.661 -> ctx: sys 22:13:40.693 -> sp: 3fffeaf0 end: 3fffffb0 offset: 0160 22:13:40.725 -> 3fffec50: 00000000 0008dd1d 40205ecc 00001fcd 22:13:40.789 -> 3fffec60: 3ffee8e4 0008dd1d 00002af8 00002af8 REPEATS MANY MANY TIMES....
解决方案
问题根源
- 引脚无反应:代码中
pinMode(RELAY_PIN_1, OUTPUT);被注释,GPIO5未配置为输出模式,导致digitalWrite无法改变引脚状态。 - Soft WDT Reset:在fauxmoESP的回调函数中直接调用
delay(11000),阻塞了ESP8266的系统任务(包括WiFi心跳、看门狗喂狗),触发看门狗超时复位。回调函数要求快速执行,不能做长时间阻塞操作。
修复代码
#include <Arduino.h> #include <ESP8266WiFi.h> #include "fauxmoESP.h" #define RELAY_PIN_1 5 // GPIO05对应NodeMCU 1.0的D1引脚 #define SERIAL_BAUDRATE 9600 #define ssid "************" #define password "************" #define RECLINE "recline" fauxmoESP fauxmo; bool triggerRecline = false; unsigned long reclineStartTime = 0; const unsigned long RECLINE_DURATION = 11000; // 11秒 void connectToWiFi() { Serial.println(); Serial.println(); Serial.print("Connecting to WiFi..."); WiFi.begin(ssid, password); int retries = 0; while ((WiFi.status() != WL_CONNECTED) && (retries < 15)) { retries++; delay(500); Serial.print("."); } if (retries > 14) { Serial.println(F("WiFi connection FAILED")); } if (WiFi.status() == WL_CONNECTED) { Serial.println(F("WiFi connected!")); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } Serial.println(F("Setup ready")); } void setup() { Serial.begin(SERIAL_BAUDRATE); Serial.println(); connectToWiFi(); // 配置引脚为输出模式 pinMode(RELAY_PIN_1, OUTPUT); digitalWrite(RELAY_PIN_1, LOW); // 初始设为低电平(安全状态) fauxmo.setPort(80); fauxmo.enable(true); fauxmo.addDevice(RECLINE); fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state, unsigned char value) { Serial.printf("[MAIN] Device #%d (%s) state: %s value: %d\n", device_id, device_name, state ? "ON" : "OFF", value); if (strcmp(device_name, RECLINE) == 0 && state) { Serial.println("RELAY 1 triggered by Alexa"); triggerRecline = true; // 设置标志位,由主循环处理延时逻辑 } }); } void loop() { fauxmo.handle(); // 主循环中处理延时逻辑,避免阻塞回调函数 if (triggerRecline) { if (reclineStartTime == 0) { reclineStartTime = millis(); digitalWrite(RELAY_PIN_1, HIGH); // 引脚设为高电平 Serial.println("RELAY_PIN_1 set to HIGH"); } else if (millis() - reclineStartTime >= RECLINE_DURATION) { digitalWrite(RELAY_PIN_1, LOW); // 时间到,引脚设为低电平 Serial.println("RELAY_PIN_1 set to LOW"); triggerRecline = false; reclineStartTime = 0; } } }
修复说明
- 引脚模式修复:取消
pinMode(RELAY_PIN_1, OUTPUT);的注释,确保GPIO5被配置为输出模式,让digitalWrite生效。 - 避免阻塞回调:用标志位
triggerRecline和时间戳reclineStartTime替代回调中的delay,将延时逻辑放到loop()中处理,保证fauxmo.handle()能持续执行,维持WiFi连接并喂看门狗。 - 初始状态优化:将初始引脚状态设为低电平,符合安全逻辑,避免上电误触发。
内容的提问来源于stack exchange,提问作者Vin
相关产品推荐
相关产品推荐

