Esp32 Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled

Hello
I am trying to develop a motion detection system using the esp32 and an ultrasonic sensor.
Everything is working fine except after the pictures/data are uploaded to firebase, it throws an error "Guru Mediation" reboots , runs the loop again sends the image throws the error repeatedly. Below is my code

#include "esp_camera.h"
#include <WiFi.h>
#include <WiFiClient.h>
#include "esp_system.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownout problems
#include "soc/rtc_cntl_reg.h"  // Disable brownout problems
#include "driver/rtc_io.h"
#include <SPIFFS.h>
#include <FS.h>
#include <Firebase_ESP_Client.h>
//Provide the token generation process info.
#include <addons/TokenHelper.h>
#include <string.h>
#include <time.h>

//#include "time.h"
// ===================
// Select camera model
// ===================
#define CAMERA_MODEL_AI_THINKER // Has PSRAM
// ===========================
// Enter your WiFi credentials
// ===========================
#define SSID "Redmi 10"
#define PASSWORD "1favour7"

// Insert Firebase parameters
#define API_KEY "AIzaSyDc-D6UXo56aIHXEBJloHDQxM0Fta-0rvs"
#define USER_EMAIL "akpanidiong777@gmail.com"
#define USER_PASSWORD "1favour7"
#define STORAGE_BUCKET_ID "esp32-project-900f8.appspot.com"
#define FIREBASE_PROJECT_ID "esp32-project-900f8"

// Photo File Name to save in SPIFFS
#define FILE_PHOTO "/data/photo.jpg"

const char* ntpServer = "pool.ntp.org";
// Variable to save current epoch time
unsigned long epochTime;
char buffe [50];
char source[] = ".jpg";
char docPath[] = "Images/";

unsigned long getTime() {
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    //Serial.println("Failed to obtain time");
    return (0);
  }
  time(&now);
  return now;
}

hw_timer_t *timer = NULL;
void IRAM_ATTR resetModule() {
  ets_printf("reboot\n");
  esp_restart();
}

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27

#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22

//Define Firebase Data objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig configF;

bool taskCompleted = false;

// Check if photo capture was successful
bool checkPhoto( fs::FS &fs ) {
  File f_pic = fs.open( FILE_PHOTO );
  unsigned int pic_sz = f_pic.size();
  return ( pic_sz > 100 );
}

// Capture Photo and Save it to SPIFFS
void capturePhotoSaveSpiffs( void ) {
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean indicating if the picture has been taken correctly
  do {
    // Take a photo with the camera
    Serial.println("Taking a photo...");

    fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("Camera capture failed");
      return;
    }
    // Photo file name
    Serial.printf("Picture file name: %s\n", FILE_PHOTO);
    File file = SPIFFS.open(FILE_PHOTO, FILE_WRITE);
    // Insert the data in the photo file
    if (!file) {
      Serial.println("Failed to open file in writing mode");
    }
    else {
      file.write(fb->buf, fb->len); // payload (image), payload length
      Serial.print("The picture has been saved in ");
      Serial.print(FILE_PHOTO);
      Serial.print(" - Size: ");
      Serial.print(file.size());
      Serial.println(" bytes");
    }
    // Close the file
    file.close();
    esp_camera_fb_return(fb);

    // check if file has been correctly saved in SPIFFS
    ok = checkPhoto(SPIFFS);
  } while ( !ok );
}
void initSPIFFS() {
  if (!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    ESP.restart();
  }
  else {
    delay(500);
    Serial.println("SPIFFS mounted successfully");
  }
}

//ultransonic sensor pins
const int trigPin = 13;
const int echoPin = 15;
boolean startTimer = false;
unsigned long time_now = 0;
int counter = 0, time_capture = 0;

//other variables
long duration;
float distanceCm;
float distanceInch;

//int FirstDistance;
//int SecondDistance;
//double velocity;
//float Time = 2.0;
//float delayedtime = 1000*Time;


//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701


