TheAngryCat
TheAngryCat

Reputation: 31

Guru Meditation Error: Core 1 Panic'ed (Load Prohibited) on ESP32

So I was trying to create a webserver for lighting up multiple LEDs with an ESP32. The server would send a GET request when a button was held down. This worked previously with only one LED and one button on the HTML page. This code is that, just with more buttons and variables. However, when I upload it to the ESP32 and open Serial Window, I get this:

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:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x40081041  PS      : 0x00060330  A0      : 0x800d1222  A1      : 0x3ffb1f40  
A2      : 0x00000004  A3      : 0x00000002  A4      : 0x0800001c  A5      : 0x00000003  
A6      : 0x00000003  A7      : 0x00000000  A8      : 0x3f401e08  A9      : 0xffffffff  
A10     : 0xff4e0000  A11     : 0x00000048  A12     : 0x08000000  A13     : 0x00000003  
A14     : 0xffffffff  A15     : 0x00000000  SAR     : 0x0000001a  EXCCAUSE: 0x0000001c  
EXCVADDR: 0xff4e0000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000  
ELF file SHA256: 0000000000000000
Backtrace: 0x40081041:0x3ffb1f40 0x400d121f:0x3ffb1f60 0x400dc8f6:0x3ffb1fb0 0x40089a52:0x3ffb1fd0
Rebooting...

I don't know what this means or what I've done wrong. I've tried:

1 - minimizing the variables (adding unsigned, const, etc. to the prefix of variables)

2 - putting the variables into a local function's scope

Could somebody please help? It would be very much appreciated if you did. (I'm totally new to Arduino programming so I wouldn't know what to do). Here's the code:

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoOTA.h>

// Replace with your network credentials
const char* ssid = "SSID_HERE";
const char* password = "PASSWORD_HERE";


const unsigned int outputfw = 2;
const unsigned int outputlt = 4;
const unsigned int outputrt = 7;
const unsigned int outputbw = 6;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    h2 {font-size: 3.0rem;}
    p {font-size: 3.0rem;}
    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
    .switch {position: relative; display: inline-block; width: 120px; height: 68px} 
    .switch input {display: none}
    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
    .slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
    input:checked+.slider {background-color: #2196F3}
    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
  </style>
</head>
<body>
  <h2>ESP Web Server</h2>
  %BUTTONPLACEHOLDER%
<script>function toggleCheckbox(state, dir) {
  console.log("Mouse is ")
  console.log(state)
  var xhr = new XMLHttpRequest();
  if(state){ xhr.open("GET", "/update?" + dir + "=" + state, true); }
  else { xhr.open("GET", "/update?" + dir + "=" + state, true); }
  xhr.send();
}

document.getElementById("fw").addEventListener("mousedown", function(event) {
    toggleCheckbox(true, "fw");
    console.log("mouse down.f");
}, false);
document.getElementById("fw").addEventListener("mouseup", function(event) {
    toggleCheckbox(false, "fw");
    console.log("mouse up.f")
}, false);
document.getElementById("bw").addEventListener("mousedown", function(event) {
    toggleCheckbox(true, "bw");
    console.log("mouse down.b");
}, false);
document.getElementById("bw").addEventListener("mouseup", function(event) {
    toggleCheckbox(false, "bw");
    console.log("mouse up.b")
}, false);
document.getElementById("lt").addEventListener("mousedown", function(event) {
    toggleCheckbox(true, "lt");
    console.log("mouse down.l");
}, false);
document.getElementById("lt").addEventListener("mouseup", function(event) {
    toggleCheckbox(false, "lt");
    console.log("mouse up.l")
}, false);
document.getElementById("rt").addEventListener("mousedown", function(event) {
    toggleCheckbox(true, "rt");
    console.log("mouse down.r");
}, false);
document.getElementById("rt").addEventListener("mouseup", function(event) {
    toggleCheckbox(false, "rt");
    console.log("mouse up.r")
}, false);

</script>
</body>
</html>
)rawliteral";

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if(var == "BUTTONPLACEHOLDER"){
    String buttons;
    String outputStateValue = outputState();
    //buttons+= "<h4>Output - GPIO 2 - State <span id=\"outputState\"></span></h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label>";
    buttons = "<h4>output button gpio5 - <span id=\"outputState\"></span></h4><button id=\"fw\">forward</button><br><button id=\"lt\">left</button><button id=\"bw\">backward</button><button id=\"rt\">right</button>";
    return buttons;
  }
  return String();
}

