Wdt reset while using MCP23017 INT

I am trying to expand the number of IO ports of an ESP8266 (wemos mini D1) using an MCP23017.
I am using INTA of the MCP23017 to trigger an interrupt on ESP8266’s pin D5 (as shown in the attached figure) mcp23017-restart-issue .
The code below works fine. When I press the button switch, the pin number attached to the pressed button is shown in the serial monitor.

#include <Wire.h>
#include "Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;

volatile unsigned long last_interrupt; // Used to store the time in millis of the last interrupt, for debouncing
int debounce_delay = 100;              // The minimum delay in milliseconds between button presses, for debouncing

volatile uint8_t pin_num;   // when an interrupt is detected and decoded the pin which generated the interrupt is stored here 
volatile uint8_t int_pin_val ;
int esp_interrupt_pin=14; // GPIO14 (D5)
bool send_to_me;

byte mcp_PA0=0;

void cleanInterrupt(){
  while(!(mcp.digitalRead(0))) ; 
 // now MCP is ready to receive another interrupt
}
void ICACHE_RAM_ATTR intCallBack()
{
//  noInterrupts();
  pin_num = mcp.getLastInterruptPin();
  int_pin_val = mcp.getLastInterruptPinValue();

  if(millis()-last_interrupt>=debounce_delay)  // Debounce routine
  {
    
    send_to_me=true;
  }

  last_interrupt=millis();
  //interrupts();
  cleanInterrupt(); // Call the function that clears all of the interrupt registers
}
void setup() {
  ///////////////start addition wifi

  Serial.begin(115200);

  pinMode(esp_interrupt_pin,INPUT); // Initialise the MCU pin used for the Interrupt line (INTA or INTB on the Waveshare board)
  mcp.begin(); // default address, no solder pads bridged
  mcp.setupInterrupts(false,false,LOW);

  mcp.pinMode(mcp_PA0, INPUT);
  mcp.pullUp(mcp_PA0, HIGH);  // turn on a 100K pullup internally
  mcp.setupInterruptPin(mcp_PA0,CHANGE);  

  cleanInterrupt(); // Call the function that clears all of the interrupt registers
                        
  // Here we attach an interrupt to the MCU pin that will be used to listen for interrupts from the mcp...
  attachInterrupt(digitalPinToInterrupt(esp_interrupt_pin),intCallBack,FALLING);
        
}

void loop() {


if (send_to_me==true){
    Serial.print("Pin = ");
    Serial.println(pin_num);
    send_to_me=false;
}
}

However, when I keep pressing the button, after few seconds, I get watchdog timer reset.

ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 3584, room 16 
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld

I tried to put yield() in the loop but didn’t solve the issue.
Any advice or help is appreciated.

Could this be the reason? Maybe put yield() in there.

Thank you your reply. I tried as you advised and I had an exception:
`User exception (panic/abort/assert)

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Panic core_esp8266_main.cpp:133 __yield`

I wonder how to clear the interrupt registry of the mcp23017 directly (not using mcp.digitalRead) .

Don’t you think you should post the modified code, so we can check it, in case your attempt was incorrect?

What’s the problem with using mcp.digitalRead()?

I tried yield() in the code as follows:

     #include <Wire.h>
    #include "Adafruit_MCP23017.h"

    Adafruit_MCP23017 mcp;

    volatile unsigned long last_interrupt; // Used to store the time in millis of the last interrupt, for debouncing
    int debounce_delay = 100;              // The minimum delay in milliseconds between button presses, for debouncing

    volatile uint8_t pin_num;   // when an interrupt is detected and decoded the pin which generated the interrupt is stored here 
    volatile uint8_t int_pin_val ;
    int esp_interrupt_pin=14; // GPIO14 (D5)
    bool send_to_me;

    byte mcp_PA0=0;

    void cleanInterrupt(){
     while(!(mcp.digitalRead(0))) yield();
     // now MCP is ready to receive another interrupt
    }
    void ICACHE_RAM_ATTR intCallBack()
    {
    //  noInterrupts();
      pin_num = mcp.getLastInterruptPin();
      int_pin_val = mcp.getLastInterruptPinValue();

      if(millis()-last_interrupt>=debounce_delay)  // Debounce routine
      {
        
        send_to_me=true;
      }

      last_interrupt=millis();
      //interrupts();
      cleanInterrupt(); // Call the function that clears all of the interrupt registers
    }
    void setup() {
      ///////////////start addition wifi

      Serial.begin(115200);

      pinMode(esp_interrupt_pin,INPUT); // Initialise the MCU pin used for the Interrupt line (INTA or INTB on the Waveshare board)
      mcp.begin(); // default address, no solder pads bridged
      mcp.setupInterrupts(false,false,LOW);

      mcp.pinMode(mcp_PA0, INPUT);
      mcp.pullUp(mcp_PA0, HIGH);  // turn on a 100K pullup internally
      mcp.setupInterruptPin(mcp_PA0,CHANGE);  

      cleanInterrupt(); // Call the function that clears all of the interrupt registers
                            
      // Here we attach an interrupt to the MCU pin that will be used to listen for interrupts from the mcp...
      attachInterrupt(digitalPinToInterrupt(esp_interrupt_pin),intCallBack,FALLING);
            
    }

    void loop() {


    if (send_to_me==true){
        Serial.print("Pin = ");
        Serial.println(pin_num);
        send_to_me=false;
    }
    }

