beginner problem with interrupts

I tried to understand interrupts by creating a simple code (shown below). The idea was to have two buttons, each assigned to interrupts. The interrupt functions assigned to the buttons would run independently, and would not be interrupted by the other buttons.

I am getting two unexpected results

  1. pressing a button once causes the serial output to count to 100 twice
  2. pressing button One while the for loop for button Two is executing causes the the code for button One to execute, then the remainder of the code for button Two to execute

Does anyone know why I am getting these results?
Thanks

void setup() {
Serial.begin(9600);
attachInterrupt(0, runButtonOne, RISING);
attachInterrupt(1, runButtonTwo, RISING);
}

void loop() {

}

void runButtonOne(){
noInterrupts();
for (int counter = 1; counter <= 100; counter++) {
Serial.print("One ");
Serial.println(counter);
for (int faker =1; faker < 10000; faker++){
}

}
interrupts();
}

void runButtonTwo(){
noInterrupts();
for (int counter = 1; counter <= 100; counter++) {
Serial.print("Two ");
Serial.println(counter);
for (int faker =1; faker < 10000; faker++){
}

}
interrupts();
}

Take out those noInterrupts(); and Interrupts(); statements, they are not needed as interrupts are disabled globably automatically once inside a ISR function and get reenabled automatically when the ISR returns. That is your button two will not be able to interrupt the button1 while it's executing it's button1 ISR code, and visa versa.

See if that changes your symptoms.

Lefty

Lesson one: Keep interrupts short, no really short, shorter ! :wink:

So remove all the Serial print statements from the IRQ

NNote: the loop with faker will probably optimized away by the compiler, so it does not exist in the executable

You should set a flag in your IRQ and handle the printing in the main loop()

Lesson two: all variables used in a IRQ must be declared volatile.

Try something like code below...

disclaimer: Partial code, not compiled or tested

volatile boolean RBO = false;
volatile boolean RBT = false;

void runButtonOne()
{
  RBO = true;
}

void runButtonTwo()
{
  RBT = true;
}

void loop()
{
  if (RBO)
  {
    for (int counter = 1; counter <= 100; counter++)  
    {
      Serial.print("One ");
      Serial.println(counter);
    }
    RBO = false;
  }

  if (RBT)
  {
    for (int counter = 1; counter <= 100; counter++)  
    {
      Serial.print("Two");
      Serial.println(counter);
    }
    RBT = false;
  }
  ...
}

all variables used in a IRQ must be declared volatile

Variables local to the ISR do not need to be declared volatile.

Oops, you're right..

Making local variables volatile would take some extra instructions and "slow" the IRQ down (only a few cycles but still)