Gremlins are causing the wrong interrupt to fire periodically. Please help!

I have two interrupts set up on my Uno attached to two buttons. One buttons will increment a “count” variable by 1, and the other interrupt will set a flag so during the next loop a function will be called to flash an LED the number of times that the value of the count variable is set to.

My circuit looks like this:

Red goes to +5V, browns go to interrupts 0 and 1 (pins 2 and 3), black to neg.

I built a breadboard prototype and everything worked so I went ahead and built out a finished version and this is where I run into a problem.

THE PROBLEM: When I press the button connect to interrupt 1 repeatedly, it will sometimes randomly also fire interrupt 0. I am posting output to serial on each main loop and I can see that when this issue happens it fires the wrong interrupt(0), goes through the main loop a handful of times, and then fires the right interrupt(1).

Here is the actual buildout:

  • The yellow lines show connections under the board.
  • You can ignore all resistors but the top 2 10K resistors. The other are connected to LEDs and not the part of the circuit I’m having issues with.

Note that it is always interrupt 1 that periodically fires interrupt 0. If I switch the wires around I can make either button accidentally fire the other one. It seems like if the flaw was in my circuit design then it would be one or the other button, but it is always whatever button is on pin 3 that has the issue.

Also, if I rebuild this circuit on a breadboard it seems to work just fine - it is only with my build that I have problems, but I can’t identify ANY difference (and yes, I’ve checked multiple times for errant solder bridges and other flaws). The error happens totally randomly, it can be the first press of the button or the 20th.

I even tried a new Atmega328 chip just in case mine was faulty.

This seems like a long shot, but if anyone has any ideas what I might be doing wrong here I would sure appreciate it. I’ve been banging my head against the wall for six hours now on this.

I am fairly confident my issue is not in my code, but here it is anyway:

byte pins[] = {9, 10, 11, 12};
const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int statusLed = 13;

//variables for the trigger IO logic        
volatile int presses = 0;		// variable to store number of presses
volatile long time = 0;			// used for debounce
long debounce = 50;	// how many ms to "debounce"
const byte numPins = 4; // how many leds
int state = LOW;
volatile int fire = LOW;

void setup() {
  for(int i = 0; i < numPins; i++) {
		pinMode(pins[i], OUTPUT);
	}
  pinMode(statusLed, OUTPUT);

  pinMode(buttonPin1, INPUT); 
  pinMode(buttonPin2, INPUT); 
  
  attachInterrupt(0, count, LOW); //pin 2
  attachInterrupt(1, commit, LOW); //pin 3
  
  Serial.begin(9600);
}


void loop() {
  
	String binNumber = String(presses, BIN);
	int binLength = binNumber.length();	
	if(presses <= 15) {	// if we have less or equal to 15 presses
                // here is the scary code
		for(int i = 0, x = 1; i < binLength; i++, x+=2) { 
			if(binNumber[i] == '0') state = LOW;
			if(binNumber[i] == '1') state = HIGH;
			digitalWrite(pins[i] + binLength - x, state);
		}	
	} else {
      for(int i = 0; i < numPins; i++) {
		digitalWrite(pins[i], LOW);
	}
		presses=0;
	}
  if(fire==HIGH && presses > 0) {
    //Fire the printer
    print();
    fire=LOW; //reset firing
  } else {
    fire=LOW;
  }
  debug();
   
}

void count() { 
        if(fire!=HIGH) {
	// we debounce the button and increase the presses
        if(millis() - time > debounce) presses++;
	time = millis();
        }
 
}

void commit () {
   if(millis() - time > debounce) fire = HIGH; //the printer is ready to be fired on the next loop
  time = millis();
}

void print() {
  //temporarily disable the buttons
  detachInterrupt(1);
  detachInterrupt(0);
  
  //print things here
  for(int i = 0; i < presses; i++) {
    	//test code to flash the status led the correct number of presses
	delay(300);	
    digitalWrite(statusLed, HIGH);
    	delay(500);
    	digitalWrite(statusLed, LOW);
	}
  
  //re-enable the buttons
  attachInterrupt(0, count, LOW); //pin 2
  attachInterrupt(1, commit, LOW); //pin 3
}

void debug() {
  Serial.print("Count = ");
  Serial.println(presses);
  if(fire==HIGH) Serial.println("FIRE!"); 
}

Explanation: Pressing interrupt 0 will increase the “presses” variable by 1. The number of presses is shown in binary on 4 LEDs. Pressing interrupt 1 will cause the LED on pin 13 to flash the number of presses.

sam1am: Explanation: Pressing interrupt 0 will increase the "presses" variable by 1. The number of presses is shown in binary on 4 LEDs. Pressing interrupt 1 will cause the LED on pin 13 to flash the number of presses.

Full marks for this wonderfully succinct description. I wish everyone did the same.

Rather than have

attachInterrupt(0, count, LOW); //pin 2

I think you should use

attachInterrupt(0, count, FALLING); //pin 2

...R

Why are you using interrupts to detect button presses? Are you Superman and can press your buttons several million times a second? Instead, poll your buttons to detect when their state changes. If you do this in loop(), you will still be testing them several times each second, faster than a human hand can manage to press them.