问题
I am on an Autonomous GPS robot project. When I am running the below code after some time the esp32(devkit v1) reboots and this goes on repeating.
Pause for Startup... 3
Pause for Startup... 2
Pause for Startup... 1
Searching for Satellites
Searching for Satellites
GPS Waypoint 1 Set Waypoint #1: 0.000000 , 0.000000
Waypoint #2: 0.000000 , 0.000000
5 Satellites Acquired10.190620
76.424872
25.190620
47.424872
YOYYYYO
Go to Waypoint
E (98333) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (98333) task_wdt: - async_tcp (CPU 0/1)
E (98333) task_wdt: Tasks currently running:
E (98333) task_wdt: CPU 0: IDLE0
E (98333) task_wdt: CPU 1: async_tcp
E (98333) task_wdt: Aborting.
abort() was called at PC 0x400de07b on core 0
Backtrace: 0x4008cbf8:0x3ffbe170 0x4008ce29:0x3ffbe190 0x400de07b:0x3ffbe1b0 0x40084f01:0x3ffbe1d0 0x40148e07:0x3ffbc0d0 0x400df42b:0x3ffbc0f0 0x4008ab01:0x3ffbc110 0x4008930d:0x3ffbc130
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac
Welcome
Autonmous Mode Initiated...
IP Address: 192.168.1.18
Compass setting done
iam here1
Pause for Startup...
Pause for Startup... 10
Pause for Startup... 9
Pause for Startup... 8
YOYYYYO
Go to Waypoint
Pause for Startup... 7
Pause for Startup... 6
Pause for Startup... 5
Pause for Startup... 4
Pause for Startup... 3
E (10128) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (10128) task_wdt: - async_tcp (CPU 0)
E (10128) task_wdt: Tasks currently running:
E (10128) task_wdt: CPU 0: Tmr Svc
E (10128) task_wdt: CPU 1: IDLE1
E (10128) task_wdt: Aborting.
abort() was called at PC 0x400de07b on core 0
Backtrace: 0x4008cbf8:0x3ffbe170 0x4008ce29:0x3ffbe190 0x400de07b:0x3ffbe1b0 0x40084f01:0x3ffbe1d0 0x4000bfed:0x3ffbd060 0x4008a489:0x3ffbd070 0x400827d1:0x3ffbd090 0x40082843:0x3ffbd0b0 0x4008b825:0x3ffbd0d0 0x4008b924:0x3ffbd100 0x4008930d:0x3ffbd130
Rebooting...
ets Jun 8 2016 00:22:57
This is the msg that appears on the serial monitor. I tried debugging but can't find why this is happening.
The Code is really big, so I have uploaded only a part of it.
// CompaSerial Variables & Setup
HMC5883L compass;
int16_t mx, my, mz; // variables to store x,y,z axis from compass (HMC5883L)
int desired_heading; // initialize variable - stores value for the new desired heading
int compass_heading; // initialize variable - stores value calculated from compass readings
int compass_dev = 5; // the amount of deviation that is allowed in the compass heading - Adjust as Needed
// setting this variable too low will cause the robot to continuously pivot left and right
// setting this variable too high will cause the robot to veer off course
int Heading_A; // variable to store compass heading
int Heading_B; // variable to store compass heading in Opposite direction
int pass = 0; // variable to store which paSerial the robot is on
//*****************************************************************************************************
// GPS Locations
unsigned long Distance_To_Home; // variable for storing the distance to destination
int ac =0; // GPS array counter
int wpCount = 0; // GPS waypoint counter
double Home_LATarray[2]; // variable for storing the destination Latitude - Only Programmed for 5 waypoint
double Home_LONarray[2]; // variable for storing the destination Longitude - up to 50 waypoints
int increment = 0;
//*****************************************************************************************************
// HTML Page
AsyncWebServer server(80);
const char* ssid = "******";
const char* password = "******";
const char* PARAM_INPUT_1 = "input1";
const char* PARAM_INPUT_2 = "input2";
const char* PARAM_INPUT_3 = "input3";
const char* PARAM_INPUT_4 = "input4";
const char* PARAM_COMMIT = "commit";
double lati1;
double logi1;
double lati2;
double logi2;
// HTML web page to handle 4 input fields
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
<h2>Autonomus GPS Robot Car<h2>
<h3> Submit your Destination coordinates</h3>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<style>
a {
border: 10px solid powderblue;
padding: 10px;
color: red;
font-family: verdana;
font-size: 150%;
}
</style>
</head>
<body>
<form action="/get" >
<br>
Waypoint 1 Latitude : <input type="text" name="input1">
<br>
<br>
Waypoint 1 Longitude: <input type="text" name="input2">
<br><br>
<br>
Waypoint 2 Latitude : <input type="text" name="input3">
<br>
<br>
Waypoint 2 Longitude: <input type="text" name="input4">
<br><br>
<input type="submit" value="Submit">
<br>
<br><br>
<br><br>
<a href="/go" >Go to Destination</a>
<br><br> <br><br>
<br><br>
<a href="/clear" > Clear waypoints</a>
</form>
</body>
</html>)rawliteral";
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}
//*****************************************************************************************************
// Extras
#define autopilot 18
void gesturecontroll();
void getGPS();
void getCompass();
void Forward();
void Forward_Meter();
void Reverse();
void LeftTurn();
void RightTurn();
void SlowLeftTurn();
void SlowRightTurn();
void StopCar();
void setWaypoint();
void move();
void Startup();
void goWaypoint();
void clearWaypoints();
int blueToothVal;
int flag=0;
int button;
void setup()
{ Serial.begin(115200); // Serial 0 is for communication with the computer
Serial.println("Welcome");
pinMode(autopilot, INPUT);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
button = digitalRead(autopilot);
if (button == HIGH)
{ flag=15;
Serial.println("Manual Control initated");
Serial.println("ESPNow/Basic/Slave Example");
//Set device in AP mode to begin with
WiFi.mode(WIFI_AP);
// configure device AP mode
// This is the mac address of the Slave in AP Mode
esp_wifi_set_mac(ESP_IF_WIFI_STA, &mac[0]);
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
// Init ESPNow with a fallback logic
if (esp_now_init()!=0)
{
Serial.println("*** ESP_Now init failed");
while(true) {};
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info.
esp_now_register_recv_cb(OnDataRecv);
Serial.print("Aheloiioi"); // the remaining code for above part is not uploaded since when switch is pulled this part of code works perfectly
}
else{
S2.begin(9600, SERIAL_8N1, RXPin, TXPin); // Serial 2 is for GPS communication at 9600 baud - DO NOT MODIFY - Ublox Neo 6m
flag=0;
// pinMode(LED_BUILTIN, OUTPUT); // An LED indicator - Not Used
Serial.println("Autonmous Mode Initiated...");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("WiFi Failed!");
return;
}
Serial.println();
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
CompaSerial////////////////////////////////////////////////////////////////////////////////////
Wire.begin(); // Join I2C bus used for the HMC5883L compass
//compass.init();
compass.begin(); // initialize the compass (HMC5883L)
compass.setRange(HMC5883L_RANGE_1_3GA); // Set measurement range
compass.setMeasurementMode(HMC5883L_CONTINOUS); // Set measurement mode
compass.setDataRate(HMC5883L_DATARATE_30HZ); // Set data rate
compass.setSamples(HMC5883L_SAMPLES_8); // Set number of samples averaged
compass.setOffset(0,0);
Serial.println("Compass setting done");
Startup(); // Run the Startup procedure on power-up one time
}
}
// Main Loop
void loop()
{ button = digitalRead(autopilot);
if (button == HIGH && flag==15)
{
}
else
{ Coordinates();
getGPS(); // Update the GPS location
getCompass(); // Update the CompaSerial Heading
//Ping(); // Use at your own discretion, this is not fully tested
}
}
void Coordinates()
{ Serial.println("i am here1");
// Send web page with input fields to client
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
// Send a GET request to <ESP_IP>/get?input1=<inputMessage>
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
String latitude1;
String latitude1Param;
String longitude1;
String longitude1Param;
String latitude2;
String latitude2Param;
String longitude2;
String longitude2Param;
String commitType;;
if (request->hasParam(PARAM_INPUT_2)||request->hasParam(PARAM_INPUT_1) ) {
// GET input1 value on <ESP_IP>/get?input1=<latitude>
latitude1 = request->getParam(PARAM_INPUT_1)->value();
latitude1Param = PARAM_INPUT_1;
// GET input2 value on <ESP_IP>/get?input2=<longitude>
longitude1 = request->getParam(PARAM_INPUT_2)->value();
longitude1Param = PARAM_INPUT_2;
// GET input3 value on <ESP_IP>/get?input3=<latitude>
latitude2 = request->getParam(PARAM_INPUT_3)->value();
latitude2Param = PARAM_INPUT_3;
// GET input4 value on <ESP_IP>/get?input4=<longitude>
longitude2 = request->getParam(PARAM_INPUT_4)->value();
longitude2Param = PARAM_INPUT_4;
}
else {
latitude1 = "No message sent";
latitude1Param = "none";
longitude1 = "No message sent";
longitude1Param = "none";
latitude2 = "No message sent";
latitude2Param = "none";
longitude2 = "No message sent";
longitude2Param = "none";
}
Serial.println(latitude1);
Serial.println(longitude1);
Serial.println(latitude2);
Serial.println(longitude2);
lati1=(latitude1.toFloat());
logi1=(longitude1.toFloat());
lati2=(latitude2.toFloat());
logi2=(longitude2.toFloat());
//Serial.println(lati,6);
//Serial.println(logi,6);
request->send(200, "text/html", "Command succesfuly sent""<br><a href=\"/\">Return to Home Page</a>");
});
server.on("/go", HTTP_GET, [] (AsyncWebServerRequest *request) {
//logic for go here
Serial.println("YOYYYYO");
goWaypoint();
request->redirect("/");
});
server.on("/clear", HTTP_GET, [] (AsyncWebServerRequest *request) {
//logic for clear here
Serial.println("fdfghgh");
clearWaypoints();
request->redirect("/");
});
server.onNotFound(notFound);
server.begin();
}
void getGPS() // Get Latest GPS coordinates
{ Serial.println("i am here2");
while (S2.available() > 0)
gps.encode(S2.read());
}
// *************************************************************************************************************************************************
void setWaypoint() // Set up to 5 GPS waypoints
{
//if ((wpCount >= 0) && (wpCount < 50))
if (wpCount >= 0)
{
Serial.print("GPS Waypoint ");
Serial.print(wpCount + 1);
Serial.print(" Set ");
Home_LATarray[ac] = lati1 ; // store waypoint in an array
Home_LONarray[ac] = logi1 ; // store waypoint in an array
Home_LATarray[ac] = lati2 ; // store waypoint in an array
Home_LONarray[ac] = logi2 ; // store waypoint in an array
Serial.print("Waypoint #1: ");
Serial.print(Home_LATarray[0],6);
Serial.print(" , ");
Serial.println(Home_LONarray[0],6);
Serial.print("Waypoint #2: ");
Serial.print(Home_LATarray[1],6);
Serial.print(" , ");
Serial.println(Home_LONarray[1],6);
wpCount++; // increment waypoint counter
ac++; // increment array counter
}
else {Serial.print("Waypoints Full");}
}
// *************************************************************************************************************************************************
void clearWaypoints()
{
memset(Home_LATarray, 0, sizeof(Home_LATarray)); // clear the array
memset(Home_LONarray, 0, sizeof(Home_LONarray)); // clear the array
wpCount = 0; // reset increment counter to 0
ac = 0;
Serial.print("GPS Waypoints Cleared"); // display waypoints cleared
}
// *************************************************************************************************************************************************
void getCompass() // get latest compass value
{
Vector norm = compass.readNormalize();
// Calculate heading
float heading = atan2(norm.YAxis, norm.XAxis);
if(heading < 0)
heading += 2 * M_PI;
compass_heading = (int)(heading * 180/M_PI); // aSerialign compass calculation to variable (compass_heading) and convert to integer to remove decimal places
}
void Startup()
{
Serial.println("Pause for Startup... ");
for (int i=10; i >= 1; i--) // Count down for X seconds
{
Serial.print("Pause for Startup... ");
Serial.println(i);
delay(1000); // Delay for X seconds
}
Serial.println("Searching for Satellites ");
Serial.println("Searching for Satellites ");
while (Number_of_SATS <= 4) // Wait until x number of satellites are acquired before starting main loop
{
getGPS(); // Update gps data
Number_of_SATS = (int)(gps.satellites.value()); // Query Tiny GPS for the number of Satellites Acquired
}
setWaypoint(); // set intial waypoint to current location
wpCount = 0; // zero waypoint counter
ac = 0; // zero array counter
Serial.print(Number_of_SATS);
Serial.print(" Satellites Acquired");
}
void goWaypoint()
{
Serial.println("Go to Waypoint");
//Serial.print("Home_Latarray ");
//Serial.print(Home_LATarray[ac],6);
//Serial.print(" ");
//Serial.println(Home_LONarray[ac],6);
//Serial1.print("Distance to Home");
//Serial1.print(Distance_To_Home);
//Serial1.print("ac= ");
//Serial1.print(ac);
while (true)
{ // Start of Go_Home procedure
// bluetooth(); // Run the Bluetooth procedure to see if there is any data being sent via BT
if (blueToothVal == 5){break;} // If a 'Stop' Bluetooth command is received then break from the Loop
getCompass(); // Update Compass heading
getGPS(); // Tiny GPS function that retrieves GPS data - update GPS location// delay time changed from 100 to 10
if (millis() > 5000 && gps.charsProcessed() < 10) // If no Data from GPS within 5 seconds then send error
Serial.println(F("No GPS data: check wiring"));
Distance_To_Home = TinyGPSPlus::distanceBetween(gps.location.lat(),gps.location.lng(),Home_LATarray[ac], Home_LONarray[ac]); //Query Tiny GPS for Distance to Destination
GPS_Course = TinyGPSPlus::courseTo(gps.location.lat(),gps.location.lng(),Home_LATarray[ac],Home_LONarray[ac]); //Query Tiny GPS for Course to Destination
/*
if (Home_LATarray[ac] == 0) {
Serial1.print("End of Waypoints");
StopCar();
break;
}
*/
if (Distance_To_Home == 0) // If the Vehicle has reached it's Destination, then Stop
{
StopCar(); // Stop the robot after each waypoint is reached
Serial.println("You have arrived!"); // Print to Bluetooth device - "You have arrived"
ac++; // increment counter for next waypoint
break; // Break from Go_Home procedure and send control back to the Void Loop
// go to next waypoint
}
if ( abs(GPS_Course - compass_heading) <= 15) // If GPS Course and the Compass Heading are within x degrees of each other then go Forward
// otherwise find the shortest turn radius and turn left or right
{
Forward(); // Go Forward
} else
{
int x = (GPS_Course - 360); // x = the GPS desired heading - 360
int y = (compass_heading - (x)); // y = the Compass heading - x
int z = (y - 360); // z = y - 360
if ((z <= 180) && (z >= 0)) // if z is less than 180 and not a negative value then turn left otherwise turn right
{ SlowLeftTurn(); }
else { SlowRightTurn(); }
}
} // End of While Loop
}
回答1:
wdt
is the watchdog timer. It's a timer that is used to detect whether your code has crashed. If it's not reset periodically it will throw an error and restart the ESP32. The timer needs to be reset frequently.
Notice that the error says that it was the async_tcp
task which was running when the watchdog timer trigger. You're using the AsyncWeb server, which uses async_tcp.
When the async web server gets a page request, it calls your code. You have handlers for individual pages. Those handlers need to treat the calls to them the way we have to deal with loop()
- if you spend 3 seconds or more without returning or calling delay()
or yield()
. This gives the underlying software the chance to reset the watchdog timer.
Review your web page handlers. Look for where you may spend a long time in them.
You'll find that you call goWayPoint()
in your handler for '/go'. It has a loop in it that may block for 5 seconds. 5 seconds is too long - if that loop doesn't return or call delay()
the watchdog timer will fire, which it does.
The easy fix is to add a call to delay()
in the while(true)
loop.
while (true)
{
delay(1);
this will let the underlying code reset the watchdog timer.
That won't help if other parts of your code (getCompass()
, getGPS()
or other things) take too long.
Ultimately you should refactor your code. You're doing too much work in the web server callbacks. That work should be done in independent tasks - perhaps in loop()
. But that's a big project. Adding a call to delay(1)
anywhere in a web server callback that you have a while loop or make take some time to do some processing is clumsy but should solve this problem.
回答2:
Welcome to the String heap fracturing club:
String latitude1;
String latitude1Param;
String longitude1;
String longitude1Param;
String latitude2;
String latitude2Param;
String longitude2;
String longitude2Param;
String commitType;;
in combination with async webserver is a huge problem. I rewrote a ~15.000 lines application to get rid of strings (also in the used libraries) and since then no resets and reboots anymore. Hope this helps you in your project.
Use predifined fixed char arrays they will go to the stack and keep heap corruption low.Use functions like strcpy, strcat, itoa / atoi to build messages or retrieve values.
EDIT: replace String class with fixed char arrays example
char numBuffer [16] ={'\0'} // For 15 chars and the null terminator
char latitude1 [32] ={'\0'} // For 31 chars and the null terminator
.... some code here ....
strcpy (latitude1 , "No values here");
//or
strcpy (latitude1 , "Value 1: ");
itoa (SomeIntDataNumber, numBuffer,10);
strcat (latitude1, numBuffer) // append the converted SomeIntDataNumber
One more thing if you use memset, make sure you do proper memory management, also check the used libraries for heavy use of String class. Some libs work in a static environment quite well, using them in a web context crashes the ESP. I had to ditch some libs or at least rewrite them without String class.
Further reading: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/
Final Tip: Try to commenting out / replacing with dummy chars all appearancies of the String class and try the code again.
来源:https://stackoverflow.com/questions/60667056/task-watchdog-got-triggered-abort-was-called-at-pc-0x400de07b-on-core-0