Strange bug registering button input - Page 1
Forum section: electronics / beginners

author: plavelle2k20
author_rank: Newbie
timestamp: November 15, 2020, 06:50:07 am
content: Hi,Hi,In the sketch below, I'm having a problem where my button debouncing code is registering 2 separate button presses. One when the switch is pressed and another when the switch is released. My sketch is below. I'm running this on a Wemos D1 Mini and using platformio as my IDE.I'm using the debounce example fromhttps://www.arduino.cc/en/Tutorial/BuiltInExamples/Debouncein my sketch. I've tried adding another check to the sketch for if the button is HIGH but I had no luck with that.Code:#include <Arduino.h>// Switches between 3 Blinking LED's.class BlinkLed{int ledPin; //LED Pin to blinkint ledState; // current state of the ledunsigned long previousMillis; // last the led was updated in millisecondsunsigned long currentMillis; // Current time the led was updated in millisecondsunsigned long blinkInterval; // rate at which to blink the led in milliseconds// constructorpublic:BlinkLed(int ledpin, unsigned long interval){ledPin = ledpin;blinkInterval = interval;pinMode(ledPin, OUTPUT); // set led pin as an outputledState = LOW; // Start with led turned offSerial.begin(9600);}void Blink(){currentMillis = millis(); //store the current time//blink the led at the frequency defined in interval if the led is marked as active (ledActive is true)if( (currentMillis - previousMillis > blinkInterval)) {previousMillis = currentMillis; // Save last time we blinked the LED// If LED is off turn it on and visa-versaif(ledState == LOW){ledState = HIGH;}else{ledState = LOW;}// write state of led to the relevent pindigitalWrite(ledPin, ledState);}}void DeactivateLed(){// set led pin to LOW (Deactivate the LED)digitalWrite(ledPin, LOW);}};class Switch{int switchPin; //Pin the switch is connected toint switchState; // current state of the switchint lastSwitchState; // last known state of the switchunsigned long debounceDelay; // Number of milliseconds to wait before considering a button press validunsigned long lastDebounceTime; // last time stored in the debounce timer in millisecondsunsigned long previousMillis; // last the led was updated in millisecondsunsigned long currentMillis; // Current time the led was updated in millisecondsint ButtonCounter; // Counts how many times the button has been pressedpublic:Switch(int pin, unsigned long debouncedelay){switchPin = pin;debounceDelay = debounceDelay;previousMillis = 0;currentMillis = 0;lastSwitchState = LOW;ButtonCounter = 0;}void CheckSwitchState(){// read the state of the switch pin into a local variableint reading = digitalRead(switchPin);// check to see if the button was pressed (LOW to HIGH transition)// and we've waited long enough since the last press to avoid any noiseif(reading != lastSwitchState){//reset the debouncing timerlastDebounceTime = millis();}if ( (millis() - lastDebounceTime) > debounceDelay){//lastDebounceTime = millis(); // store the last debounce time value//whatever the reading is at, its been there longer than than the debounce delay//so this will be its actual state//Serial.println("millis - lastdebouncetime is more than debounce delay");//if the button has changedif(reading != switchState){//Serial.println("increment the counter");switchState = reading;ButtonCounter = ButtonCounter + 1;//ButtonCounter = ButtonCounter - 1;//Serial.println("switchstate set equal to reading");}}// save the switch reading. next time through the loop it will be the lastSwitchStatelastSwitchState = reading;}bool ButtonPressed(){CheckSwitchState();if(switchState == HIGH){return true;}else{return false;}}int GetButtonCounter(){//CheckSwitchState();return(ButtonCounter);}void ResetButtonCounter(){ButtonCounter = 0;}};// initialise objectsBlinkLed led1(5, 1000);BlinkLed led2(4, 1000);BlinkLed led3(15, 1000);Switch switch1(16, 150);void setup() {// put your setup code here, to run once:Serial.begin(9600);}void loop() {// put your main code here, to run repeatedly:switch1.ButtonPressed(); // check for a button press//Serial.println(switch1.GetButtonCounter());if((switch1.GetButtonCounter() == 1)){led1.Blink();led2.DeactivateLed();led3.DeactivateLed();}if (switch1.GetButtonCounter() == 2){led1.DeactivateLed();led2.Blink();led3.DeactivateLed();}if(switch1.GetButtonCounter() == 3){led1.DeactivateLed();led2.DeactivateLed();led3.Blink();}if(switch1.GetButtonCounter() > 3){switch1.ResetButtonCounter();}}

author: Nerull
author_rank: Frequent Contributor
timestamp: November 15, 2020, 07:03:00 am
content: Your code increments the counter on every state change, not just low to high.

author: plavelle2k20
author_rank: Newbie
timestamp: November 15, 2020, 07:07:00 am
content: Thank you for your reply. Would I need a check for if the switch is HIGH inside ofif ( (millis() - lastDebounceTime) > debounceDelay){}or would the check need to be somewhere else?

author: plavelle2k20
author_rank: Newbie
timestamp: November 15, 2020, 08:02:23 am
content: I think I've solved it now. Thank you very much for your advice.I changed my code to the followingCode:if ( (millis() - lastDebounceTime) > debounceDelay){//lastDebounceTime = millis(); // store the last debounce time value//whatever the reading is at, its been there longer than than the debounce delay//so this will be its actual state//if the button state has changedif(reading != switchState){switchState = reading;// Check if the switch is currently HIGH and its last known state was also HIGH (i.e The button has been pressed)if((switchState == HIGH) && lastSwitchState == HIGH){ButtonCounter = ButtonCounter + 1;Serial.println("increment the counter");}//ButtonCounter = ButtonCounter - 1;//Serial.println("switchstate set equal to reading");}}counter now increments each time the button is pressed and released.

author: plavelle2k20
author_rank: Newbie
timestamp: November 15, 2020, 08:05:07 am
content: Sorry, meant to say that the counter now incrementsby 1each time the button is pressed and released.