Interrupt used by switch fires at strange times

I have been seeing this strange behavior on a few of my devices which I wanted to ask the community about.

I have a momentary on switch connected from D3 to 3.3v which is used as a button.
The setup for D3 is:

 int button = D3;
 pinMode(button, INPUT_PULLDOWN);
 void setup()
   pinMode(button, INPUT_PULLDOWN);
   attachInterrupt(button, doButtonAction, RISING);

 void doButtonAction()
   Serial.print("doButtonAction triggered\n");
   delayMicroseconds(200000);  // helps with debounce
   if (!isHelpNeeded)
     doSetStatusRed = true;
   else //if (isHelpNeeded)
     doSetStatusGreen = true;

The button works fine. When pressed the interrupt fires and sets a global variable which is handled in the loop() function. One part of which is lighting D7. The loop{} code is not relevant to the button operation so I excluded it here.

What happens once in a while is that I go to do a voltage measurement, touching a probe to ground, and the interrupt fires. No, the switch didn’t close, I had an ohm meter on it while troubleshooting this. I have touched the outside of the usb connector with the usb cable before going to connect it and the interrupt will fire.

I have not been able to figure out what is causing the interrupt to just fire once in a while. There is nothing else connected to D3 in the circuit. DAC is not in use, and one reason I moved this over to D3.

Any ideas on why the interrupt may be firing at these times?

@brettski, putting a delay in the ISR is not a good idea. If you search in the forum for “button debounce interrupt” you will find some code suggestions.

The most likely reason you are seeing false triggers is due to the “weak” pull-down (~40K ohms) used in the STM32. I suggest you add a stronger (2.2K to 4.7K ohms) external pull-down. The lack of a strong pull-down makes the pin susceptible to noise as you saw for yourself.


Thank you @peekay123. If I recall correctly the delayMicroseconds() isn’t a huge issue in the ISR and thus only being 200ms. Though I will stick it on my backlog to refactor that bit of code to check for last trigger.

For pull-up resistor, if I add an external one, I assume I then change pinMode(button, INPUT_PULLDOWN); to pinMode(button, INPUT); so those two resistors are not running in parallel affecting actual resistance. I guess it doesn’t mater that much lowing the overall resistance a bit 1/(1/40k + 1/4.7k) = 4206

@brettski, a delay in an ISR causes the ISR to block other equal or lower priority interrupts for that long which is never a good idea. As for the resistor, you are correct!

It can’t be stressed enough what @peekay123 said.
Interrupt routines should return within microseconds not milliseconds. I’d even kick the Serial.print() out of the ISR.

So even if it doesn’t cause troubles for your particular project, it’s a bad, bad habit and should never be even considered, since one of these days it may cause troubles and then the question arises: “Why now, I’ve always done that?”

Never starting the wrong way prevents you from having to track back.
Unlearning bad habits is harder than never starting them :wink:


I agree and the Serial.print() was their solely for troubleshooting. Thanks for the feedback @ScruffR!

I bumped the backlog item to the top to refactor the debounce based on both of your very strong objections! Doing it now :slight_smile:

Thanks much!