Multiple (both Hardware) Interrupts firing simultaneously on UNO

Hi guys,

I'm fairly new to the Arduino and I'm trying to implement a functionality using multiple pushbuttons in my code. The idea is that one pushbutton is used to switch between 3 different states, while the other detects short and long presses. Both buttons work (apart from some minor debouncing I need to take care of on the hardware side of things). However the issue I'm facing is that no matter which button I press, both interrupts get fired simultaneously. I'm using the two hardware interrupts on the Arduino UNO. They're set for INPUT and grounded in their default state. When the button gets pushed, the 5V line (coming from the same UNO) causes the pins to go HIGH.

The code is attached below. I'd appreciate your advice to help me figure out what I'm doing wrong.

Thank you.

int Countbutton = 2;
int Pressbutton = 3;

//long buttonTimer = 0;
//long longPressTime = 250;

volatile boolean buttonActive = false;
//boolean longPressActive = false;

volatile int count = 1;
volatile unsigned long PressTime = 0;
volatile unsigned long ReleaseTime = 0;
volatile unsigned long TotalTime = 0;

void countISR() {
     count++;
}

void setup() {
     Serial.begin(9600);
     pinMode(Countbutton, INPUT);
     pinMode(Pressbutton, INPUT_PULLUP);
     attachInterrupt(digitalPinToInterrupt(Countbutton), countISR, RISING);
     attachInterrupt(digitalPinToInterrupt(Pressbutton), PressISR, CHANGE);
}

void loop() {
   if (count>1){
   Serial.print("Number of counts ");
   Serial.println(count);
   Serial.println("\n");
   }
     if (count >= 4 )
     {
      count = 1;
     }
/*  Serial.print("The time at which the button was pressed ");
    Serial.println(PressTime);
    Serial.print("The time at which the button was released ");
    Serial.println(ReleaseTime);
    Serial.print("Button active ");
    Serial.println(buttonActive);
    */
      if (TotalTime>0){ 
         Serial.print("The total time for which the button remained pressed ");
         Serial.println(TotalTime);
        if (TotalTime>5000){
          Serial.println("I just sensed a long press");
          }
          else {
          Serial.println("You just pressed the button");
          }
       TotalTime = 0;
//       Serial.println("\n");
//       Serial.print("Button active ");
//       Serial.println(buttonActive);
      }
    
//    Serial.print("Button active ");
//    Serial.println(buttonActive);
//    Serial.println("\n");
//    delay(500);
}

void PressISR(){
  if (buttonActive == true){
  ReleaseTime = millis();
  TotalTime = ReleaseTime - PressTime;
    buttonActive = false;
  }
 else { 
  PressTime = millis();
  buttonActive = true;
}
}

Can you post the output that shows that both ISRs are firing when you only press one button?

If your buttons are wired as you say, that shouldn't happen. Can you show a schematic?

Unless The Flash is pushing the buttons, push buttons are really not the sort of thing that require an interrupt. Unless you can press and release the button in under a millisecond you'd be better off polling them from loop.

Swayer: They're set for INPUT and grounded in their default state. When the button gets pushed, the 5V line (coming from the same UNO) causes the pins to go HIGH.

     pinMode(Countbutton, INPUT);
     pinMode(Pressbutton, INPUT_PULLUP);

One is set to INPUT_PULLUP. Could that be the problem?

If not, please include a schematic. From your description, it sounds as though when a button is pressed, there will be a short-circuit from 5V to ground. If by "grounded" you mean using a resistor, what value?

Paul

Are you using pinMode(x,INPUT_PULLUP) ?

I just left the two types of input there since I was trying different combinations of it to see if that would help (I wasn’t sure if using Input pullup on both was causing a short of some kind internally).

I’ve thrown together a quick schematic in paint, since the laptop I’m currently on is too slow to run any of online tools. I am just shorting it to ground via a resistor, and using a capacitor in parallel to take some of the noise out. I’ve tried both 5K and 10 K resistors.

Thank you for helping me out guys. I really appreciate it.

It would be really hard for anyone to read the output since due to a lack of delay the main loop will print "Number of counts 'x'" continuously once the button gets pressed once. However, let me summarize what's happening (and if you set up the circuit and upload the code to an UNO you should see the same stuff happening).

