M5.Axp.ScreenBreath() crashes when used in interrupt
-
Hi.
It seems that M5.Axp.ScreenBreath() crashes when it is used in a interrupt. Try the demo below in Arduino IDE. It should turn off the display after a timer delay and turn it back on when the button is pressed.
On my system this program crashes with a watchdog timeout during i2c operation.#include <M5StickC.h> //define M5StickC hardware components and functions #define BUTTON_MAIN 37 //The main button pin number #define SCREEN_TIMEOUT 10 //Screen-off timeout in seconds hw_timer_t *timer; void IRAM_ATTR onButton() { //Interrupt on button press => turn on the screen detachInterrupt(BUTTON_MAIN); //Ignore more button presses M5.Axp.ScreenBreath(10); //Set screen light ON timerAlarmEnable(timer); //Start timer for screen-off delay } void IRAM_ATTR onTimer(){ //Interrupt on timer => turn off the screen timerAlarmDisable(timer); //Stop the timer. M5.Axp.ScreenBreath(0); //Set screen light OFF attachInterrupt(BUTTON_MAIN,onButton,FALLING); //Attach interrupt on button press => turn on the screen } void setup() { M5.begin(); //Init M5 M5.Lcd.fillScreen(YELLOW); //Make screen yellow pinMode(BUTTON_MAIN, INPUT_PULLUP); //Button GPIO set as input, pull-up enabled timer=timerBegin(1,40000,true); //Init screen light timer, divisor 40000 => 0.5ms steps timerAttachInterrupt(timer,&onTimer,true); //Set screen light timer interrupt function timerAlarmWrite(timer,SCREEN_TIMEOUT*2000,true); //Set interrupt to turn off screen after X timer steps of 0.5ms each. timerAlarmEnable(timer); //Start timer for screen-off delay } void loop() { //No code here. }
-
Hello @M95D
interrupt functions need to be as short as possible, run from RAM and everything in it (e.g. every function you call from within) also needs to run from RAM. In your case only
onTimer()
is in RAM, but everything else is probably not. All this is causing the watchdog to trigger.To solve the issue, you should only set a flag in the interrupt function and test this flag in the
loop()
function and then act upon it.Try something like this:
#include <M5StickC.h> //define M5StickC hardware components and functions #define BUTTON_MAIN 37 //The main button pin number #define SCREEN_TIMEOUT 10 //Screen-off timeout in seconds hw_timer_t *timer; volatile bool onButtonFlag = false; volatile bool onTimerFlag = false; void IRAM_ATTR onButton() { //Interrupt on button press => turn on the screen onButtonFlag = true; } void IRAM_ATTR onTimer(){ //Interrupt on timer => turn off the screen onTimerFlag = true; } void setup() { M5.begin(); //Init M5 M5.Lcd.fillScreen(YELLOW); //Make screen yellow pinMode(BUTTON_MAIN, INPUT_PULLUP); //Button GPIO set as input, pull-up enabled timer=timerBegin(1,40000,true); //Init screen light timer, divisor 40000 => 0.5ms steps timerAttachInterrupt(timer,&onTimer,true); //Set screen light timer interrupt function timerAlarmWrite(timer,SCREEN_TIMEOUT*2000,true); //Set interrupt to turn off screen after X timer steps of 0.5ms each. timerAlarmEnable(timer); //Start timer for screen-off delay } void loop() { if(onButtonFlag) { onButtonFlag = false; detachInterrupt(BUTTON_MAIN); //Ignore more button presses M5.Axp.ScreenBreath(10); //Set screen light ON timerAlarmEnable(timer); //Start timer for screen-off delay } if(onTimerFlag) { onTimerFlag = false; timerAlarmDisable(timer); //Stop the timer. M5.Axp.ScreenBreath(0); //Set screen light OFF attachInterrupt(BUTTON_MAIN,onButton,FALLING); //Attach interrupt on button press => turn on the screen } }
Cheers
Felix -
Works. Thank you!