ESP32 WROOM 32 crashes when exiting function

Hi there.

I have an ESP32 WROOM 32 devkit 1 and I am trying to use the Capacitive Touch sensors built into the ESP

I have some code which waits for touch to be detected, and once it is detected, it should return that the pad has been touched, instead it crashes and reboots.

Does anyone know why and what might be causing this behavior?

Code below

#define Threshold 40

int touchPad;
bool touchDetected = false;
int flag = 0;
int i = 0;
                  
void setup() {
  Serial.begin(115200);
  delay(1000); // give me time to bring up serial monitor
  Serial.println("Booting");
  
  touchAttachInterrupt(T0, gotTouch0, Threshold);
  touchAttachInterrupt(T3, gotTouch3, Threshold);
  touchAttachInterrupt(T4, gotTouch4, Threshold);
  touchAttachInterrupt(T5, gotTouch5, Threshold);
  touchAttachInterrupt(T6, gotTouch6, Threshold);
  touchAttachInterrupt(T7, gotTouch7, Threshold);
  touchAttachInterrupt(T8, gotTouch8, Threshold);
  touchAttachInterrupt(T9, gotTouch9, Threshold);
}

void loop(){
  if(touchDetected){ //Check continuously if any touch is detected
    switch(touchPad){
      case 0  : Serial.println("Case 0 Selected"); delay(1000); break;
      case 3  : Serial.println("Case 3 Selected"); break;
      case 4  : Serial.println("Case 4 Selected"); break;
      case 5  : Serial.println("Case 5 Selected"); break;
      case 6  : Serial.println("Case 6 Selected"); break;
      case 7  : Serial.println("Case 7 Selected"); break;
      case 8  : Serial.println("Case 8 Selected"); break;
      case 9  : Serial.println("Case 9 Selected"); break;
      default : break;
      
      delay(1000);
    }
  }
}

void gotTouch0(){
 Serial.println("Got 0");
 touchDetected = true;
 Serial.println("Changed TouchDetected to True");
 touchPad = 0;
 Serial.println("Set TouchPad to True");
 delay(5000);
 Serial.println("Going Back");
 }

void gotTouch3(){
 Serial.println("Got 3");
 touchDetected = true;
 touchPad = 3;
 delay(500);
}

void gotTouch4(){
 Serial.println("Got 4");
 touchDetected = true;
 touchPad = 4;
 delay(500);
}

void gotTouch5(){
 Serial.println("Got 5");
 touchDetected = true;
 touchPad = 5;
 delay(500);
}

void gotTouch6(){
 Serial.println("Got 6");
 touchDetected = true;
 touchPad = 6;
 delay(500);
}

void gotTouch7(){
 Serial.println("Got 7");
 touchDetected = true;
 touchPad = 7;
 delay(500);
}

void gotTouch8(){
 Serial.println("Got 8");
 touchDetected = true;
 touchPad = 8;
 delay(500);
}

void gotTouch9(){
 Serial.println("Got 9");
 touchDetected = true;
 touchPad = 9;
 delay(500);
}

general recommendation is not to put Serial.print() statements in interrupt routines and callback functions such as gotTouch0()
I have found this is very important on the ESP32 where such calls cause system resets etc
use global volatile variables to pass data from such functions to loop() where values can then be printed using Serial.print()

also avoid using delay() in such functions

1 Like

@horace my friend, this got me out of the woods to an extent! Thank you for this.

My next issue is not I am trying to use these interrupts to push an image onto my E Paper Display. I can see it enters my function call successfully by using serial outs just to see where it gets stuck, and it's getting stuck on line 126 which is being used to clear the display...

I know @ZinggJM is a Guru with these displays, maybe you could bestow some of your wisdom onto us :slight_smile: Please refer to my other post to see my setup for this including the display and lib I used.

Thanks in advance guys!

I have posted my code below for reference

/* Includes ------------------------------------------------------------------*/
#include "DEV_Config.h"
#include "EPD.h"
#include "GUI_Paint.h"
#include "imagedata.h"
#include <stdlib.h>
#define Threshold 15