this code crashes with this exception:
`User exception (panic/abort/assert)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Panic core_esp8266_main.cpp:133 __yield

stack>>>

ctx: cont
sp: 3ffffdd0 end: 3fffffc0 offset: 0000
3ffffdd0: 00000020 00000020 3ffee4f4 40202a38
3ffffde0: 000000fe 00000000 00000000 00000000
3ffffdf0: 00000000 00000000 00000000 3ffee4f0
3ffffe00: 00000001 00000001 00000001 00000020
3ffffe10: ffffffff 0000000e 3ffee30c 402024e2
3ffffe20: 00000000 00000000 4bc6a7f0 4020253f
3ffffe30: ffffffff 0000000e 00000000 40202025
3ffffe40: 00000000 3ffee310 3ffee30c 40201023
3ffffe50: ffffffff 0000000e 3ffee30c 40100168
3ffffe60: 4010060e 7fffffff 00000000 40100698
3ffffe70: c0033035 00000080 0000001f 401001e0
3ffffe80: 00000000 00000000 0000001f 00000022
3ffffe90: 3fffc200 401005d4 3fffc258 4000050c
3ffffea0: 40201f7d 00000030 00000010 ffffffff
3ffffeb0: 402020e4 00000050 402020d8 00000000
3ffffec0: 00000000 00000000 00000000 fffffffe
3ffffed0: ffffffff 3fffc6fc 00000001 3ffe84f0
3ffffee0: 00000000 3fffdad0 3ffee4b4 00000030
3ffffef0: 00000000 3fffdad0 3ffee4b4 00000030
3fffff00: 00000000 3fffdad0 3ffee4b4 00000030
3fffff10: 00000020 00000020 feefeffe 40201398
3fffff20: 00000001 0000000c 3ffee310 3ffee4b4
3fffff30: 00000012 00000020 00000001 40202bf4
3fffff40: 00000012 3ffee310 00000004 40201308
3fffff50: 402031d5 00000001 3ffee310 40201333
3fffff60: 007a1200 18581b85 00000000 40201424
3fffff70: 00000000 3ffee308 00000000 3ffee4b4
3fffff80: 00000000 00000000 00000001 401001e0
3fffff90: 3fffdad0 00000000 3ffee474 40100201
3fffffa0: 3fffdad0 00000000 3ffee474 40202101
3fffffb0: feefeffe feefeffe 3ffe84f0 40101011
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

ets Jan 8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld
`
mcp.digitalRead clears mcp23017 interrupt registry.

Ok, that’s what I intended. Sorry, don’t know why that caused an error.

This the best working version so far. I now clean the mcp23017 interrupt register in the loop().

#include <Wire.h>
#include "Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;

volatile unsigned long last_interrupt; // Used to store the time in millis of the last interrupt, for debouncing
int debounce_delay = 100;              // The minimum delay in milliseconds between button presses, for debouncing


const int   watchdog2 = 50; 
unsigned long previousMillis2 = millis();

volatile uint8_t pin_num;   // when an interrupt is detected and decoded the pin which generated the interrupt is stored here 
volatile uint8_t int_pin_val ;
int esp_interrupt_pin=14; // GPIO14 (D5)
bool send_to_me;
byte mcp_PA0=0;

void ICACHE_RAM_ATTR intCallBack()
{
  pin_num = mcp.getLastInterruptPin();
  int_pin_val = mcp.getLastInterruptPinValue();

  if(millis()-last_interrupt>=debounce_delay)  // Debounce routine
  {
    send_to_me=true;
  }
  last_interrupt=millis();
}
void setup() {
  Serial.begin(115200);
  pinMode(esp_interrupt_pin,INPUT); // Initialise the MCU pin used for the Interrupt line (INTA or INTB on the Waveshare board)
  mcp.begin(); // default address, no solder pads bridged
  mcp.setupInterrupts(false,false,LOW);

  mcp.pinMode(mcp_PA0, INPUT);
  mcp.pullUp(mcp_PA0, HIGH);  // turn on a 100K pullup internally
  mcp.setupInterruptPin(mcp_PA0,CHANGE);                         
  // Here we attach an interrupt to the MCU pin that will be used to listen for interrupts from the mcp...
  attachInterrupt(digitalPinToInterrupt(esp_interrupt_pin),intCallBack,FALLING);       
}

void loop() {

if(send_to_me==true){
    int val0 = mcp.digitalRead(0);
    unsigned long currentMillis2 = millis();
  if ( currentMillis2 - previousMillis2 > watchdog2 ) {
    previousMillis2 = currentMillis2;
       Serial.print("Pin = ");
       Serial.println(pin_num);
    send_to_me=false;
  }
  }

}