In the following code, why does ISR2
never run?
const int in = 19;
const int LED = 9;
int flag;
void setup() {
pinMode(in, INPUT_PULLUP);
pinMode(LED, OUTPUT);
attachInterrupt(digitalPinToInterrupt(in), ISR2, RISING);
attachInterrupt(digitalPinToInterrupt(in), ISR1, FALLING);
}
void loop() {
if (flag) {delay (100); flag = false;}// debounce
}
void ISR1(){
digitalWrite(LED, LOW);
// Turn Off the motor, since, Limit Switch was engaged
flag = true;
}
void ISR2(){ // Limit Switch was disengaged.
digitalWrite(LED, HIGH);
delay(100); // Debounce, so I do not receive spurious FALLING edges from this.
}
Does the Arduino not allow you to attach two interrupts on the same pin even if the interrupts are programmed for different events?
In my setup, pin 19 gets a signal from a limit switch used in a motion control setup. When the limit switch is engaged, the in
pin gets LOW
signal. Thus, I first see a FALLING
edge followed by RISING
edges and FALLING
edges due to mechanical bounce. I handle the debouncing correctly in this case.
However, imagine the Limit Switch was sitting in engaged state for a while, and then I reverse the motor causing the Limit Switch to disengage, this will send a RISING
edge followed by FALLING
and RISING
edges. I need to ignore these edges since nothing is in danger. The ISR2
was written with purpose of capturing the first RISING
edge when the Limit switch disengages, and then debouncing it so that the following FALLING
edges are ignored. But now that ISR2
never gets called, how can I deal with this situation?
P.S. My microcontroller is ATMEGA 2650, It's a Arduino Mega board.
ISR2 never runs because there can be only one interrupt service routine for any interrupt source and you have replaced ISR2 with ISR1 as the sercice routine for this interrupt. If you reordered your code and attached ISR1 before ISR2 then you might see ISR2 run but not ISR1.
A typical microcontroller has an interrupt vector table that associates an interrupt service routine with each interrupt source. There can be only one service routine for each interrupt source. If you assign an new service routine then you're replacing the old service routine. There are not separate service routines for the rising and falling edges. Rising versus falling edge is a configuration setting for the interrupt source to determine when that interrupt should fire. The interrupt source cannot be configured to fire on both edges simultaneously.
However you may be able to reconfigure the interrupt for the other edge after you have received the interrupt for the first edge and debounced the transition. This way your code will ping-pong back and forth configuring for one ISR and then the other.
Why are you saying that it never gets called? I think that it is called, but you don't notice it because the led does not change its state (because there are bounces).
Anyway, you are NOT debouncing it correctly. Let's do an example: you hit the endstop. ISR1
gets called, so flag
is true. Ok, at next loop the motor will be stopped. But... Now the switch bounces. ISR2
gets called, and the delay
function in it waits for 100ms before exiting the ISR. Result: you delayed the motor stop function by 100ms.
I suggest you to read my answer here, particularly the second case. And I suggest you to use my code instead of yours, since this way you will be able to IMMEDIATELY stop the motor, without bounces nor any other kind of problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With