Interrupt

Hello guys,

I'm trying to understand how an interrupt is working so I've tested the code below:

int pin = 13, i = 0;
volatile int state = LOW;

void setup()
{
Serial.begin(9600);
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}

void loop()
{
digitalWrite(pin, state);
delay(1000);
}

void blink()
{
state = !state;
i++;
Serial.println(i);
}

I noticed that when an interrupt takes place in serial monitor appear this:

1
2
3
4

Is this right? I thought that blink() would be excetuted only one time. Therefore I was expecting only the number 1 in serial monitor. How can I modify the code so every time an interrput takes place blink() be excecuted only one time?

I'm guessing here, and assuming you have a push switch on the interrupt pin?

First with mode as CHANGE, presumably you would always get 2: 1st change = press and 2nd change = release.

Then if the switch is bouncy, it might give 2 complete reads for a total of 4?

Guessing though....

what I’m trying to do is to make something happen every second time an interrupt happens. I am using a push button but arduino sometimes stops responding and sometimes seems that interrupt routine is being excecuted not once. Is this right? How can I fix this. For example if I press a button a varible i will take a value 1. If the button is being pressed again tha variable will take the value 2 and so on. Any ideas?

You maybe don't need an interrupt anyway: see my current thread here.

This may do the trick, and much simpler than interrupts.

thank you.

And if you look at interrupts in the ref section you'll be told not to use serial.print etc inside an ISR as it can crash your program.

Mark

katsar:
what I'm trying to do is to make something happen every second time an interrupt happens. I am using a push button but arduino sometimes stops responding and sometimes seems that interrupt routine is being excecuted not once. Is this right? How can I fix this. For example if I press a button a varible i will take a value 1. If the button is being pressed again tha variable will take the value 2 and so on. Any ideas?

  1. Don't use interrupts for button presses, its total overkill. Find one of the button
    libraries that does debouncing for you.

  2. Never call Serial functions or delay() in an ISR, the whole system can hang.

  3. If you do use interrupt for the button your ISR will have to maintain some sort
    of state machine to do the debouncing. You can use RISING or FALLING rather
    than CHANGE in the attachInterrupt call if thats what you actually mean.

If the purpose of your short code is just to learn about interrupts then, of course, any kind of input is fine for triggering the interrupt.

As others have said don't put and Serial.print() statements into an ISR - for one thing, they take too much time. Put your Serial.print() in loop().

Your counter (i++) will let you know how many interrupts have happened.

You can then experiment with RISING, FALLING and CHANGE.

If you have a second Arduino you could write a short program on it to toggle an I/O pin and that could be connected to the interrupt pin. Remember also to connect the Grounds of the 2 Arduinos.

...R

katsar:
I'm trying to understand how an interrupt is working...

Great, you are trying to understand how an interrupt works. A pushbutton is a great way to learn!

How can I modify the code so every time an interrput takes place blink() be excecuted only one time?

the solution to your problem is easier than you think.

If you want to execute the interrupt every other time, just use your math skills...

void blink()
{
  state = !state;
  if state = LOW  // only count when the state goes from HIGH to LOW!!
  {
    i++;
  }
  //Serial.println(i);
}

if you want to toggle it every n times?

void blink()
{
  {
    i++;
    int myInt = i % 3 ;// every 3rd push
    if (myInt = 0) state = !state;
  }
}

added using this:

attachInterrupt(0, blink, CHANGE);

will send an interrupt when the button is pressed and when it is released, as Robin points out.

Use this:

attachInterrupt(0, blink, RISING);

or

attachInterrupt(0, blink, FALLING);

to only once per pushbutton/release cycle