arduino / ArduinoCore-nRF528x-mbedos

[Archived] Arduino core supporting mbed-enabled boards
86 stars 34 forks source link

attachInterrupt() fails to detect falling edges when mode is set to CHANGE #68

Closed f-jiang closed 4 years ago

f-jiang commented 4 years ago

When I set my interrupt to detect both rising and falling edges using CHANGE, what ends up happening is that falling edges are ignored. I'm using a Nano 33 BLE.

My test setup consists of the code at the bottom, along with an LED connected to ledPin and a pushbutton connected to interruptPin. Note that interruptPin is pulled high.

What I expect to happen, given the CHANGE mode, is that LED should toggle when the button is both pressed (falling edge) and released (rising edge); however, it only toggles during button release.

(At first, I was having problems with my quadrature encoder code, but after some investigation it boiled down to the above issue).

const byte ledPin = 4;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}
f-jiang commented 4 years ago

I dug through the repo a bit, and it appears that every mode other than FALLING is being treated as rising edge detection (cores/arduino/Interrupts.cpp, line 49):

void attachInterruptParam(PinName interruptNum, voidFuncPtrParam func, PinStatus mode, void* param) {
  detachInterrupt(interruptNum);
  mbed::InterruptIn* irq = new mbed::InterruptIn(interruptNum);
  if (mode == FALLING) {
    irq->fall(mbed::callback(func, param));
  } else {
    irq->rise(mbed::callback(func, param));
  }
#ifdef digitalPinToInterruptObj
  digitalPinToInterruptObj(interruptNum) = irq;
#endif
}

According to this old forum post, you can detect both rising and falling edges on an interrupt. How would I go about implementing and testing this change? Thanks!