Skip to content

Commit f329635

Browse files
committed
feat: use RTOS to run reset button detection on Core 0
Move reset button detection to a separate FreeRTOS task on Core 0: - Main loop (WiFi/HTTP handling) runs on Core 1 uninterrupted - Reset button task runs independently on Core 0 - Use vTaskDelay() instead of delay() to not block other tasks - Use volatile flag wifiResetRequested to communicate between cores - WiFi reset operation still happens on main loop (Core 1) This fixes the issue where delay() in LED/buzzer feedback was blocking the HTTP server, making 192.168.4.1 inaccessible during button press. Changes: - E1001: Convert checkResetButtonFeedback() to resetButtonTask() - E1002: Same conversion - Both: Add xTaskCreatePinnedToCore() in setup() - Both: Add wifiResetRequested handling in loop()
1 parent 247f70b commit f329635

3 files changed

Lines changed: 200 additions & 145 deletions

File tree

arduino/SeeedHADiscovery/examples/reTerminal_E1001_HASubscribe_Display/reTerminal_E1001_HASubscribe_Display.ino

Lines changed: 99 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,13 @@ bool lastHAConnected = false;
163163
bool wifiProvisioningMode = false;
164164

165165
// Reset button state tracking | 重置按钮状态跟踪
166-
uint32_t resetButtonPressTime = 0;
167-
bool resetButtonPressed = false;
168-
bool resetFeedbackGiven = false;
166+
volatile uint32_t resetButtonPressTime = 0;
167+
volatile bool resetButtonPressed = false;
168+
volatile bool resetFeedbackGiven = false;
169+
volatile bool wifiResetRequested = false; // Flag to trigger reset from main loop | 主循环触发重置的标志
170+
171+
// RTOS task handle for reset button | 重置按钮的 RTOS 任务句柄
172+
TaskHandle_t resetButtonTaskHandle = NULL;
169173

