Button / Interrupt handler periodically stops working

I have a strange issue where a button handler will work fine for hours / days, but then suddenly stop working. I know the button itself is fine - a separate periodic timer reads the button status correctly.

My device uses auto light sleep.

the handler is set in js using the following function:

GPIO.set_button_handler(
  b_P,
  GPIO.PULL_UP,
  GPIO.INT_EDGE_ANY,
  50,
  function (b_P) {
    let button_State = GPIO.read(b_P);
        if (button_State === BTN_PRESS) {
          li("Button Pressed");
          if (isProvisioning === true) {
            // li("Button press:" + js(button_State));
            Timer.del(timer_DeepSleep);
            timer_DeepSleep = Timer.set(5000, 0, checkButtonDeepSleep, null);
          } else {
            timer_btnRelease = Timer.set(
            100,
            0,
            function () {
              Timer.del(timer_btnRelease);
              Timer.del(timer_Provision);
              timer_Provision = Timer.set(8000, 0, checkButtonProvision, null);
              boxButtonHandler(b_P);
              },
              null
            );

            
          }
        } else {
          li("Button Released");
          Timer.del(timer_Provision);
          let f = ffi("void blink_watchdog()");
          f();
        }
    //   // }
    // }
  },
  null
);

What’s even stranger is that, for testing purposes I created an RPC function to create a new handler:

RPC.addHandler("checkButton", function () {
  // GPIO.disable_int(b_P);
  GPIO.set_mode(b_P, GPIO.MODE_INPUT);
  li("Setting new interrupt handler on: " + js(b_P));
  let res = GPIO.set_int_handler(b_P, GPIO.INT_EDGE_ANY, function(pin) {
    let button_State = GPIO.read(pin);
    if (button_State === BTN_PRESS) {
      li("Button Pressed (3)");
    } else {
      li("Button Released (3)");
    }
  }, null);
  GPIO.enable_int(b_P);
  return res
});

If I call the above function when the button is still working, as expected the original handler gets replaced by this new one, and all works fine. However, once the original handler fails, even if I then call this function, it returns 1 (so success), but it doesn’t work either - no response at all when the button is pressed.

The button is on GPIO 13. I have a separate button handler on GPIO 33 which continues to work fine, and has never failed.

Anyone got any ideas what could be causing this / how to resolve it?

Based on what you’ve described I’d personally be looking at the button GPIO being used. You mention that another GPIO has not had any issues ever, but pin 13 has.

What chip are you using?

Sorry I forgot about that bit! I’m using ESP32 Wrover. I know the button itself is working, as calling GPIO.read on a timer correctly records the GPIO going high/low.

The details in this article have helped me a few times: ESP32 Pinout Reference: Which GPIO pins should you use? | Random Nerd Tutorials

Not sure on the GPIO differences of wrover vs wroom, but the diagrams have GPIO13 listed as:

  • RTC_GPIO14
  • HSPI_MOSI
  • TOUCH4
  • ADC2_CH4

It’s not really an answer, but I would try to dig in to what other things GPIO13 is doing or has the capability to do - could be some unexpected behaviour resulting from other uses of that GPIO.

You also mentioned that GPIO33 is working fine - the only difference I see in GPIO13 and GPIO33 in the diagrams is the HPSI_MOSI. Could be somewhere to start looking

Thanks, this is interesting. I’m using ESP32 WROVER, with SPIRAM enabled. I wonder if the built-in SPIRAM is using HSPI for communications, perhaps (although I can find no mention of this - unless I’ve totally missed it)

Is there any way I can simply disable HSPI for testing purposes? The problem I’m seeing is very intermittent (once every couple of days when testing quite frequently), so a challenging one to consistently replicate.

Looks like it’s not connected to HSPI