Momentary buttons 'double registering'

Hello

I have a simple project that I prototyped using those little breadboard momentary buttons. I've debounced them and everything works great. For my final product, I switched to a larger momentary button, but now they tend to very rapidly double register their LOW state when pressed which is breaking the functionality.

I guess my question is, could the buttons themselves just be cheap and not as precice? As cheap as those little momentary buttons are, they have a definitive 'click' where the bigger buttons do not, but they're all I could find....

I've double checked my solder connections. I just don't know if I should be looking at the buttons or the code, but like I said those little buttons work flawlessly...

Just in case, here is my code for the button:

if(!redButtonState){
      redReading = redButtonState;
      digitalWrite(redPin, HIGH);  
      tone(buzzer,notes[0],50);   
      if (redReading == LOW && redPrevious == HIGH && millis() - redButtonLastTime >= debounce) {  
        Serial.println("RED");
        redButtonLastTime = millis();     
        redPrevious = LOW;
        // GUESSES
        guess = redPin;
        if(guess == randomPatternArray[guesses]){
           guessLastTime = millis();
          Serial.println("correct");
            guesses ++;
        }else{
           Serial.println("wrong");
           resetGame();  
        }
        
      }     
    }else{
      digitalWrite(redPin, LOW);
      redPrevious = HIGH;
    }

Just scan your switch every 50ms and if there is a change in state respond to a switch closer or opening.

Of course it is the code, but you have published a useless "snippet". :cold_sweat:

Can't see from that code what the value of "debounce" is - it clearly needs to be a bit larger for
the bigger buttons.

Hi,
Have you got a 0.1uF capacitor from the controller input pin to gnd?

Tom... :slight_smile:

MarkT:
Can't see from that code what the value of "debounce" is - it clearly needs to be a bit larger for
the bigger buttons.

I had the debounce at 50, but have moved it up to 500ms which seems to be the sweet spot for these buttons.

flyagaricus:
I had the debounce at 50, but have moved it up to 500ms which seems to be the sweet spot for these buttons.

Then something is terribly wrong. Those tact switches are not that bad. What happens when you run a known to be good switch debounce and read sketch, like the IDE example?

500ms is a ridiculous time for a bounce. Thats not a switch its a football!

Can you please post a schematic so we can see what you are doing wrong?

On my site here you can find a schematic and sketch to measure your bounce time

http://www.skillbank.co.uk/arduino/switchbounce.htm

You'll see the worst case bounce time I measured was 2ms.

flyagaricus:
I had the debounce at 50, but have moved it up to 500ms which seems to be the sweet spot for these buttons.

Did you try 0.1uF capacitor from the input pin to gnd?
Tom… :slight_smile:

If software debounce fails to work, I doubt that adding a "hardware" fudge is going to help. :roll_eyes:

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

What value pull down resistor do you have on your buttons?

Thanks... Tom.... :slight_smile:

I suspect those push buttons are pretty rubbish without reliable connection. A proper push button
momentary switch has an internal spring that makes the contact reliable (after any bouncing has
died away). Without such a mechanism you are pressing two bits of metal together by finger pressure
alone, and that can be unreliable as fingers tend to move around a bit.

A decent push switch is tactile - you feel the spring operate and release.

I see, it's not tact switches, it's the panel mount switches. Indeed, they might not be as good. Still, I would like to see the results of using them with a standard, already proven debounce routine.

aarg:
Then something is terribly wrong. Those tact switches are not that bad. What happens when you run a known to be good switch debounce and read sketch, like the IDE example?

The buttons 'switch from LOW to HIGH more than one in the the 50ms...I guess? So by code picks up two presses which is not acceptable.

TomGeorge:
Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

What value pull down resistor do you have on your buttons?

Thanks… Tom… :slight_smile:

I’m using ‘INPUT_PULLUP’, so no resistors. You’ve seen adn helped me with the same project in another thread.