When the pushbutton connected to pin 3 is pressed, the interrrupt PressISR captures the millis() of when the button was pressed, (and simultanously, the count ISR increments the count by one, which it isn't supposed to do). When the button is depressed, the PressISR captures the time of release and stores the time difference in to the variable TotalTime (which reports the Total Time pressed). This variable (TotalTime) is then used by the main loop to determine if the button was pressed.

When the pushbutton connected to pin 2 is pressed, the count increments, (and simultaneously the PressISR launches and captures the time of when the button was pressed, which again, it isn't supposed to do). When the count button is depressed, nothing happens. When the count button is pressed again, the counter increments again and the PressISR treats this second press as a release, and stores the time difference between the two pushes into TotalTime (which it isn't supposed to do).

If I only connect one button at a tie (and comment out the code for the second interrupt) everything works fine and dandy (aside from the noise when the button is released, which again, I need to take care of on the hardware side).

I made a SPICE model of your circuit. I’ll post the picture here, but if you want the model I can post that too. LTSpice is a free download BTW.

button_schematic.png

I don’t know how much you know about electronics so I’ll try to explain in basically. Capacitors behave like open circuits under DC voltages, and like short circuits under high frequency AC voltages. When you use a switch to make a rising edge, the instant when the voltage jumps looks like an infinitely high frequency.

Now if you have a perfect ground, that shouldn’t matter. Look at what happens if you add a little resistance to your connection to ground, however. In addition you’ll have a little inductance back to ground too, which acts the opposite of a capacitor: it behaves like an open circuit at high frequencies and a short circuit at DC. You now have a short circuit between PIN1 and PIN2 for high frequenecies, letting the voltage edge get through to both pins. After the edge is passed, you now have another DC level and the caps go back to looking like open circuits.

button_graph.png

Do you need to fix this? It’d be cleaner if you did and if you were making a PCB then you could do it with good layout techniques. On breadboards it’s not that easy to eliminate all mΩ and fH in your grounds, however.

All of the advice you’re getting to not use interrupts to monitor the buttons is good too. If you polled them in your main loop you’d never see this. I figured I’d explain the strange connection between your INT pins, however.

Edited to add: BTW - did you notice that PIN2 is never at ground in the simulation? That’s caused by the voltage divider created by your 10kΩ and the ~30kΩ pullup inside the AVR. That should really be happening in your circuit. Do you see it with a meter? You might want to decrease the 10kΩ to 1kΩ.

4d32f7b50319a3ed246044d66a5947688cf96cf5.png

Thanks BigBobby, I had a small suspicion that there might some voltage seeping through the ground to the other pin. I’m not a pro at electronics so I didn’t that it was the capacitor causing it. Thank you for the explanation. if I remove the capacitor the performance becomes pretty reliable. However, the pushbutton connected to Pin2 still (occasionally) triggers pin3. Would adding a diode to my circuit fix the short that’s taking place? Any suggestions, on how I should add it?

The reason I need to poll the buttons using interrupts is because eventually the main loop will be doing a lot of work. I might even be communicating over SPI; I need the pushbuttons to act as a high priority function so that, whenever they’re pressed, they get detected. I do plan on creating a PCB down the line. But, for now, I’m just prototyping using breadboards and protoboards.

Thanks again for the help, and for the lesson in electronics. If I understand your simulation correctly, the leakage voltage is about 1.2V when a button is pressed (the blue lline)?

Swayer: Thanks again for the help, and for the lesson in electronics. If I understand your simulation correctly, the leakage voltage is about 1.2V when a button is pressed (the blue lline)?

No, the blue line is the voltage on PIN2 (I really should have labelled the pins 2 and 3 in the schematic, sorry) and it's sitting at 1.2V because of the voltage divider created between R2 and the pullup inside the AVR.

When you close S1, however, the voltage on PIN1 briefly shows up on PIN2, before PIN2 settles back down to 1.2V again.

Did you remove both capacitors or just one? If you only removed one I'd believe that you still had some issues with coupling from one of the buttons to the other pin.

About your main loop getting long, if you're writing it such that it may be busy by human-time standards (like 1s) then you're not going about it the right way. 20ms would be considered a long main loop, but if you polled your buttons every 20ms it'd seem instantaneous by human standards.

ah ok. Hence the blue spike which probably triggers the second interrupt. Cool.

I did remove both of the capacitors, and I tried removing just one, and I tried adding diodes as well.

So, at this point I'm not sure how large the code will be, but your right, it probably won't be more than 10's of thousands of instructions in machine code (20ms). But, even if I do poll the switches in the main loop, I will still need to debounce the switch properly and make sure it doesn't trigger the other switch. I guess I'll go with either D-flip flops or with Schmitt triggers and build a proper debouncing circuit. Any recommendations on which would be better?

Thanks for your help guys, and a special thank you to BigBobby.

Swayer: I guess I'll go with either D-flip flops or with Schmitt triggers and build a proper debouncing circuit. Any recommendations on which would be better?

Thanks for your help guys, and a special thank you to BigBobby.

No problem :)

Personally, I'd do all of my debouncing in software. If you poll at 20mS, don't take action until you've been two HIGHs in a row.

Or you poll when and as often as you can. When you first see the input change from LOW to HIGH, you record the time according to millis(). Then if you see another LOW to HIGH, you can ignore it if less than 20ms have elapsed.

Swayer: The reason I need to poll the buttons using interrupts is because eventually the main loop will be doing a lot of work. I might even be communicating over SPI; I need the pushbuttons to act as a high priority function so that, whenever they're pressed, they get detected.

You still don't need interrupts for the buttons. SPI is super fast. Just don't put any delays in the loop. There's no way you push and release a button in less than a few hundred milliseconds. That's an eternity to the microprocessor. You can do lots of things and still poll your buttons.

Interrupts have nothing to do with priority in code. That is all about how you write the loop code. How the priority over other tasks works out is all a function of where you check the flags the interrupt sets. You can check the buttons in the same place and get the same level of procedural priority.

Interrupts are for things that happen really really fast and transiently. Like microseconds. Push buttons hardly fit that description. You have to stop thinking in human time and think about it in computer time.