<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[M5.Axp.ScreenBreath() crashes when used in interrupt]]></title><description><![CDATA[<p dir="auto">Hi.<br />
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.<br />
On my system this program crashes with a watchdog timeout during i2c operation.</p>
<pre><code>#include &lt;M5StickC.h&gt;  //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 =&gt; 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 =&gt; 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 =&gt; 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 =&gt; 0.5ms steps
timerAttachInterrupt(timer,&amp;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.
}
</code></pre>
]]></description><link>https://community.m5stack.com/topic/2387/m5-axp-screenbreath-crashes-when-used-in-interrupt</link><generator>RSS for Node</generator><lastBuildDate>Wed, 29 Apr 2026 19:12:00 GMT</lastBuildDate><atom:link href="https://community.m5stack.com/topic/2387.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 16 Oct 2020 19:28:31 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to M5.Axp.ScreenBreath() crashes when used in interrupt on Thu, 22 Oct 2020 17:48:56 GMT]]></title><description><![CDATA[<p dir="auto">Works. Thank you!</p>
]]></description><link>https://community.m5stack.com/post/10431</link><guid isPermaLink="true">https://community.m5stack.com/post/10431</guid><dc:creator><![CDATA[M95D]]></dc:creator><pubDate>Thu, 22 Oct 2020 17:48:56 GMT</pubDate></item><item><title><![CDATA[Reply to M5.Axp.ScreenBreath() crashes when used in interrupt on Sun, 18 Oct 2020 10:16:04 GMT]]></title><description><![CDATA[<p dir="auto">Hello <a class="plugin-mentions-user plugin-mentions-a" href="/user/m95d" aria-label="Profile: M95D">@<bdi>M95D</bdi></a></p>
<p dir="auto">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 <code>onTimer()</code> is in RAM, but everything else is probably not. All this is causing the watchdog to trigger.</p>
<p dir="auto">To solve the issue, you should only set a flag in the interrupt function and test this flag in the <code>loop()</code> function and then act upon it.</p>
<p dir="auto">Try something like this:</p>
<pre><code>#include &lt;M5StickC.h&gt;  //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 =&gt; turn on the screen
  onButtonFlag = true;
}

void IRAM_ATTR onTimer(){  //Interrupt on timer =&gt; 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 =&gt; 0.5ms steps
timerAttachInterrupt(timer,&amp;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 =&gt; turn on the screen
  }
}
</code></pre>
<p dir="auto">Cheers<br />
Felix</p>
]]></description><link>https://community.m5stack.com/post/10381</link><guid isPermaLink="true">https://community.m5stack.com/post/10381</guid><dc:creator><![CDATA[felmue]]></dc:creator><pubDate>Sun, 18 Oct 2020 10:16:04 GMT</pubDate></item></channel></rss>