Always wise to show us a good photo of the actual wiring.

Try the sketch below.

Switch is on A0, buzzer is on D08, LED1 on D07, heartbeatLED on D13.

Open the Serial monitor at 9600 baud to see the counter increment.

If all okay, change line #24 to 50ms.

//
// YY/MM/DD   Version
// 18/04/27   1.00          Working code
//

#define PUSHED              LOW  //the switch is connected between GND and our pin

#define LEDon               HIGH //LED anode connected to +5V
#define LEDoff              LOW  

#define BUZZERon            true
#define BUZZERoff           false

const byte buttonPin      = A0;
const byte led1Pin        = 7;  
const byte buzzerPin      = 8;  
const byte heartbeatLED   = 13;  //toggles every 500ms if code is non-blocking

float sinVal;                   
unsigned int toneVal;            //sound frequency
unsigned int buzzerNumber = 0;
unsigned int counter;

byte lastButtonState;
byte pushNumber           = 0;

bool buzzerStateFlag      = BUZZERoff;

//timing stuff
unsigned long switchBounceInterval = 100;   // <-----<<<< change to 50ms for shorter period
unsigned long buzzerTime           = 5;

unsigned long switchMillis;
unsigned long buzzerMillis;
unsigned long heartbeatMillis;

//********************************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(led1Pin, OUTPUT);

  pinMode(buttonPin, INPUT_PULLUP);  //closed = LOW

} //END of setup()

//********************************************************************
void loop()
{
  //*********************************
  //time to toggle the heartbeat LED ?
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the Timer
    heartbeatMillis = millis();

    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));

  }

  //*********************************
  //check the switches
  checkSwitches();

  //*********************************
  //time for the next sound to be made ?
  if (buzzerStateFlag == BUZZERon && millis() - buzzerMillis >= buzzerTime)
  {
    //restart the Timer
    buzzerMillis = millis();

    //buzzer program with sins wave
    sinVal = sin(buzzerNumber * (PI / 180)); // Calculate the sine of x
    toneVal = 3300 + sinVal * 500; // Calculate sound frequency according to the sine of x

    tone(buzzerPin, toneVal); // Output sound frequency to buzzerPin

    //buzzerNumber++;

    buzzerNumber = buzzerNumber + 20;

    if (buzzerNumber > 360)
    {
      buzzerNumber = 0;
    }

  }

  //*********************************
  //Other non-blocking code goes here
  //*********************************

} //END of loop()

//********************************************************************
void checkSwitches()
{
  //*********************************
  //time to proceed with switch checking ?
  if (millis() - switchMillis < switchBounceInterval)
  {
    return;
  }

  //restart the Timer
  switchMillis = millis();

  byte buttonState = digitalRead(buttonPin);

  //*********************************
  //has the switch changed state ?
  if (lastButtonState == buttonState)
  {
    return;
  }

  //update to the new state
  lastButtonState = buttonState;

  //*********************************
  //was the switch closed ?
  if (buttonState == PUSHED)
  {
    //odd/even number of pushes
    pushNumber = 1 - pushNumber;

    //*********************************
    //should we enable the buzzer ?
    if (pushNumber == 1)
    {
      //enable the buzzer
      buzzerStateFlag = BUZZERon;

      //restart the Timer
      buzzerMillis = millis();
      buzzerNumber = 0;

      //turn LED ON
      digitalWrite(led1Pin, HIGH);

      Serial.println(counter++);
    }

    //*********************************
    //should we disable the buzzer ?
    else if (pushNumber == 0)
    {
      //disable the buzzer
      buzzerStateFlag = BUZZERoff;
      noTone(buzzerPin);

      //turn LED OFF
      digitalWrite(led1Pin, LOW);
    }

  } //END of  if (buttonState == PUSHED)


  //*********************************
  //Other switch code goes here
  //*********************************

} //END of checkSwitches()

//********************************************************************