1

I'm new to Arduino and need assistance from knowledgeable people. I'm having a problem with my code, which allows the user to increase or decrease the number by pressing buttons. From time to time, the number does not change by one, but by two or three. This occurs on a sporadic basis. This is known as "bouncing." I googled "attachInterrupt debounce" in vain, but I couldn't find a suitable solution. My code is here.

int digit_state = 0;
void increment(void){
  digit_state = digit_state + 1;
  }
void decrement(void){
  digit_state = digit_state - 1;  
  }
String user_input = "";
String password = "3452";
int enterbutton = 11;
int increment_button = 2;
int decrement_button = 3;
int counter = 0;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(enterbutton,INPUT);
  attachInterrupt(digitalPinToInterrupt(increment_button),increment,FALLING);
  attachInterrupt(digitalPinToInterrupt(decrement_button),decrement,FALLING);
}

void loop() {
  // put your main code here, to run repeatedly:
  lastButtonState = reading;
  while(counter<=3){
    delay(500);
    Serial.println(digit_state);
    if(digitalRead(enterbutton)==LOW){
      user_input = user_input + digit_state;
      Serial.println("Saved input so far is "+user_input);
      if(user_input == password){
        Serial.println("検証できた");
      }
      delay(500);
      digit_state = 0;
      counter++;
  }
}
}

As the user presses, I need to stop it from bouncing and get an accurate password all the time.

1 Answer 1

1

First: It is not necessary to use interrupts for buttons, because when humans press buttons they will be at least actived for about 100ms, which is very slow for a microcontroller. You would just need to rewrite your code to be non-blocking (for example by ditching all delay() calls and instead use millis() like in the BlinkWithoutDelay example, that comes with the Arduino IDE). Then you can also use existing libraries for debouncing like Bounce2.


A very simple approach would be to set a timeout after each button press, where no new button press will be registrated, like 10ms (should be plenty enough for debouncing, though you can test for your setup yourself). This can be done with millis() by maintaining a timestamp of the last button press:

#define DEBOUNCE_TIME  10
volatile unsigned long button_press_timestamp = 0;

void increment(void){
  if(millis()-button_press_timestamp > DEBOUNCE_TIME){
      digit_state = digit_state + 1;
      button_press_timestamp = millis();
  }
}

First in global scope we are defining our debounce time and a variable for holding the timestamp, when the last button press was registered. In the ISR (here only increment() as example) we then check the difference between this timestamp and the current time. If that is bigger than the debounce time we execute the buttons action (incrementing in this case). Then we update the timestamp to the current time.

On a button press the first falling edge will trigger the button action. Any falling edges from the bouncing will appear inside the debounce time and thus will be ignored (the ISR gets called but the code in the if statement is not executed).

This debouncing principle is not perfect but easy to implement and it might be enough for you.

1
  • Thank you for the solution.
    – Ori
    Commented Jul 10, 2021 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.