int touchPad;
bool touchDetected = false;
int flag = 0;
int i = 0;

  UBYTE *BlackImage;
  UWORD Imagesize = ((EPD_4IN2_V2_WIDTH % 8 == 0)? (EPD_4IN2_V2_WIDTH / 8 ): (EPD_4IN2_V2_WIDTH / 8 + 1)) * EPD_4IN2_V2_HEIGHT;

void setup() {
  Serial.begin(115200);
  delay(1000); // give me time to bring up serial monitor
  Serial.println("Booting");
  
  // printf("Beginning Display Setup----------------\r\n");
  Serial.println("Beginning Display Setup");
  DEV_Module_Init();      //Needs to be present
  EPD_4IN2_V2_Init();     //Needs to be present
  EPD_4IN2_V2_Clear();    //Needs to be present - Clears display on boot
  // DEV_Delay_ms(500);      //Needs to be present - Waits some time to let display chill

  if((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL) {
  printf("Failed to apply for black memory...\r\n");
  // while (1);
  }

  // printf("Goto Sleep...\r\n");
  EPD_4IN2_V2_Sleep();
  free(BlackImage);
  BlackImage = NULL;
  Serial.println("Completed Display Setup");
  // printf("Completed Display Setup----------------\r\n");

  
  // printf("Beginning Touch Setup------------------\r\n");
  Serial.println("Beginning Touch Setup");
  touchAttachInterrupt(T0, gotTouch0, Threshold);
  touchAttachInterrupt(T3, gotTouch3, Threshold);
  touchAttachInterrupt(T4, gotTouch4, Threshold);
  touchAttachInterrupt(T5, gotTouch5, Threshold);
  touchAttachInterrupt(T6, gotTouch6, Threshold);
  touchAttachInterrupt(T7, gotTouch7, Threshold);
  touchAttachInterrupt(T8, gotTouch8, Threshold);
  touchAttachInterrupt(T9, gotTouch9, Threshold);
  // printf("Completed Touch Setup------------------\r\n");
  Serial.println("Completed Touch Setup");
  
}

void loop(){
  if(touchDetected){ //Check continuously if any touch is detected
    touchDetected = false;
    switch(touchPad){
      case 0  : Serial.println("Case 0 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_4in2_4Gray); sleepDisplay(); break;
      case 3  : Serial.println("Case 3 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_4in2_4Gray1); sleepDisplay(); break;
      case 4  : Serial.println("Case 4 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_Uchihas); sleepDisplay(); break;
      case 5  : Serial.println("Case 5 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_barb); sleepDisplay(); break;
      case 6  : Serial.println("Case 6 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_4in2_4Gray); sleepDisplay(); break;
      case 7  : Serial.println("Case 7 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_4in2_4Gray); sleepDisplay(); break;
      case 8  : Serial.println("Case 8 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_4in2_4Gray); sleepDisplay(); break;
      case 9  : Serial.println("Case 9 Selected"); prepareDisplay(); Paint_DrawBitMap(gImage_4in2_4Gray); sleepDisplay(); break;
      default : break;
    }
  }

    // DEV_Delay_ms(2000);
    

  touchDetected = false;
  delay(1000);
}

void gotTouch0(){
 touchDetected = true;
 touchPad = 0;
 }

void gotTouch3(){
 touchDetected = true;
 touchPad = 3;
}

void gotTouch4(){
 touchDetected = true;
 touchPad = 4;
}

void gotTouch5(){
 touchDetected = true;
 touchPad = 5;
}

void gotTouch6(){
 touchDetected = true;
 touchPad = 6;
}

void gotTouch7(){
 touchDetected = true;
 touchPad = 7;
}

void gotTouch8(){
 touchDetected = true;
 touchPad = 8;
}

void gotTouch9(){
 touchDetected = true;
 touchPad = 9;
}

void prepareDisplay(){
  
    EPD_4IN2_V2_Init_4Gray();
    free(BlackImage);
    Paint_NewImage(BlackImage, EPD_4IN2_V2_WIDTH, EPD_4IN2_V2_HEIGHT, 0, WHITE);
    Paint_SetScale(4);
    Paint_Clear(WHITE);
    EPD_4IN2_V2_Display_4Gray(BlackImage);
    // DEV_Delay_ms(2000);
    
    Paint_Clear(WHITE);
    // Paint_DrawBitMap(gImage_barb);

}

void sleepDisplay() {
  EPD_4IN2_V2_Display_4Gray(BlackImage);
  // DEV_Delay_ms(2000);
  EPD_4IN2_V2_Sleep();
  free(BlackImage);
  BlackImage = NULL;
}

Also for reference, please see the crash report

Booting
e-Paper busy
e-Paper busy release
e-Paper busy
e-Paper busy release
e-Paper busy
e-Paper busy release
e-Paper busy
e-Paper busy release
Completed Display Setup
Beginning Touch Setup
Completed Touch Setup
Case 9 Selected
Preparing Image-----------------------

e-Paper busy
e-Paper busy release
Free Image-----------------------

Set Image Width -----------------------

Set Image Scale -----------------------

Set Image Colour ----------------------- (This is line 126)

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

Core 1 register dump:
PC      : 0x400d19b8  PS      : 0x00060a30  A0      : 0x800d16f7  A1      : 0x3ffb2230  
A2      : 0x000000ff  A3      : 0x00000000  A4      : 0x0000012c  A5      : 0x00000000  
A6      : 0x000000ff  A7      : 0x00000000  A8      : 0x00000000  A9      : 0x00000000  
A10     : 0x00000001  A11     : 0x3ffc1c74  A12     : 0x00000000  A13     : 0x0000ff00  
A14     : 0x00ff0000  A15     : 0xff000000  SAR     : 0x0000001b  EXCCAUSE: 0x0000001d  
EXCVADDR: 0x00000000  LBEG    : 0x400864a1  LEND    : 0x400864b1  LCOUNT  : 0xfffffff5  


Backtrace: 0x400d19b5:0x3ffb2230 0x400d16f4:0x3ffb2250 0x400d17a2:0x3ffb2270 0x400d34e1:0x3ffb2290




ELF file SHA256: 2c57bb49822248f3

Rebooting...

have a look at the EspExceptionDecoder may give some help in finding the problem

did you implement the code in "GUI_Paint.h" etc? if so post the code

I never used the E Paper Display. - have you tried web searches

Edit: have you tried a simpler program just writing an image to the display - no interrupts etc etc

Not that it will help with your crash, but both touchDetected and touchPad should be declared volatile since they're altered in interrupt handlers.

@horace Yes! managed to get basic stuff working including writing images to the display
on this thread --> E-Ink Display shows image zoomed in

I basically copy pasted all the working parts into this new project and tried to implement these interrupts based on touch input.

Please see the attachments below
GUI_Paint.cpp (33.8 KB)
GUI_Paint.h (7.3 KB)

Do you think this issue is linked to the code for the display?

@van_der_decken Thank you for the feedback, i am still new to c ++ coding and Arduino code in general so i appreciate this. I just looked it up and understand the compiler can cut code if this is skipped.

it did not resolve my issue however I have implemented it :slight_smile:

Got it working guys!

changed my prepareDisplay function to take the image buffer in and print selected image based off the case condition

important part was the part around line 4 and the if statement. this is a must for any function which is refreshing the image. it is not enough to call global one.

Enjoy kids and stay out of trouble!

void prepareDisplay(const unsigned char *image_buffer){
  
    EPD_4IN2_V2_Init_4Gray();
    free(BlackImage);

    BlackImage = NULL;
    Imagesize = ((EPD_4IN2_V2_WIDTH % 8 == 0)? (EPD_4IN2_V2_WIDTH / 4 ): (EPD_4IN2_V2_WIDTH / 4 + 1)) * EPD_4IN2_V2_HEIGHT;
    if((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL) {
        printf("Failed to apply for black memory...\r\n");
        while (1);
    }

    Paint_NewImage(BlackImage, EPD_4IN2_V2_WIDTH, EPD_4IN2_V2_HEIGHT, 0, WHITE);
    Paint_SetScale(4);
    Paint_Clear(WHITE);
    EPD_4IN2_V2_Display_4Gray(BlackImage);
    DEV_Delay_ms(2000);
    Paint_Clear(WHITE);
    Paint_DrawBitMap(image_buffer);
    EPD_4IN2_V2_Display_4Gray(BlackImage);
    DEV_Delay_ms(2000);
    EPD_4IN2_V2_Sleep();
    free(BlackImage);
    BlackImage = NULL;

}

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