My debouncing solution

Hi!

I’m using analogWrite() function in order to change the light intensity on a LED. What I want is to use one push button to increase the amount of light
and another one to decrease the amount of light, I know that this is done with the power provided by the PWM output, which is controlled by the analogWrite() function.

My code simply tries to debounce the two pullups inputs (Increase_button and Decrease_button), for example:

//Increase_button debouncing
if(digitalRead(Increase_button) == 0){
LastZero_time1 = millis();
unsigned long diff = LastZero_time1 - LastOne_time1;
if(diff >= Interval){
debounced1 = 1;
}
}
else{
LastOne_time1 = millis();
}

It marks the last time when the last zero was presented at the Increase_button pullup input, the time will be stored at LastZero_time1, else it marks the last time
a one was presented at the same input and also it’ll be stored at LasOne_time1. Every time a zero is presented it will evaluate the difference of time from the moment
the zero was presented and the last time a one was presented, if the result is equal or greater than the constant Interval (50 milliseconds), it marks the variable
debounced1 with a interger 1.

Another piece of my code:

if(debounced1 == 1 && digitalRead(Increase_button) == 1 && Fade_value < 255){
debounced1 = 0;
Fade_value = Fade_value + Fade_increment;
}

If the Increase_button input is said to be debounced and it presents a high voltage, it will increase the Fade_value which is used at analogWrite(Led,Fade_value).

Complete code:

//Port constants
const short int Led = 11;
const short int Increase_button = 3;
const short int Decrease_button = 4;
const unsigned int Fade_increment = 5;
//Global variables
unsigned long Interval = 50; // 50 milliseconds for debouncing delay
unsigned long LastZero_time1,LastOne_time1; //Stores the last time a logic 1 and logic 0 has respectibly been at Increase_button input
unsigned long LastZero_time2,LastOne_time2; //Stores the last time a logic 1 and logic 0 has respectibly been at Decrease_button input
short int debounced1,debounced2 = 0;
unsigned int Fade_value = 0;

void setup() {
pinMode(Increase_button,INPUT_PULLUP);
pinMode(Decrease_button,INPUT_PULLUP);
pinMode(Led,OUTPUT);

Serial.begin(9600);
}

void loop() {

Serial.println(Fade_value);
analogWrite(Led,Fade_value);//PWM

//Increase_button debouncing
if(digitalRead(Increase_button) == 0){
LastZero_time1 = millis();
unsigned long diff = LastZero_time1 - LastOne_time1;
if(diff >= Interval){
debounced1 = 1;
}
}
else{
LastOne_time1 = millis();
}

//Decrease_button debouncing
if(digitalRead(Decrease_button) == 0){
LastZero_time2 = millis();
unsigned long diff = LastZero_time2 - LastOne_time2;
if(diff >= Interval){
debounced2 = 1;
}
}
else{
LastOne_time2 = millis();
}

//Increase and decrease of the analogWrite(Led,Fade_value) function value
if(debounced1 == 1 && digitalRead(Increase_button) == 1 && Fade_value < 255){
debounced1 = 0;
Fade_value = Fade_value + Fade_increment;
}
if(debounced2 == 1 && digitalRead(Decrease_button == 1) && Fade_value > 0){
debounced2 = 0;
Fade_value = Fade_value - Fade_increment;
}

}

I’ve use the same debouncing algorithm for both increasing and decreasing buttons. Also I called the Serial transmision function in order to see the value stored at
Fade_value, the problem is that when the Increase_button is pressed, it correctly increment the fade value (5 units every press), but it’s not working with the Decrease_button,
it decrements a greater value.

Is there something wrong?

Is there a simpler and/or eficient form to debounce buttons?

Thanks for reading! :slight_smile:

Please use code tags. Use the </> icon in the posting menu. [code] Paste sketch here. [/code]

All this:

  //Increase_button debouncing
  if(digitalRead(Increase_button) == 0){
    LastZero_time1 = millis();
    unsigned long diff = LastZero_time1 - LastOne_time1;
    if(diff >= Interval){
      debounced1 = 1;
    }
  }
  else{
    LastOne_time1 = millis();
  }


  //Increase and decrease of the analogWrite(Led,Fade_value) function value
  if(debounced1 == 1 && digitalRead(Increase_button) == 1 && Fade_value < 255){
    debounced1 = 0;
    Fade_value = Fade_value + Fade_increment;
  }

could be reduced to something like :

  static unsigned long lastAcceptedIncreaseButtonPressMs = 0 ;
  if(digitalRead(Increase_button) == 0 && millis() - lastAcceptedIncreaseButtonPressMs > Interval && Fade_value < 255 ){
     Fade_value +=  Fade_increment;
     lastAcceptedIncreaseButtonPressMs = millis() ;
  }

if you don’t need to wait until the button is released before considering the button press as valid.

The problem you mentioned with button decrements could lie here:

if(debounced2 == 1 && digitalRead(Decrease_button == 1) && Fade_value > 0){ 
   debounced2 = 0;
   Fade_value = Fade_value - Fade_increment;
}

It would work if Fade_increment was 1 (instead of 5). Consider what happens when Fade_value has the value 1. You attempt to decrement it by 5. You have declared it as an unsigned int. What value do you expect it to have?

You could make the following change:

 . . . && Fade_value >= Fade_increment){

This:

... && digitalRead(Decrease_button == 1) && ...

is certainly NOT what you want...

Regards,
Ray L.

And once you start numbering variable, array's, always array's :wink:

And once you understand the debouncing, it's way easier and a lot cleaner to grab a library like Bounce2.

RayLivingston:
This:

... && digitalRead(Decrease_button == 1) && ...

is certainly NOT what you want...

Regards,
Ray L.

Good one. I was expecting a maximum of one error per line. As it is, it would compile and, depending on the activity on pins 0 and 1, could even give plausible results.

Writing a debouncer is a bit of a rite of passage.

Mine is at GitHub - PaulMurrayCbr/DebounceInput: Arduino library for debouncing digital inputs.