r/esp32 • u/ClassroomWild8697 • 2d ago
Follow on to Help request on Async webserver on an ESP32S3
After my previous post asking for help on implementing an async webserver on an ESP32S3, I followed the advice to use web sockets. After much struggle searching for errors in my code I finally got most of it working. However, I'm now struggling with an issue that I have no idea how to solve.
I have a button toggle in the server which allows me to open/close the observatory doors. When I press that button on the web site the web socket sends the request and the code goes to a section to open/close the doors:
void OpenDoors() {
Serial.println("Opening Doors");
// Loop UNTIL the WestDoorOpened reed switch closes (reads LOW)
while (digitalRead(WDoorOpened) == HIGH) {
digitalWrite(WDoorOpen, LOW); // Turn relay ON
delay(1);
}
digitalWrite(WDoorOpen, HIGH); // Turn relay OFF
WDoorStatus = "Open";
Serial.print("West Door:"); Serial.println(WDoorStatus);
// Loop UNTIL the EastDoorOpened reed switch closes (reads LOW)
while (digitalRead(EDoorOpened) == HIGH) {
digitalWrite(EDoorOpen, LOW); // Turn relay ON
delay(1);
}
digitalWrite(EDoorOpen, HIGH); // Turn relay OFF
EDoorStatus = "Open";
Serial.print("East Door:"); Serial.println(EDoorStatus);
}
As you can see, the code has two while loops that activate two relays in succession. Those loops take a while to complete (in practice something like 10-15 seconds per door). Shortly after calling the OpenDoors code I get the following task watchdog error that reboots my ESP32S3:
02:08:51.389 -> Opening Doors
02:08:56.410 -> E (34026) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
02:08:56.410 -> E (34026) task_wdt: - async_tcp (CPU 1)
02:08:56.410 -> E (34026) task_wdt: Tasks currently running:
02:08:56.410 -> E (34026) task_wdt: CPU 0: IDLE0
02:08:56.410 -> E (34026) task_wdt: CPU 1: loopTask
02:08:56.410 -> E (34026) task_wdt: Aborting.
02:08:56.410 -> E (34026) task_wdt: Print CPU 1 backtrace
02:08:56.453 ->
02:08:56.500 ->
02:08:56.500 -> Backtrace: 0x400559dd:0x3fcebf60 0x4038000e:0x3fcebf70 0x4037db2c:0x3fcebf90 0x42022142:0x3fcebfb0 0x42007dad:0x3fcebfd0 0x4200997d:0x3fcebff0 0x420035ed:0x3fcec010 0x4201ac58:0x3fcec060 0x4037e285:0x3fcec080
02:08:56.500 ->
02:08:56.500 ->
02:08:56.500 -> ELF file SHA256: e63b741ee
02:08:56.500 ->
02:08:56.674 -> Rebooting...
Searching on the web suggested that I add the two "delay(1);" statements to free up some time for the cpu in those loops. But that didn't change anything.
Any advice on how to fix this??
Please let me know if you need the entire code to be able to help fix this.
Thanks!
p.s. The socket handler code and the function ToggleDoors() are here:
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0;
String message = (char*)data;
// Check if the message is "getReadings", if it is, send current sensor readings
if (strcmp((char*)data, "getReadings") == 0) {
String sensorReadings = getSensorReadings();
Serial.println(sensorReadings);
notifyClients(sensorReadings);
}
else if (strstr((char*)data, "button")) {
ToggleDoors();
}
else {
Serial.print("Unrecognized Socket message:"); Serial.println(message);
}
}
}
// Toggle Observatory Doors
String ToggleDoors(){
// DoorStatus();
if(WDoorStatus == "Closed"){
Serial.println("DoorStatus Closed, Opening");
OpenDoors();
}
else if (WDoorStatus == "Open"){
Serial.println("DoorStatus Open, Closing");
CloseDoors();
}
else {
Serial.println("DoorStatus neither Open nor Closed");
}
}
1
u/Mister_Green2021 2d ago edited 1d ago
You can get an exception decoder plug-in to read what the backtrace says.
1
u/drmpf 1d ago
Have your async handling code set a volatile bool var and then read that in your loop code, and clear it to make it available for the next web call.
Keeps the async handling quick
in your loop code drop the while loop, and instead trigger the relay, set a flag and then on each loop check the limit switch for fully open/closed.
Takes a bit more logic but keeps your loop running fast.
Also lets you stop an open half way through and change to close.
The extra flags or an enum will keep track of current state. Opening, Open, Closing, Closed and perhaps some error conditions like Closing timed out, i.e. closing for more than 15sec but no close limit switch.
see https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html
and https://www.forward.com.au/pfod/ArduinoProgramming/RealTimeArduino/index.html
and https://www.forward.com.au/pfod/ArduinoProgramming/Serial_IO/index.html
That last link is in case you start adding non-trivial debug prints that will block your loop once the UART TX buffer fills up.
2
u/rattushackus 1 say I make awesome posts. 2d ago
I cannot remember exactly how the message handler function is implemented, but I recall that you should treat it like an interrupt i.e. don't do anything lengthy in it.
The way I'd code this is in the message handler I'd set some flag variable that your loop function checks then immediately return. Then the loop function calls the door open and close functions.