Having trouble getting attachInterrupt with CHANGE working


#1

I am trying to use CHANGE with an interrupt and not having luck. I literally have a jumper going from D4 to ground which I am toggling and have D4 setup with…

pinMode(D4, INPUT_PULLUP);
attachInterrupt(D4, setFlag, CHANGE);

The function never gets called, but I can poll the value of the pin successfully and it is accurate. I want to be able to fire on any change (rising or falling) on this pin.


#2

Which version of firmware are you using? Can you post the function for setFlag?

This code should work, I see no issues. How are you triggering the pin externally? A button or some other switch?


#3

I am using Beta 5.

void setFlag() {
    theFlag = true;
}

The switch is just a magnetic switch that is normally closed (to ground).


#4

I have an interrupt on another pin. It seems to start working after commenting out that interrupt.


#5

So you had two interrupts and only one is working?
Not sure if you mean this is resolved or info u still have an issue. Let me know


#6

I already had one. Tried to add the second one and the second one doesn’t work. If I comment out the first one (but leave it as an input) the second one starts working.


#7

Which version of firmware are you using? 1.1.47 only supported one interrupt, any 2.0.50 beta version will support up to 6. If you upgrade, they should both work at the same time.


#8

I am using 2.0.50-beta.5. I am only using this.


#9

Can you post the code with the two interrupts? This should work just fine, not sure why there would be an issue.


#10

I am literally just setting flags with the interrupts. As soon as I comment out the first interrupt (buttonPin) the second one starts working, but even when the interrupt isn’t working polling the pin yields the proper value.

const int buttonPin = D0;
const int doorPin = D1;

void setup() {
    pinMode(buttonPin, INPUT_PULLUP);
    pinMode(doorPin, INPUT_PULLUP);
    attachInterrupt(buttonPin, setButtonFlag, RISING);
    attachInterrupt(doorPin, setDoorFlag, CHANGE);
}

void setButtonFlag() {
    buttonFlag = true;
}

void setDoorFlag() {
    doorFlag = true;
}

#11

Two things. First, can you change the first one to CHANGE? If you do that, does it work?

Second, are the boolean values buttonFlag and doorFlag marked as volatile? Any value that can get updated in an interrupt should be marked as volatile.


#12

I will try that.

I just noticed that in the docs. Not using volatile has been working and I also tried putting a particle publish in the function. What exactly does the volatile option do?


#13

Volatile basically tells the C compiler that the value can change at any time, and that it shouldn’t try to use optimizations.

As an extreme example, look at this code:

bool set = false;

void setup() {
    while(!set) { delay(1); }
}

The compiler, when optimizing, could assume that ‘set’ is never changed and the assembly generated will only actually check the value of it the first time. This is bad, because if you added an interrupt that modified set, it would never be detected.

By declaring it volatile, it forces the compiler to recheck the value of ‘set’ for every iteration of the loop. So if it were to be modified elsewhere (in an interrupt, for example), then it would be detected and your code would work.


#14

Got it.

Did some more testing… using volatile on the variable didn’t help, but changing the original interrupt to CHANGE did make it so that the second interrupt started working…


#15

Thanks! I will take a look, perhaps there is a bug there with mixing interrupt types. The easy fix for now is to use CHANGE always and just read the pin state in the interrupt, only doing to work when the desired state change happens.

I will try and update when I find something more


#16

The item that I didn’t want to use CHANGE for is just a button, so I’m just going to use CHANGE for now and do a detachInterrupt on it when triggered and attachInterrupt after processing do avoid duplicates from down/up movements on the button. Doing it as we speak.


#17

EDIT: Detaching works in the interrrupt, but trying to reattach using attachInterrupt within the condition inside of loop is not working. Checking state of pin on interrupt instead (makes more sense anyway), but should this work?


#18

To clarify the first point, about the CHANGE and RISING, is that code the intended action? There was a PULLUP resistor enabled and you wanted to detect RISING conditions. Would it make sense to use a PULLDOWN resistor in this case?

For the last question, could you post an example of code that recreates the issue?


#19

Could technically have gone with either for this, yes.

Not doing this anymore since checking the state of the pin during the interrupt makes much more sense, but I’d imagine at some point I would want to. Here is an example:

void setup() {
   pinMode(switchPin, INPUT_PULLUP);
   attachInterrupt(switchPin, setFlag, CHANGE);
}

void loop () {
   if (flag == true) {
      flag = false;
      attachInterrupt(switchPin, setFlag, CHANGE);
   }

void setFlag() {
   detachInterrupt(switchPin);
   flag = true;

#20

Performing actions inside of interrupts isn’t normally the best practice. Why would you want to detach and then reattach?