Go Down

Topic: Interrupt triggered once on startup? (Read 640 times) previous topic - next topic

kfreak

Hi,

I am experimenting with PinInterrups on Duemilanove 328 using simple code.

It appears that the Interrupt service routine is triggered once on board startup.

What I want to do:
- Startup --> pin13 LED Off
- Ground pin2 (Interrupt 0) --> Toggle pin13 LED

My code
Code: [Select]
int pin = 13;
volatile int state = LOW;

void setup()
{
 pinMode(pin, OUTPUT);
 digitalWrite(2, HIGH);
 attachInterrupt(0, blink, FALLING);
}

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

void blink()
{
  state = !state;
}


Expected: After startup LED stays off

What happens: After startup LED turn on

How to fix: Change volatile int state = LOW; to volatile int state = HIGH;

Can anyone shed some light on this?

retrolefty

How are you externally causing a interrupt signal for pin 2 to happen (a high to low transition), with a switch?

Lefty

kfreak

A simple wire plugged into 2, which I then touch to the housing of the USB connector.

But even if I do not connect anything to pin 2 the described happens. LED turns on on startup.

Once its started the simple wire described above will toggle the LED.

The board I have came yesterday, and its my first Arduino...

retrolefty

#3
Jun 18, 2010, 01:07 am Last Edit: Jun 18, 2010, 01:07 am by retrolefty Reason: 1
Do a little searching on 'contact bounce". I think you will find that digital input pins are very prone to this problem and when used as a interrupt signal, can cause multiple interrupts of random amount when you wish for just a single transition.

Lefty


kfreak

Hi,

you were right, that was due to "bounce", even though i didnt have anything connected to the pin.

I solved it like this:
Code: [Select]
int pin = 13;
volatile int state = LOW;

void setup()
{
 pinMode(pin, OUTPUT);
 digitalWrite(2, HIGH);
 attachInterrupt(0, blink, FALLING);
}

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

void blink()
{
 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();
 // If interrupts come faster than 200ms, assume it's a bounce and ignore
 if (interrupt_time - last_interrupt_time > 200)
 {
 state = !state;
 }
 last_interrupt_time = interrupt_time;
 
}


Just a question: Is this the recommended way? Apparently millis() stops being updated while in ISR. But then again this is only relevant if you want to have an accurate clock...

floresta

#5
Jun 20, 2010, 05:58 pm Last Edit: Jun 20, 2010, 05:58 pm by floresta Reason: 1
Did you overlook this note that is with the 'attachInterrupt()' information?

Note

Inside the attached function, delay() won't work and the value returned by millis() will not increment. Serial data received while in the function may be lost. You should declare as volatile any variables that you modify within the attached function.


Don

kfreak

Hi,

I've seen this note in the attachInterrupt() page, thats why I asked. Is the debounce of interrupts as I did the recommended way? Comparing a value to millis()? Or is there a "cleaner" or "more efficient" method?



Mitch_CA

They way you've listed is the way that I like to debounce...
I.e. do nothing while the input state is changing quickly.

200ms should be an eternity for any decent electro-mechanical switch.

Go Up