Incrementing a counter with a momentary pushbutton

Hello all.

I may sound a bit stupid but I have a momentary pushbutton (NO) that I need to push once an increment a counter once. Not 15,000 time like I keep seeing that. I have looked at most of the code and am not coming up with a good solution.

I need to:

Check the state of the button then check to see if it is the same state as before. Then I need to increment the counter once. Then I need to release the button and not have anything else happen until I press it again.

Once the counter reaches a certain number it resets to zero

This is what I have so far. It is commented out and I have been forcing it into a state to check if all the sub state and functions work properly. They do and this one thorn in my side is killing me. This code temporary goes to the next number but then falls back and I start looking for a glass of scotch.

And code gurus that could lend a hand get my total thanks

Bill

//int TopMenuSelect(int NextButton){ // if (NextButtonState != LastNextButtonState) { // if (NextButtonState == LOW) { // if(WaterMenu == 23){ // lcd.clear(); // WaterMenu = 0; // } // else{ // ++WaterMenu ; // } // } // LastScrollButtonState = ScrollButtonState;

Firstly you don't have any debouncing (unless that's somewhere else). Secondly you test for

NextButtonState != LastNextButtonState

then set

LastScrollButtonState = ScrollButtonState

so the if (NextButtonState != LastNextButtonState) at the top will always (or never) be true depending on the state of the variables. I don't see these two variables being reset anywhere.


Rob

Hello,

Thank you for the reply. I am still a bit confused. I need to save the last state of the button to my new state? Am I in the question, saving the old state to the new one?

Could you by any chance elaborate on the topic? You have my absolute attention

Thank you

I need to save the last state of the button to my new state? Am I in the question, saving the old state to the new one?

That's correct but you seem to be saving one variable (LastScrollButtonState = ScrollButtonState;) and comparing another (if (NextButtonState != LastNextButtonState) {). In fact there seems to be four variables involved here and it's not clear to me why.

I can't see the rest of your code so don't know where these variables come from but here's a code snippet that should do something similar and be easily modified to handle what you are doing.

byte current_button_state = HIGH;  // assumes button to GND with pull up resistors
byte new_button_state == HIGH;
const byte buttonPin = 5;
byte WaterMenu = 0;

byte getButtonState() {
    // made this a function because I don't know 
    // where you are getting the button state from
   return (digitalRead(buttonPin)); 
}

void setup () {
  pinMode (buttonPin, INPUT);
}

void loop () {
    new_button_state = getButtonState();

    if (new_button_state == LOW && current_button_state == HIGH) {
       // detected button pressed, we don't care about released
       delay (30);  // debounce by waiting a while and re testing
       if (getButtonState() == LOW) {
            // still low so the button has been pressed
            if (WaterMenu  == 23) {
                lcd.clear();
                WaterMenu  = 0;
            } else {
                ++WaterMenu ;
            }
        current_button_state = new_button_state;
        } 
    }
}

I can't test this but it does compile.


Rob

Hello and thanks. This works but in monitoring it with a serial output it increments on the leading edge and the trailing edge thus incrementing the counter twice each button push. Any way to fix this?

Thanks again

Here is what I have after trying again

const int NextButton = 8;

int TopMenuSelect= 1;

byte NextButtonState = 0;

byte LastNextButtonState = 0;

void setup () {
pinMode(NextButton, INPUT);
Serial.begin(2400);
}

void loop () {
NextButtonState = digitalRead(NextButton);

if(NextButtonState != LastNextButtonState){
if(NextButtonState = HIGH){
if(TopMenuSelect == 3){
TopMenuSelect = 0;
}
else{
TopMenuSelect++;
Serial.print(TopMenuSelect);
LastNextButtonState = LOW;
}

}
}

}//end loop

The thing goes 123123123 a hundred times in one push

This one works better. Still goes several states when a button is pushed const int NextButton = 8;

int TopMenuSelect= 1;

byte NextButtonState = 0;

byte LastNextButtonState = 0;

void setup () { pinMode(NextButton, INPUT); Serial.begin(2400); }

void loop () { NextButtonState = digitalRead(NextButton);

if(NextButtonState != LastNextButtonState){ if(TopMenuSelect == 3){ TopMenuSelect = 0; } else{ TopMenuSelect++; Serial.print(TopMenuSelect); LastNextButtonState = NextButtonState; }

}

}//end loop

Thanks again for all your help but I cannot use delay as this is one small piece of code and I need the CPU to be calculating at all times. I have other operations planned

Thanks

Bill

First, the LastNextButtonState variable should be set to NextButtonState on every pass through loop UNCONDITIONALLY. Get that assignment statement out of the if block.

Second, you don't need to use delay, if 30 milliseconds is really too long to wait. You can use millis() and record when the last button state change occured, and compare the current time that a change seems to have occured to when the last one really occured. If the events are far enough apart, use the change event. Otherwise, ignore it.

Third, there is a library that manages all this stuff for you. Make life easy on yourself, and just use it. http://arduino.cc/playground/Code/Button

Thank you button library. I couldn't have helped but thought I wasn't the first person to have this problem

Thank you

There are two general issues involved here... the fact that most mechanical switches "bounce"...

In the following, "0" stands for "not pushed", and 1 stands for "pushed"

What you think was....

00001111111111111111111111111111111000000000000

... to the Arduino looks like.....

00001010110011101011111111111111111011100100000

As the button's switch closes (and when it opens) it goes "on" and "off" very rapidly for "a moment" until it settles down in the "on" (and subsequently "off") state.

That "moment" is imperceptively short to a human, of significant duration to a computer.

The phenomenon is called "switch bounce", and there are many ways of dealing with it, each with its pros and cons.

A start to discussing bounce is at....

sheepdogguides.com/arduino/aht0bounce1.htm

and more is said at...

sheepdogguides.com/arduino/FA1updwn.htm

=== Once you're clear on "bounce", you'll start into the realm of "blocking" and "non-blocking" solutions.

In a "blocking" solution, nothing else can go on in the Arduino while you have a button pressed... the program waits for you to release the button. This is often acceptable, so the "blocking" isn't a problem. Other times it DOES matter, in which case you're faced with the need to come up with a "clever" answer, which is "non-blocking".

With those terms, you'll find lots of discussions to study. Enjoy!...