JeremyBlum.com

v3.1

Tutorial 10 for Arduino: Interrupts + Debouncing

| 122 Comments

This video was featured on Hackaday.com on 3/8/2011
This tutorial was featured on the official Arduino blog on 3/9/2011

Interrupts are an extremely useful, yet often feared element of microprocessors. Interrupts allow you to run a program, while still being able to react to asynchronous input from the outside world. On many platforms they can be confusing to implement, but the arduino makes it easy! In this week’s episode, I’ll show you how to use a hardware-debounced button to activate a hardware interrupt on the arduino. I’d suggest you go check out episode 2, where I initially introduced button debouncing, if you haven’t already. I won’t be covering timer interrupts in this episode, since I recently wrote an extensive blog post about using them. Enjoy the video!

EDIT: You can find a great run-down of debouncing techniques and problems here: http://www.ganssle.com/debouncing.htm (Thanks Jope)

 

You can download the files associated with this episode here:

GNU GPL License Distributed under the GNU General Public (Open-Source) License.
Please Attribute and Share-Alike.

122 Comments

  1. I would like a suggestion on execution of an interrupt only on the condition that the value change is retained for like 10 seconds. I would like to know if the hardware and software solutions/

  2. Dear mr Blum,

    Your Schmitt trigger debounce sketch is very helpfull for me.
    My question is: can this sketch be changed in a single state switch. (When the switch is pressed, the pinled is on and when released it is off). And yes, how?

    Greetings,

    Erik

  3. hi i am using intrupts with in intrupts while i am doing it i am experiencing different problems
    1) the code suddenly stops to function
    2) when ever interrupt is called with in an interrupt i cannot predict the behavior

    • That’s because you can’t do interrupts within interrupts. If you think of it like a hierarchy, interrupts are pretty much at the top of the totem pole. When an interrupt happens, it takes almost top priority. If you put another interrupt within an interrupt, your Arduino gets confused since they both have the same level of priority, and thinks well, which one should I be doing? This interrupt, or that interrupt? And that’s why you have unpredictable behavior. A simple example is you can’t use the delay() within an interrupt. You will get unpredictable results, ranging from the whole Arduino just hanging to weird results like it does one thing but not another. Your interrupts should be as short as possible, because everything else is being put on hold until your interrupt completes. If you’re trying to do an interrupt within an interrupt, then you need to find another way to do whatever it is you’re doing. Chances are, there is a better way to do it.

  4. Hi Jeremy,

    Great tutorials, great work.. no words.. learned a lot thankyou.

    I am working on building a kind of pressure sensor to trigger a flow in java code.
    I cant figure out what is the best way to recive that trigger, I want to send “true” as long as the pressure is above some value (like a button).

    Thanks,
    Guv

  5. Dear Mr. Blum

    Can i make pushbutton for clock input?for example 4026?
    so everytime i press the button it will give the clock falling edge input,without arduino it works because it just a simple seven segment counter, but now the problem is i want to add arduino+xbee so i can wirelessly input the clock with button. I want to make a wireless scoreboard :)
    Great tutorial anyway ,it really helps, thanks you :D

    Regards,

    Anasthasia

    PS : sorry for my bad english, it’s not my native language
    i’m a beginner :)

  6. hey Jeremy.. I am new with the arduino board. Im am designing a parking lot with two floors. with four parking space each. the problem is i have created both floors separately. When I try to put it together my program doesn’t work. I have also used two interrupts for my arduino uno board so that the user can choose the floor they want to park but the spot will be chosen automatically. my problem is im not sure how to write the coding for two separate interrupts in my program. Can u help me?

  7. Pingback: Arduino Interrupts and Debouncing -Arduino for Projects

  8. Hi Jeremy,

    Love the videos use them for refernce all the time if working on something new with the arduino. My question is, can a interrupt pin be defined as a normal button and an interrupt? For example:

    int buttonTwo = 2; // pin 2
    int buttonInt = 0; //pin 2

    void loop()
    {
    noInterrupts();
    // code that would use buttonTwo
    Interrupts();
    // code that would involve buttonInt
    }

    Thanks

  9. Hi Jeremy, please tell me the time constant, if you use a key to shorten a capacitor. Is it allowed?
    Current should be very, very high. So that it is possible to make a damage or to reset the Arduino?

    • I don’t understand what you are asking.

      • Hi,

        I think he asked about button connected to capacitor.
        When U push the button it will connect capacitor + to the ground.
        What about current? It will be huge.

        • Yes, theoretically if the capacitor discharges into zero ohms then you get infinite current. Practically, though, there is internal resistance in the cap; and the wires themselves will have some small resistance. If you model the resistance of the cap and the wires as one ohm, then when you close the switch you have a one ohm resistor across a 10 uF cap. Time constant equals 1*10e-6 = 10 us. It takes five time constants to completely discharge the cap, i.e. 50 us.

          When you close the switch you have five volts discharging into 1 ohm = 5A. After one time constant this current drops by 63%, i.e. to 1.8A, and so on. After 5 time constants (50us) the current is zero. Most small circuit wiring can handle this current for this duration. Additionally, and probably more important than the 1 ohm resistance of the circuit, is the inductance. The inductance of the wiring and the capacitor plates will limit any current surge (dI/dt) that can flow in the circuit. Shorting a small capacitor charged to 5V is probably not going to burn out any but the teeniest, tiniest wires.

  10. huh,

    when i add the capacitor this circuit got a delay on it.
    When I press my button it does exactly what it needs to do,
    but fast paces get lost in -what i expect- is the discharging of the capacitor???
    needs like several 100’s of milliseconds…?

  11. Hi Jerry,

    Very Nice and useful tutorial and thank you very much. I need your help in the following:-

    Currently I am using a Rotary switch to select a sine wave source from multiple Sine wave sources.

    I want to move to soft switch(s) instead of the current mechanical switch in other word Micro controller based. Since this is not just a logical voltage output (like transistor output or straightforward) and hence having difficulty to design.

    Requesting your help in this regard?

    Thanks in advance,
    Pradip3

  12. Hey Jeremy! Am a great fan on all your tutorials! Thanks so much for sharing your knowledge!

  13. Hi Jeremy, maybe you help me ;)

    There is the code:

    #include
    #include

    void toggle()
    {
    detachInterrupt(0);

    //Message to send:
    const char *msg = “ALERT!”;
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx(); // We wait to finish sending the message
    // delay(1000);We wait to send the message again
    }

    void setup()
    {
    pinMode(2, INPUT);
    vw_set_ptt_inverted(true); // Required by the RF module
    vw_setup(2000); // bps connection speed
    vw_set_tx_pin(3); // Arduino pin to connect the receiver data pin

    }

    void loop()
    {

    attachInterrupt(0,toggle,RISING);
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
    }

    Arduino awaits for HIGH signal on INT0, wakes up and sends the message via rfm12b. After that it should come back to sleep mode.

    The problem is that is stucks at interrupt looop(toggle). I can see it with current measuring: it starts with 0.1uA, after the HIGH comes it awakes up, but never coming back to sleep even if the pin2 is low. Do you know where could be thie problem? I was trying also with HIGH and Change as an interrupt parameters, but without positive results.

    Regards,
    Jakub

  14. Pingback: Re-programmable IR Camera Remote for Sony NEX-5 | Mayank Joneja

  15. Hi Jeremy

    Bit late but I wanted to point out that the addition of a switch across the capacitor does not incur a time constant of RC as you indicate

    It is effectively short circuit and therefor R=0 or as close as to be irrelevant

    It is the recovery back to a logic 1 that is relevant here and this is based on the time constant RC

    your circuit is correct, just the description is a little off, once the cap is discharged (Almost instant) it does not get back to a logic one right away (RC time constant) and therefor de-bounces using the hysteresis of the Schmidt trigger IC. As i Said, circuit is good, just correcting the description

    Good tutorial

    Thanks

    Peter

  16. Interrupts within interrupts are not viable. You CAN have multiple interrupt sources, e.g. a pin interrupt and a timer interrupt. Different interrupt sources have different ‘priority’ and are handled according to that priority. Check out the ATMEL data sheet for the device you are using. If you are using an Arduino Uno check out the ATmega328 data sheet, specifically sections 7.1, 7.5 and 12. Section 12 describes all the interrupts and their priorities. If you plan to use multiple interrupt sources be aware that it can get very complicated. All I can say is, “Good luck!”

    Kevin H.

  17. How should I probe further to develop an idea of my own? Where can I find the relevant material(as in algorithms, hardware designs etc) for the same?

    Thank you for all your guidance!

  18. how would you use the interupt function if you are using two switches. one to control speed of the fan and the other to switch power on and off.

  19. how to get the interupt function to work if you are using two switches. one to control speed of the fan and the other to switch power on and off.
    i need help with this code:

    int switchPin = 2; //interrupt 0
    int motorPin = 9;
    int offPin=3; //interrupt 1
    boolean lastButton = LOW;
    boolean currentButton = LOW;
    boolean lastButton2 = LOW;
    boolean currentButton2 = LOW;
    volatile boolean motorOn = false;

    int motorLevel = 82;

    void setup()
    {
    pinMode(switchPin, INPUT); //set button as input
    pinMode(offPin, INPUT); //set button as input
    pinMode(motorPin, OUTPUT); // set motor as output
    attachInterrupt (1,powerbutton,CHANGE);

    }

    boolean debounce(boolean last)
    {
    boolean current = digitalRead(switchPin);
    if (last != current)
    {
    delay(10);
    current = digitalRead(switchPin);
    }
    return current;
    }

    boolean speedup(boolean last2)
    {
    boolean current = digitalRead(offPin);
    if (last2 != current)
    {
    delay(10);
    current = digitalRead(offPin);
    }
    return current;
    }

    void loop()
    {
    // speedup off the fan
    currentButton2 = speedup(lastButton2);
    if (lastButton2 == LOW && currentButton2 == HIGH)
    {

    motorLevel = motorLevel + 82;

    }

    lastButton2 = currentButton2;
    if (motorLevel > 255) motorLevel = 82;

    analogWrite(motorPin,motorLevel);
    }

    void powerbutton()
    {
    currentButton = debounce(lastButton);
    if (lastButton == LOW && currentButton == HIGH)
    {
    motorOn = ! motorOn;

    }

    lastButton = currentButton;

    digitalWrite(motorPin,motorOn);
    }

  20. Hi, Jeremy
    I’d like to know what hardware do you use
    I’m interested in schimtt’s trigger especially.

    Thanks, Vladimir

  21. how we read these pde files?

  22. Is this necessary to use Schmmit-triger ecc for the button or a small capacitor to make it low is ok? (to use FALLING)

  23. Hi Jeremy,

    Thanks for the awesome video tutorial, works great.
    I’d like to know how you would implement hardware debounce if you have multiple switches connected to a single interrupt pin.
    Is this possiable?

    Regards,
    Jaun

    • Why would you want to connect multiple switches to the same interrupt pin? You wouldn’t be able to tell which one is being pressed.

      • Thank for the reply.
        The Idea was to save some pins on the ATMega328 chip, so I could connect multiple switches to a analog pin with different resistors on them and then calculate which button was pressed by looking at the reading on the analog pin.

        I Then do some custom interrupt settings to enable interrupts on analog pins.
        cli(); // switch interrupts off while messing with their settings
        PCICR =0x02; // Enable PCINT1 interrupt
        PCMSK1 = 0b00000111;
        sei(); // turn interrupts back on

        But having said all that the best would probably be to use something like a MCP23017 that supports interrupts or will that not work.

      • Perhaps think of limit switches at each end of a CNC axis. If the X-axis is increasing and we hit a limit switch, we know we have exceeded the allowable size of the X-axis. If we are decreasing our X-axis value and hit a limit switch, then we have returned to zero. As the number of interrupts is limited, it makes sense to minimize their usage.

  24. Hi Mr Blum
    Thanks for this example about interrupts but I do think it is mainly just an example and not enough of a tutorial about WHY and HOW are interrupts needed. You mention it is better with them but perhaps you could give more explanations there. An example is not a good demonstration, it is just an illustration. So, I have understood how you do it in this very case but still would have an enormously hard time on any other cases.
    In short, here are a few questions which might help:
    – More cases where interrupts are needed and WHY so
    – Explanation of the syntax of the interrupt
    – Some interrupts are provided by the Arduino hardware, some are not: what is the global rule behind those ?

    Thanks and also your book is indeed a gret help !

  25. Hardware-debouncing can be done easier. Use the internal pullup-resistor and let the button connect to ground. A parallel capacity of 200nF parallel to the button does the trick for most pushbutton types.

    Some code for testing the debouncing on interrupt 0:

    /*
    Debouncing Test for Interrupt 0 Button
    The button connects Pin 2 to Ground,
    Parallel to the button, a capacity of 200 nF is attached.
    Achim Berg, 2014-07-17
    */

    volatile int count = 0;
    int lastCount = 0;

    // the setup routine runs once when you press reset:
    void setup() {
    // initialize serial communication at 9600 bits per second:
    Serial.begin(9600);

    //Pin 2 fires Interrupt 0
    pinMode(2, INPUT_PULLUP);
    attachInterrupt(0, countUp, FALLING);
    }

    void countUp()
    {
    count++;
    }

    // the loop routine runs over and over again forever:
    void loop()
    {
    if(count != lastCount)
    {
    if (count > lastCount + 1)
    {
    // we have bouncing:
    Serial.print(count);
    Serial.print(“–>”);
    Serial.println(count – lastCount);
    }
    else
    {
    // no bouncing
    Serial.println(count);
    }
    lastCount = count;
    }
    delay(1); // delay in between reads for stability
    }

  26. Pingback: [Arduino #23] Interrupts | Curious Seyoung

  27. Hi Jeremy,

    great video! How would i customize the circuit to work with an Arduino Due which has 3.3 V logic level and not 5 V like the Uno?

    Thanks,

    Robert

Leave a Reply

Required fields are marked *.