In this example we create a simple filtering class for Arduino to debounce buttons, after using MegunoLink’s XY Plot library and visualiser to observe the false button activation caused by button bounce.
The Button Bounce Problem
Button bounce refers to multiple high-low transitions in the output signal of a switch as it is pressed or released, in addition to the single transition expected. The signal ‘bounces’ before it finally settles at it’s new level. This is typically caused by mechanical bouncing in the switch. The debounce class eliminates the extra transitions so we get a clean change.
These additional fast transitions are a problem in high speed systems, especially edge-sensitive ones. For example, a high speed counter would count six high-low transitions or ‘button presses’ in the button bounce signal plotted above, as opposed to the single button press by the user.
The delay method of debouncing buttons in software involves waiting for the signal from the button to stabilise before taking action. A simple delay-based button debounce class using the ArduinoTimer feature of the MegunoLink Arduino library can be found in the below example for your debouncing convenience.
Downloads
This example requires our Arduino Library. You can download a ZIP file containing the button debounce Arduino program and bonus bounce plotting Arduino program with MegunoLink interface below.
An Arduino Debounce Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
/* ************************************************************************ Simple Button Debouncer This program demonstrates a simple delay-based button de-bouncing class using the ArduinoTimer class included in the MegunoLink Arduino library. Visit: * http://www.MegunoLink.com to read the matching example post * or to download MegunoLink. ************************************************************************ */ //--------------------Includes------------------------- #include "ArduinoTimer.h" // If missing, install the MegunoLink library: //"Sketch"-> "Include Library" -> "Manage Libraries..." -> search and install //--------------------Class Header------------------------- // Delay-based simple Button Debounce Class class DebouncedSwitch { const int m_uDebounceDelayMs = 25; // Increase if bouncing still occurs const int m_SwitchPin; bool m_bRecentState; bool m_bLastSteadyState; ArduinoTimer TransitionTimer; public: DebouncedSwitch(int SwitchPin, bool UseInternalPullup); bool Read(); }; //--------------------Class Body------------------------- DebouncedSwitch::DebouncedSwitch(int SwitchPin, bool UseInternalPullup) : m_SwitchPin(SwitchPin) { if (UseInternalPullup) {pinMode(m_SwitchPin, INPUT_PULLUP);} else {pinMode(m_SwitchPin, INPUT);} m_bRecentState = digitalRead(m_SwitchPin); m_bLastSteadyState = m_bRecentState; } // Reads pin and returns debounced state bool DebouncedSwitch::Read() { bool CurrentState = digitalRead(m_SwitchPin); if(CurrentState != m_bLastSteadyState) // potential change in steady state { if (CurrentState != m_bRecentState) {TransitionTimer.Reset();} // new transition detected, wait for bounces else if (TransitionTimer.TimePassed_Milliseconds(m_uDebounceDelayMs,false)) {m_bLastSteadyState = CurrentState;} // bouncing should be over by now } m_bRecentState = CurrentState; return m_bLastSteadyState; } //--------------------Globals------------------------- const int ButtonPin = 8; // Pin number of the user's button const int LedPin = 13; // Pin number of the onboard LED bool LastState; // Previous button state seen in loop() unsigned int Count = 0; // Count of button presses seen in loop() // Setup debounced button input with internal pullup: // using DebouncedSwitch MyButton(ButtonPin, true); // instead of pinMode(ButtonPin, INPUT_PULLUP); DebouncedSwitch MyButton(ButtonPin, true); // Connect far side of button to GND, internal pullup will do the rest. // Alternatively, without internal pullup: // use DebouncedSwitch MyButton(ButtonPin, false); // instead of pinMode(ButtonPin, INPUT); //--------------------Setup------------------------- void setup() { // Setup serial for outputting button press count Serial.begin(9600); Serial.println("MegunoLink Button Debouncer"); // Setup last state variable used to detect button changes LastState = MyButton.Read(); // Setup onboard LED pin for indicating button state pinMode(LedPin, OUTPUT); } //--------------------Loop------------------------- void loop() { // Read the debounced button state: // using MyButton.Read() // instead of digitalRead(ButtonPin) bool CurrentState = MyButton.Read(); // Turn on LED if the button is being pressed if (CurrentState == LOW) // level-sensitive {digitalWrite(LedPin, HIGH);} else {digitalWrite(LedPin, LOW);} // Increment and print the count at the start of each button press if (CurrentState == LOW && CurrentState != LastState) // edge-sensitive { Count++; Serial.print("Count: "); Serial.println(Count); } // Store button state so changes can be detected LastState = CurrentState; } |