debounce in an interrupt

Discussion in 'Embedded Systems and Microcontrollers' started by bug13, Mar 11, 2015.

  1. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Hi guys

    I am working on a project, it's a battery power device. So the device needs to sleep as much as possible. And I don't want to use delay within interrupt to debounce.

    The interrupt is triggered by a push button. Thanks guys!

    Code (Text):
    1. uint8_t global_var_state_1;
    2. uint8_t global_var_state_2;
    3. uint8_t global_var_state_3;
    4.  
    5. while(1)
    6. {
    7.     //state machine bases on
    8.     //input from global variables
    9.     sleep();
    10. }
    11.  
    12. void interrupt buttonPress(void)
    13. {
    14.     //debounce (how? don't want to use delay here)
    15.    if (button_press_is_valid)
    16.     {
    17.         //change values of global_var
    18.         //for state machine.
    19.     }
    20. }
     
    Last edited: Mar 11, 2015
  2. MrChips

    Moderator

    Oct 2, 2009
    12,416
    3,354
    Do you have a timer? Use that to create another interrupt.
     
  3. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Yes I have a timer, what do you mean? The interrupt is only triggered by user input(push button). Do you mean using timer to keep a time base?
     
  4. MrChips

    Moderator

    Oct 2, 2009
    12,416
    3,354
    After your interrupt from the button, turn off the interrupt, set the timer to interrupt after 50ms and go back to sleep.

    (I'm going back to sleep now.):)
     
    bug13 likes this.
  5. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    What mystery function does this button start off?

    A complete answer would require knowing lots more then there is a button doing "something."
     
  6. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    The button interrupt will just change the value of a couple global vars, and increase the counter by one. There are three buttons in total.

    Code (Text):
    1.  
    2. uint8_t global_var_state_1;
    3. uint8_t global_var_state_2;
    4. uint8_t global_var_state_3;
    5.  
    6. while(1)
    7. {
    8. //state machine bases on
    9. //input from global variables
    10. sleep();
    11. }
    12.  
    13. void interrupt button_01_Press(void)
    14. {
    15.     //debounce (how? don't want to use delay here)
    16.    global_var_state_1 = 0;
    17.    global_var_state_2 = 1;
    18.    global_counter++;
    19. }
     
  7. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Instead of directly setting these global state variables use the ISR to set global button flags that the main code can detect, debounce, and process. That's one general way to get the debounce out of the ISR to respond to other events.

    Not much more can be said as are still leaving your device function as a mystery.
     
    bug13 likes this.
  8. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    If the issue is "//debounce (how? don't want to use delay here)" then what you could do is run a repetitive timer counting up (say) milliseconds during the time when the button is not pushed, up to some maximum. Then as soon as the button is pressed, you check that total and if it's found to be at its maximum, do whatever the button does and reset the count to zero. But if there's a second or third closure of the button contacts, the intervening bounce time won't be enough for the counter to reach its limit, so those instances can be ignored. Note that here you're not waiting for the button contacts to become stable, but waiting for a button operation after a period of stability.
     
    bug13 likes this.
  9. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Oh, I misunderstand your last replay.

    So there are two buttons, and one lower power PIR sensor.
    SW_Power_ON - connected to interrupt pin
    SW_Power_OFF - connected to interrupt pin

    For the end user, power off is PIR_Disable, power on is PIR_Enable. And the PIR sensor is connected to one of the interrupt pin too.

    when SW_Power_ON is pressed:
    A special sequence of LED is displayed.

    when SW_Power_OFF is pressed:
    A different sequence of LED is displayed.

    And don't ask me why I can't just hook up a PIR sensor with a mechanical switch. This is how the user is requested, and this is how I will give to the user.
     
  10. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    You need a "rastering" interrupt, like 20 to 50 msec., then you just set a flag, and call your tasks.

    One could be to check keys, and update their variables.
    you only need 3 states: 0, 1, and 2.

    Then you can also test the variables if one has reached 2.
     
  11. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    So one button turns it on, another turns it off.

    ON turns it ON till OFF is hit.

    OFF turns it OFF till ON is hit.

    And you need to debounce that because?
     
    RamaD likes this.
  12. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Oh I forgot to mention the counter++ on each button.
     
  13. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    And what does this mysterious counter do? Is there a second function of these buttons?

    Are you just counting turn on and turn off, or are you also setting some other function?
     
    Last edited: Mar 13, 2015
  14. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Yes just counting turn on and off.
     
  15. Flare_Guy

    New Member

    Nov 18, 2012
    13
    1
    Debounce in hardware using an RC. That way you do not have to waste battery power to determine if it was a valid key press.

    [​IMG]
     
  16. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Excellent. Now we see the whole function. Good news: you have no need to do any debouncing at all.

    Why not? Over the long term # time turn off = # times turn on. Even over the short term these never differ more than 1.

    So let's press the ON button: device wakes, disables whatever sleep mode it is in, exits the ISR and goes about it's business. Should the button bounce for another trip to the ISR none of these actions have any affect the 2nd or 200th time they get performed. But I would set a flag bit somewhere for turn off.

    Now press the OFF button: the ISR increments the counter and calls sleepy time. Now there is a conflict if the OFF button bounces because each bounce wakes you up just long enough for the counter to get incremented. That is why the flag was set at turn on: when going to sleep check the bit: ONLY if set inc the counter, then clear the flag and go to sleep.
     
    bug13 likes this.
  17. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    I frankly disagree.
     
  18. GopherT

    AAC Fanatic!

    Nov 23, 2012
    5,984
    3,720

    That's a crazy hypothesis and even crazier expected improvement.
     
  19. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Hi guys

    Just some feedback, I have decided to use this method because it's easier, and I don't need a timer to keep track of the time. No extra timer means less power consumption during sleep.

    Thanks all your replies, as always, every reply gives me something to think about about, and I learn something new. And something I can use on other project even I don't use it on this project.
     
Loading...