Micro Controlers are amazing devices however their resources must be used sparingly. Whilst it is ideal to debounce many inputs at the hardware level with a combination of capacitors and schmitt triggers sometimes it is not practical so debouncing is performed by the Microcontroller and it’s internal timers. To debounce an input you need to register 3 things:
- The input has changed
- The input has remained changed for a set ammount of time
- Update the status of the input
This is typically done with a section of code similar to that below, this is for an “Up” navigation button.
1 | int historicUP = 0; |
2 | int stateUP = 0; |
3 | long upTime; |
4 | |
5 | |
6 | int debounce(){ |
7 | int up_reading = digitalRead(yourPin); //read the digital input |
8 | if(historicUp != up_reading) { //state has changed since last input scan |
9 | upTime = millis(); // reset time count |
10 | historicUp = up_reading; // Record the current state |
11 | } |
12 | else if( millis() - upTime > 30){ // The state has not changed within the time frame defined |
13 | stateUp = up_reading; // Store the debounced state |
14 | } |
15 | } |
However sometimes it can be benefitial to detect just the rising edge of a button. With this it becomes easier to navigate menus and events which increment/decrement with each button push. This can be achieved with the addition of a few extra lines of code and is much less resource hungry than multiple delay timers and calls to the millis() function. So the code is similar to before but notice the few additons
1 | if(historicUp != up_reading){ //State has changed since last input scan |
2 | upTime = millis(); // Reset time count |
3 | historicUp = up_reading; // Record the current state |
4 | } |
5 | else if( millis() - upTime > debounceT ){ // The state has not changed within the time frame defined |
6 | if(menuUp != up_reading){ // If the previous debounced state is not the same as the previous time it was called |
7 | if(up_reading){ // If the input is high, could just as easily work for falling edge detection |
8 | upRising = 1; // Toggle the rising edge bit high |
9 | } |
10 | } |
11 | else{ // The bit has not changed therefore no longer a rising edge since previous function call |
12 | upRising = 0; // Toggle the rising edge bit low |
13 | } |
14 | menuUp = up_reading; //Store the new debounced state ready for refernce elsewhere and for the next call of this routine. |
15 | } |