void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;
  }
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  WiFi.begin(SSID, PASSWORD);
  Serial.printf("WiFi connecting to %s\n", SSID);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(400);
  }
  Serial.printf("\nWiFi connected\nIP : ");
  Serial.println(WiFi.localIP());
  initSPIFFS();
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  configTime(0, 0, ntpServer);
  //Firebase
  // Assign the api key
  configF.api_key = API_KEY;
  //Assign the user sign in credentials
  auth.user.email = USER_EMAIL;
  auth.user.password = USER_PASSWORD;
  //Assign the callback function for the long running token generation task
  configF.token_status_callback = tokenStatusCallback; //see addons/TokenHelper.h
  Firebase.begin(&configF, &auth);
  Firebase.reconnectWiFi(true);

  timer = timerBegin(0, 80, true); //timer 0, div 80Mhz
  timerAttachInterrupt(timer, &resetModule, true);
  timerAlarmWrite(timer, 20000000, false);
  timerAlarmEnable(timer); //enable interrupt

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  if (psramFound()) {
    // FRAMESIZE_ +
    //QQVGA/160x120//QQVGA2/128x160//QCIF/176x144//HQVGA/240x176
    //QVGA/320x240//CIF/400x296//VGA/640x480//SVGA/800x600//XGA/1024x768
    //SXGA/1280x1024//UXGA/1600x1200//QXGA/2048*1536
    config.frame_size = FRAMESIZE_VGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  }
  else {
    config.frame_size = FRAMESIZE_QQVGA; config.jpeg_quality = 12;
    config.fb_count = 1;
  }
  // Init Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
}

void loop() {
  timerWrite(timer, 0); //reset timer (feed watchdog)
  epochTime = getTime();
  sprintf(buffe, "%lu", epochTime);
  strcat(buffe, source);
  strcat(docPath, buffe);
  
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);

  // Calculate the distance
  distanceCm = duration * SOUND_SPEED / 2;

  // Convert to inches
  distanceInch = distanceCm * CM_TO_INCH;

  // Prints the distance in the Serial Monitor
  Serial.print("Distance (cm): ");
  Serial.println(distanceCm);
  Serial.print("Distance (inch): ");
  Serial.println(distanceInch);


  if (distanceCm <= 50 && startTimer != true) {
    Camera_capture();
    startTimer = true;
  } else if (distanceCm > 50) {
    startTimer = false;
    time_capture = 0;
  } if (distanceCm <= 50) {
    if (++time_capture > 4) {
      time_capture = 0;
      Camera_capture();
      Serial.println("Over Time");
    }
  }
  delay(500);
}


void Camera_capture() {
  capturePhotoSaveSpiffs();
  delay(1);
  if (Firebase.ready() && !taskCompleted) {
    taskCompleted = true;
    String documentPath = docPath;
    FirebaseJson content;

    Serial.print("Uploading picture... ");
    //MIME type should be valid to avoid the download problem.
    //The file systems for flash and SD/SDMMC can be changed in FirebaseFS.h.
    if (Firebase.Storage.upload(&fbdo, STORAGE_BUCKET_ID /* Firebase Storage bucket id */, FILE_PHOTO /* path to local file */, mem_storage_type_flash /* memory storage type, mem_storage_type_flash and mem_storage_type_sd */, buffe /* path of remote file stored in the bucket */, "image/jpeg" /* mime type */)) {
      Serial.printf("\nDownload URL: %s\n", fbdo.downloadURL().c_str());
    }
    else {
      Serial.println(fbdo.errorReason());
    }

    content.set("fields/ImgUrl/stringValue", fbdo.downloadURL().c_str());
    content.set("fields/velocity/stringValue", String(distanceCm).c_str());
    //content.set(fields/ImgUrl/stringValue", fbdo.downloadURL().c_str());
    Serial.print("Uploading data... ");

    if (Firebase.Firestore.createDocument(&fbdo, FIREBASE_PROJECT_ID, "" /* databaseId can be (default) or empty */, documentPath.c_str(), content.raw())) {
      Serial.printf("ok\n%s\n\n", fbdo.payload().c_str());
    }
    else {
      Serial.println(fbdo.errorReason());
    }
    taskCompleted = false;
  }
}