170174
// Entity data structure | 实体数据结构
171175
struct EntityDisplay {
@@ -196,88 +200,86 @@ void setStatusLED(bool on) {
196200
}
197201

198202
/**
199-
* Check reset button and handle WiFi reset with visual feedback
200-
* 检查重置按钮并处理 WiFi 重置(带视觉反馈
203+
* Reset button detection task (runs on Core 0)
204+
* 重置按钮检测任务(运行在 Core 0
201205
*
202-
* This function monitors the reset button, provides LED feedback at 6 seconds,
203-
* and triggers WiFi reset when button is released after threshold.
204-
* 此函数监控重置按钮,在 6 秒时提供 LED 反馈
205-
* 并在按钮释放后触发 WiFi 重置
206+
* This task runs independently on Core 0, monitoring the reset button
207+
* without blocking the main loop (which handles WiFi/HTTP on Core 1).
208+
* 此任务独立运行在 Core 0,监控重置按钮
209+
* 不会阻塞主循环(主循环在 Core 1 处理 WiFi/HTTP)
206210
*/
207-
void checkResetButtonFeedback() {
208-
bool currentState = (digitalRead(PIN_RESET_BUTTON) == LOW); // Button pressed when LOW
209-
uint32_t now = millis();
210-
211-
// Button just pressed | 按钮刚被按下
212-
if (currentState && !resetButtonPressed) {
213-
resetButtonPressed = true;
214-
resetButtonPressTime = now;
215-
resetFeedbackGiven = false;
216-
Serial1.println("Reset button pressed...");
217-
}
211+
void resetButtonTask(void* parameter) {
212+
Serial1.println("[RTOS] Reset button task started on Core " + String(xPortGetCoreID()));
218213

219-
// Button held - check for 6 second threshold | 按钮保持按下 - 检查6秒阈值
220-
if (currentState && resetButtonPressed && !resetFeedbackGiven) {
221-
uint32_t holdTime = now - resetButtonPressTime;
214+
while (true) {
215+
bool currentState = (digitalRead(PIN_RESET_BUTTON) == LOW); // Button pressed when LOW
216+
uint32_t now = millis();
222217

223-
if (holdTime >= WIFI_RESET_HOLD_TIME) {
224-
resetFeedbackGiven = true;
225-
Serial1.println();
226-
Serial1.println("=========================================");
227-
Serial1.println(" WiFi Reset threshold reached (6s)!");
228-
Serial1.println(" WiFi 重置阈值已达到(6秒)!");
229-
Serial1.println(" Release button to reset WiFi...");
230-
Serial1.println(" 松开按钮以重置 WiFi...");
231-
Serial1.println("=========================================");
218+
// Button just pressed | 按钮刚被按下
219+
if (currentState && !resetButtonPressed) {
220+
resetButtonPressed = true;
221+
resetButtonPressTime = now;
222+
resetFeedbackGiven = false;
223+
Serial1.println("Reset button pressed...");
224+
}
225+
226+
// Button held - check for 6 second threshold | 按钮保持按下 - 检查6秒阈值
227+
if (currentState && resetButtonPressed && !resetFeedbackGiven) {
228+
uint32_t holdTime = now - resetButtonPressTime;
232229

233-
// Audio + Visual feedback | 声音 + 视觉反馈
234-
// Buzzer alarm sound | 蜂鸣器警报声
235-
for (int i = 0; i < 3; i++) {
236-
tone(PIN_BUZZER, 1500, 100);
230+
if (holdTime >= WIFI_RESET_HOLD_TIME) {
231+
resetFeedbackGiven = true;
232+
Serial1.println();
233+
Serial1.println("=========================================");
234+
Serial1.println(" WiFi Reset threshold reached (6s)!");
235+
Serial1.println(" WiFi 重置阈值已达到(6秒)!");
236+
Serial1.println(" Release button to reset WiFi...");
237+
Serial1.println(" 松开按钮以重置 WiFi...");
238+
Serial1.println("=========================================");
239+
240+
// Audio + Visual feedback (on Core 0, won't block main loop)
241+
// 声音 + 视觉反馈(在 Core 0,不会阻塞主循环)
242+
for (int i = 0; i < 3; i++) {
243+
tone(PIN_BUZZER, 1500, 100);
244+
setStatusLED(true);
245+
vTaskDelay(pdMS_TO_TICKS(100));
246+
tone(PIN_BUZZER, 1000, 100);
247+
setStatusLED(false);
248+
vTaskDelay(pdMS_TO_TICKS(100));
249+
}
237250
setStatusLED(true);
238-
delay(100);
239-
tone(PIN_BUZZER, 1000, 100);
240-
setStatusLED(false);
241-
delay(100);
251+
tone(PIN_BUZZER, 2000, 200);
242252
}
243-
// Keep LED on to indicate ready to reset | 保持 LED 亮起表示准备重置
244-
setStatusLED(true);
245-
tone(PIN_BUZZER, 2000, 200); // Final beep | 最后一声
246253
}
247-
}
248-
249-
// Button released | 按钮释放
250-
if (!currentState && resetButtonPressed) {
251-
uint32_t holdTime = now - resetButtonPressTime;
252-
resetButtonPressed = false;
253254

254-
// If held long enough and feedback was given, trigger WiFi reset
255-
// 如果按住足够长时间并且已给反馈,触发 WiFi 重置
256-
if (resetFeedbackGiven && holdTime >= WIFI_RESET_HOLD_TIME) {
257-
Serial1.println();
258-
Serial1.println("=========================================");
259-
Serial1.println(" WiFi Reset triggered!");
260-
Serial1.println(" WiFi 重置已触发!");
261-
Serial1.println("=========================================");
262-
Serial1.println(" Clearing credentials and restarting...");
263-
Serial1.println(" 正在清除凭据并重启...");
255+
// Button released | 按钮释放
256+
if (!currentState && resetButtonPressed) {
257+
uint32_t holdTime = now - resetButtonPressTime;
258+
resetButtonPressed = false;
264259

265-
// Confirmation beep | 确认蜂鸣
266-
tone(PIN_BUZZER, 800, 500);
267-
setStatusLED(false);
260+
// If held long enough, set flag for main loop to handle reset
261+
// 如果按住足够长,设置标志让主循环处理重置
262+
if (resetFeedbackGiven && holdTime >= WIFI_RESET_HOLD_TIME) {
263+
Serial1.println();
264+
Serial1.println("=========================================");
265+
Serial1.println(" WiFi Reset triggered!");
266+
Serial1.println(" WiFi 重置已触发!");
267+
Serial1.println("=========================================");
268+
269+
tone(PIN_BUZZER, 800, 500);
270+
setStatusLED(false);
271+
272+
// Set flag for main loop (WiFi operations should be on main core)
273+
// 设置标志给主循环(WiFi 操作应在主核心执行)
274+
wifiResetRequested = true;
275+
}
268276

269-
// Clear WiFi credentials and restart
270-
// 清除 WiFi 凭据并重启
271-
ha.clearWiFiCredentials();
272-
Serial1.flush();
273-
delay(500);
274-
ESP.restart();
275-
// Never reaches here | 永远不会到达这里
277+
setStatusLED(false);
278+
resetFeedbackGiven = false;
276279
}
277280

278-
// Turn off LED | 关闭 LED
279-
setStatusLED(false);
280-
resetFeedbackGiven = false;
281+
// Small delay to prevent hogging CPU | 小延时防止占用 CPU
282+
vTaskDelay(pdMS_TO_TICKS(20));
281283
}
282284
}
283285

@@ -809,6 +811,20 @@ void setup() {
809811
pinMode(PIN_RESET_BUTTON, INPUT_PULLUP);
810812
Serial1.println(" - Status LED (GPIO6): Initialized");
811813
Serial1.println(" - Reset Button (GPIO3): Initialized");
814+
Serial1.println(" - Buzzer (GPIO45): Ready");
815+
816+
// Create RTOS task for reset button on Core 0 (main loop runs on Core 1)
817+
// 在 Core 0 创建重置按钮的 RTOS 任务(主循环在 Core 1)
818+
xTaskCreatePinnedToCore(
819+
resetButtonTask, // Task function | 任务函数
820+
"ResetButton", // Task name | 任务名称
821+
4096, // Stack size | 堆栈大小
822+
NULL, // Parameters | 参数
823+
1, // Priority | 优先级
824+
&resetButtonTaskHandle, // Task handle | 任务句柄
825+
0 // Core 0 | 核心 0
826+
);
827+
Serial1.println(" - Reset button task started on Core 0");
812828

813829
// Brief LED blink to indicate boot | 短暂 LED 闪烁指示启动
814830
for (int i = 0; i < 2; i++) {
@@ -978,8 +994,17 @@ void loop() {
978994
// Handle HA communication | 处理 HA 通信
979995
ha.handle();
980996

981-
// Check reset button and provide LED feedback | 检查重置按钮并提供 LED 反馈
982-
checkResetButtonFeedback();
997+
// Check if WiFi reset was requested by the button task (on Core 0)
998+
// 检查按钮任务(Core 0)是否请求了 WiFi 重置
999+
if (wifiResetRequested) {
1000+
wifiResetRequested = false;
1001+
Serial1.println(" Clearing credentials and restarting...");
1002+
Serial1.println(" 正在清除凭据并重启...");
1003+
ha.clearWiFiCredentials();
1004+
Serial1.flush();
1005+
delay(500);
1006+
ESP.restart();
1007+
}
9831008

9841009
// Detect if we entered AP mode due to reset button press
9851010
// 检测是否因按下重置按钮而进入了 AP 模式

0 commit comments

Comments
 (0)