String outputState(){
  if(digitalRead(outputfw)){
    return "checked";
  }
  else {
    return "";
  }
  return "";
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  
  pinMode(outputfw, OUTPUT);
  pinMode(outputbw, OUTPUT);
  pinMode(outputlt, OUTPUT);
  pinMode(outputrt, OUTPUT);
  digitalWrite(outputfw, LOW);
  digitalWrite(outputbw, LOW);
  digitalWrite(outputlt, LOW);
  digitalWrite(outputrt, LOW);
//  pinMode(buttonPin, INPUT);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());
  ArduinoOTA.begin();

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Send a GET request to <ESP_IP>/update?<direction>=<inputMessage>
  server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
    int ledState1 = LOW;          // the current state of the output pin
  int ledState2 = LOW;
  int ledState3 = LOW;
  int ledState4 = LOW;
    String inputMessage;
    String inputParam;
    const char PARAM_INPUT_1[] = "fw";
const char PARAM_INPUT_2[] = "bw";
const char PARAM_INPUT_3[] = "lt";
const char PARAM_INPUT_4[] = "rt";

    // GET input1 value on <ESP_IP>/update?state=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1)) {
      inputMessage = request->getParam(PARAM_INPUT_1)->value();
      inputParam = PARAM_INPUT_1;
      digitalWrite(outputfw, inputMessage.toInt());
      ledState1 = !ledState1;
    }
    else if (request->hasParam(PARAM_INPUT_2)) {
      inputMessage = request->getParam(PARAM_INPUT_2)->value();
      inputParam = PARAM_INPUT_2;
      digitalWrite(outputbw, inputMessage.toInt());
      ledState2 = !ledState2;
    }
    else if (request->hasParam(PARAM_INPUT_3)) {
      inputMessage = request->getParam(PARAM_INPUT_3)->value();
      inputParam = PARAM_INPUT_3;
      digitalWrite(outputlt, inputMessage.toInt());
      ledState3 = !ledState3;
    }
    if (request->hasParam(PARAM_INPUT_4)) {
      inputMessage = request->getParam(PARAM_INPUT_4)->value();
      inputParam = PARAM_INPUT_4;
      digitalWrite(outputrt, inputMessage.toInt());
      ledState4 = !ledState4;
    }
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.println(inputMessage);
    request->send(200, "text/plain", "OK");
  });

  // Send a GET request to <ESP_IP>/state
  server.on("/state", HTTP_GET, [] (AsyncWebServerRequest *request) {
    request->send(200, "text/plain", String(digitalRead(outputfw)).c_str());
  });
  // Start server
  server.begin();
}
  
void loop() {
  ArduinoOTA.handle();
  delay(2);}

Upvotes: 2

Views: 6650

Answers (1)

romkey
romkey

Reputation: 7054

You're using GPIO pins that are connected to the ESP32's flash chip. When you reprogram those with pinMode() you interfere with the ESP32's ability to read and write flash storage and it crashes.

const unsigned int outputfw = 2;
const unsigned int outputlt = 4;
const unsigned int outputrt = 7;
const unsigned int outputbw = 6;

Pins 6 and 7 are connected to the SPI flash chip. They're not generally safe to use in applications. They're also not usually expressed on ESP32 breakout boards.

Try rebuilding the firmware using safe pins like 13 and 14 instead of 6 and 7 and you'll find it doesn't crash the way it did.

Perhaps you confused the breakout board's pin numbering with GPIO pin numbering? You'll need to refer to the pinout for the board you're using to find the correct GPIO pin. ESP32 Arduino code will refer to GPIO pin numbers, not breakout board pin numbers.

There's a very useful reference for how ESP32 GPIO pins are used and which ones are safe for which purposes here.

Upvotes: 2

Related Questions