This are the errors

Using the Esp decoder i inputted the backtrace but i dont seem to get the issue

Decoding stack results
0x400e93b0: gpio_set_level at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/esp32/include/hal/gpio_ll.h line 427
0x400e5ad9: __digitalWrite at C:\Users\ACER\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.3\cores\esp32\esp32-hal-gpio.c line 126
0x400d3660: loop() at C:\Users\ACER\Desktop\speed/speed.ino line 253
0x400e8065: loopTask(void*) at C:\Users\ACER\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.3\cores\esp32\main.cpp line 50

Please i need help as this is part of my final year project thanks

This line in your loop function looks fishy:

strcat(docPath, buffe);

Here's your definition of the global variable docPath.

char docPath[] = "Images/";

How much room do you think you have to concatenate characters onto the end of that?

Just as bad, you try to do that concatenation on every pass through loop(). You seem to be overwriting quite a bit of memory that you don't own.

Alright I'll change that and get back to you

Hi,
put this function "yield();" before delay(500); which has at the end of the loop();

Likely unecessary. On an ESP32 delay merely calls vTaskDelay().

Also, the exception appears due to a memory access failure, not a WDT reset.

Seems the issue is around these lines.

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);

of code.

Thanks this works but is there a better way i could go about the process? I'm trying to generate document id's using epoch time?

using the SafeString-library
The name is program. You can't write beyond the maximum bytes reserved for a SafeString.

I'm pretty sure the C++-purists here will answer
"no don't use SafeString ! Just learn to use c_string-arrays carefully and everything will work."

I general the C-language allows a lot of "dirty" things that aren't allowed in most other programming-languages.

best regards Stefan

Just not much of a reason to on an ESP. Arduino String (or std::string) is typically fine. In fact, the String class is used extensively in the Arduino cores for ESP8266 and ESP32.

However, attempting to concatenate a (string, String, std::string) on every pass through loop() as @mozman777's code does is a recipe for disaster no matter how you do it. You eventually run out of heap and/or overwrite memory that you don't own.

SafeString will just drop the characters that don't fit into the size of the SafeString.
This means the user will see that there are missing characters but the code won't crash.


#include <SafeString.h>
createSafeString(mySafeStr_SS, 10);

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
char ch;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  mySafeStr_SS = "Test";
  ch = 'A';
}


void loop() {

  if ( TimePeriodIsOver(MyTestTimer, 1000) ) {
    mySafeStr_SS += ch;
    ch++;
    Serial.print("ch=");
    Serial.print(ch);
    Serial.print(" mySafeStr_SS=#");
    Serial.print(mySafeStr_SS);
    Serial.println("#");
  }
}

Serial output

Setup-Start
ch=B mySafeStr_SS=#TestA#
ch=C mySafeStr_SS=#TestAB#
ch=D mySafeStr_SS=#TestABC#
ch=E mySafeStr_SS=#TestABCD#
ch=F mySafeStr_SS=#TestABCDE#
ch=G mySafeStr_SS=#TestABCDEF#
ch=H mySafeStr_SS=#TestABCDEF#
ch=I mySafeStr_SS=#TestABCDEF#
ch=J mySafeStr_SS=#TestABCDEF#
ch=K mySafeStr_SS=#TestABCDEF#
ch=L mySafeStr_SS=#TestABCDEF#
ch=M mySafeStr_SS=#TestABCDEF#
ch=N mySafeStr_SS=#TestABCDEF#
ch=O mySafeStr_SS=#TestABCDEF#
ch=P mySafeStr_SS=#TestABCDEF#
ch=Q mySafeStr_SS=#TestABCDEF#
ch=R mySafeStr_SS=#TestABCDEF#
ch=S mySafeStr_SS=#TestABCDEF#

best regards Stefan

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.