External Interrupt crash

Hello, I am trying to raise an interrupt when a button connected to pin 3 is pressed, so on the RISING edge of pin 3. The code I run is:

int buttonPin=3;
int button;

void setup(){
  Serial.begin(9600);
  pinMode(buttonPin,INPUT);
  
  // Attach interrupt routine to pin 3. Raised on RISING edge!
  attachInterrupt(1,buttonHandler,RISING);
}

void loop(){
  button=digitalRead(buttonPin);
  Serial.print("button:");
  Serial.println(button);
  delay(40);
}

void buttonHandler(){
  Serial.println("BUTTON ON!!");
}

So I control button value in each loop and when it turns ON the routine buttonHandler should be executed.

The problem is that sometimes it is executed more than once and it always let arduino crash, in the sense that arduino stops running after the execution of the routine. I need then to reset it.

How is that possible? Does anyone have any suggestion?

Thanks

It's probably button bounce.

You should see this thread: http://arduino.cc/forum/index.php/topic,110756.0.html

Thanks a lot, I guess it was that problem. I tried to disable interrupts and the re-enable them and it seems to work, even though it still executes the routine twice on Rising edges.
By now I do not have the components to try the debounce circuit, but I will try when I'll got them.

Thanks again!

Interrupt service routines are supposed to be very, very fast.

void buttonHandler(){
  Serial.println("BUTTON ON!!");
}

Serial printing is NOT fast, by any stretch of the imagination, regardless of the baud rate. Enough said.

Is there some reason that the button must be read via an interrupt, as opposed to polling it? A software debounce algorithm could then be used as well, eliminating the need for additional circuitry.

PaulS:
Serial printing is NOT fast, by any stretch of the imagination, regardless of the baud rate. Enough said.

The serial buffer isn't particularly large. With bounces it might try to send that message 20 times. The buffer fills up, it waits for an interrupt to empty it, that doesn't happen inside an ISR so it "crashes". Really, it is just waiting forever for interrupts to be enabled again.

Ok, so what I should do is using Interrupts for really fast tasks. But how can I determine if is it fast enough?

Is there some reason that the button must be read via an interrupt, as opposed to polling it? A software debounce algorithm

The problem is that I am implementing a Domain Specific Language to automatically generate Arduino code, and in the language I defined the concept of Interrupt. But when the user declares an Interrupt then I have no control on what will be written in the handler.
So I need to know what is allowed and what is not, so to report it to the user.

What do you mean with software debounce algorithm?

Thanks

So I need to know what is allowed and what is not, so to report it to the user.

Anything that takes a long time or messes with other interrupts.

I am implementing a Domain Specific Language

A what?

It's a specification language in which a user can specificy how the system is composed (which sensors, actuators...) and how they behave (interrupts, polling, tasks..). Then the interpreter automatically generates all the Arduino code needed, leaving to the user the specification of small parts of the code (the business logic). Basically I generate the skeleton and the user adds some little parts once everything is generated.

Mirco_b:
It's a specification language in which a user can specificy how the system is composed (which sensors, actuators...) and how they behave (interrupts, polling, tasks..). Then the interpreter automatically generates all the Arduino code needed, leaving to the user the specification of small parts of the code (the business logic). Basically I generate the skeleton and the user adds some little parts once everything is generated.

It seems to me that neither you nor your users are taking responsibility for timing control, so I suggest you need to design your architecture so that no control is needed. To start with, I'd say that nothing user defined should happen within an interrupt. I don't know what you're using interrupts for, but look for ways to do it without involving interrupts.

Yes it's true, when I was implementing the interpreter I couldn't try interrupts because I did not have enouh components and in Arduino documentation there is no reference to these kind of problems.
Of course I should re-think their usage...

Mirco_b:
Ok, so what I should do is using Interrupts for really fast tasks. But how can I determine if is it fast enough?

...

Mirco_b:
Yes it's true, when I was implementing the interpreter I couldn't try interrupts because I did not have enouh components and in Arduino documentation there is no reference to these kind of problems.

The meaning of these words strangely eludes me.

Mirco_b:
What do you mean with software debounce algorithm?

Buttons and switches, being mechanical beasties that involve springs, levers, etc., often do not cleanly make or break a circuit. For example, when closing a switch, it may not just be open one moment and closed the next, but it goes through a transition phase where the contacts open and close rapidly (bounce); this may last some milliseconds. This is of course the opposite of what is usually desired in a logic circuit, where we want a single, clean transition from one state to the other. Most logic circuits are fast enough to react to each bounce, so a single actuation of the switch may be seen as dozens of state transitions by the circuit. Mitigating this behavior and transforming it into a single, clean transition is called debouncing, and can be addressed with either hardware or software. See Switch - Wikipedia

Additionally, a microcontroller circuit may handle a switch in various ways. One way is via interrupts, another way is "polling" or frequently reading the switch state.

I'm not familiar with writing DSLs, but in this case, if the language is intended to address more than fairly simple use of common sensors, etc., it will need to comprehend various applications of said sensors. Another example with switches, depending on how they are wired, the logic may be inverted or not. So a button switch could give a high logic level when pressed if wired one way, or a low logic level when pressed if wired differently. It's also possible for a switch to be used in multiple modes in a single circuit. I have a couple projects where a button generates an interrupt in one state, but is polled when the circuit is in another state. For the DSL to be really robust, it would have to allow for such things.

Ok thanks.
I will try with hardware debounce and I will look for a sotware algorithm too. If I succeed to implement it via SW I can let the user define small interrupt routines and that should be one more feature of my language...

A workaround, incase this helps anyone.

bool interruptFlag = false; //Declare a global variable for the interrupt flag

void ISR(){                       //Your interrupt function

    interruptFlag = true;         //Set the variable to true as soon as an interrupt occurs

}

void loop(){                     

    if(true == interruptFlag)  //Check continuously if an interrupt was triggered
    {

        noInterrupts();            // Disable interrupt (optional). This may somewhat help with the debouncing

        Serial.println("Button Pressed");  //Do your thing

        interruptFlag = false;  //Set the interruptFlag back to false

        interrupts();   // If disabled earlier, enable the interrupt again

    }
}

Note: This is just a code snippet. You still need to setup you interrupt pins in setup() for it to work. (mentioning this just in case)

        noInterrupts();            // Disable interrupt (optional). This may somewhat help with the debouncing

        Serial.println("Button Pressed");  //Do your thing

        interruptFlag = false;  //Set the interruptFlag back to false

        interrupts();   // If disabled earlier, enable the interrupt again

Printing serial data relies on interrupts, usually.

preludetomadness:

bool interruptFlag = false; //Declare a global variable for the interrupt flag

Should interruptFlag be volatile?