Simple debounce/button press issue

Hi folks,

It's been a while! It's been a while since I've played with my arduino and coded, but with all this time at home it has come back out. I've been working on a more complex project which works fine but I've been having a nightmare of a time capturing simple button presses. I've looked at the examples and even stripped my code down all the way and still cannot get it to work. So much so that here is the example that I'm using (which works):

// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
   // Initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
        Serial.println("Button Pressed");
      }
    }
  }

  // set the LED:
  digitalWrite(ledPin, ledState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

And here is my broken down code; it looks exact to me - but I would appreciate an eye spotting the error:

// PUSH BUTTONS ========================================================================
// Push Button Assignment; the numbers here represent the digital pins
const int btnLineSelectPin = 2;
int btnLineSelectState;
int btnLineSelectLastState = LOW;

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers


// SETUP CODE ============================================================================
void setup() {
  // Initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  // Define all button pins input pins:
  pinMode(btnLineSelectPin, INPUT);

}


// LOOP CODE =============================================================================
void loop() {

  int LineSelectReading = digitalRead(btnLineSelectPin);
  
  if (LineSelectReading != btnLineSelectState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (LineSelectReading != btnLineSelectState) {
      btnLineSelectState = LineSelectReading;

      if (btnLineSelectState == HIGH) {
        Serial.println("Line Select Pressed");
      }
    }
  }

  btnLineSelectLastState == LineSelectReading;

}

Please explain the difference in behaviour between the working and non-working code.

Then please read these two posts:

General Guidance and How to use the Forum
and
Read this before posting a programming question ...

How is your button wired? Do you have a pull-down resistor? Your code is looking for a HIGH as a button press so I'm assuming you have it connected +5V with a pull-down resistor.

aarg:
Please explain the difference in behaviour between the working and non-working code.

Then please read these two posts:

General Guidance and How to use the Forum
and
Read this before posting a programming question ...

aarg: Honestly, there should be no difference and that is my problem; about the only thing I've taken out is the LED state change. I have already tried everything in your guides. I have restarted the computer, changed arduinos, used it in TinkerCAD; etc.

ToddL1962: I did not worry to post the circuit diagram, because I am attempting to use the exact same circuit with the sample code and with my code; and as they are (to me) identical in form and function should not behave any differently. But if it helps for the purpose of the testing the arduino is wired as per the attached wiring diagram.

However, I again, cannot find a differentiation in the code to cause my code not to work and I have checked and rechecked and stripped down for hours.

Cheers,

Steven

Wiring Diagram 1.png

Just to be clear; this is a simple on button press serial print line: "Button Pressed"; the only difference is Im trying to get it to work with the variable names from my larger code.

btnLineSelectLastState == LineSelectReading;

should be = rather than ==

and

if (LineSelectReading != btnLineSelectState)

should be

if (LineSelectReading != btnLineSelectLastState)

B-D-N: Thanks! I've been staring at this entirely too long side by side to have not seen that! Appreciate the set of eyes!

Cheers!

Steven

You're welcome

Ok so the next step:

I'm trying to build my project back up to where it was to get everything functioning as it should. I've added back in the buttons and extended the code to cover the buttons set. Still having trouble getting multiple buttons to function.

So, I'll keep going over the code for a bit. From what I've seen this should be right, but wiring is not my strong suit; can someone confirm that the attached would be the correct way to wire 6 buttons for input use. The remaining pins will be assigned to an LCD for display and a stepper motor.

With the code above duplicated out for the 6 buttons, I am getting 4 buttons working; is there any reason that pin 0 and pin 1 would not allow the same code to work?

aarg: Honestly, there should be no difference and that is my problem

Our problem is that we need your help to troubleshoot your problem. That means answering questions about things you forgot to mention.

You can not use pin 0 and 1 for digital I/O if you are using serial, those are also the serial RX and TX pins.

aarg:
Our problem is that we need your help to troubleshoot your problem. That means answering questions about things you forgot to mention.

I understand; I just meant that there was supposed to be no difference between the two!

aarg:
You can not use pin 0 and 1 for digital I/O if you are using serial, those are also the serial RX and TX pins.

If I had realised this, I might not have had to strip the code down in the first place! Thanks for saving me another few hours of torture.

Seeing as you guys are working through this with me! Next question:

I need to increment variables on my button presses using predefined increments, maximums and minimums; I am currently using this:

intValue = max(min((intValue + intValueInc),intValueMax), intValueMin); 
// Increase the current Inspiration Value by the Increment

The negative increment code is similar:

intValue = max(min((intValue - intValueInc),intValueMax), intValueMin); 
// Increase the current Inspiration Value by the Increment

However, this doesn't seem to work. The logic is the minimum of the increased value and the maximum allowable value will limit the value tothe max and simarly with the maximum of the lower limit and the moving value.

For some of my variables the increments will be 0.1; for some 1; and for others; 10. When I use 10 as the increment and I press my button, my display reads increments of 11; however, when it reaches 99 the next press takes it to 100.

For the float values with I get apparently random changes; defining the value, max, and min as floats with a 0.10 increment; can result in changes from .1 to 1 each time the function is triggered by a button press; with huge jumps from 2 to 20 for example.

If you need more information please advise!

What’s wrong with:

x = x + changeValue;

If you need to limit things use if(. . .)

You can modify ‘changeValue’ in code as needed.

intValue = max(min((intValue + intValueInc),intValueMax), intValueMin);
// Increase the current Inspiration Value by the Increment

works as expected for me, could you post the full code or an example that exhibits the error?

I did a little screen recording to demonstrate the issue I'm having; It was 3mb so I put it on Youtube:

It's operating in TinkerCAD as I don't have the components with me as theyre presently mounted in the device in the lab.

Button Code:

  // Button Press for Line 2 Up --------------------------------|
  if (btnLine2UpReading != btnLine2UpLastState) {
    Line2UplastDebounceTime = millis();
  }

  if ((millis() - Line2UplastDebounceTime) > debounceDelay) {
    if (btnLine2UpReading != btnLine2UpState) {
      btnLine2UpState = btnLine2UpReading;

      if (btnLine2UpState == HIGH) {
        Serial.println("Line 2 Up Pressed");
      // Change Operation Based on Display Page
        switch (intDisplayPage) {
          case 1:
            intExpirationValue = max(min((intExpirationValue + intExpirationValueInc), intExpirationValueMax), intExpirationValueMin); // Increase the current Expiration Value by the Increment
            break;
          case 2:
            intBreathVolume = max(min((intBreathVolume + intBreathVolumeInc), intBreathVolumeMax), intBreathVolumeMin); // Increase the current Volume Value by the Increment
            break;
          case 3:
            // code
            break;  
        }
        UpdateLCD();
        delay(50);
      }
    }
  }

Screen Refresh Code:

void UpdateLCD() {
      lcd.clear()
       switch (intDisplayPage) {
       case 1:
          Serial.println("Page 1");
            lcd.setCursor(0, 0);
            lcd.print("I: " + String(intInspirationValue));
            lcd.setCursor(0, 1);
            lcd.print("E: " + String(intExpirationValue));
            break;
       case 2:
          Serial.println("Page 2");
            lcd.setCursor(0, 0);
            lcd.print("BMP: " + String(intBPM));
            lcd.setCursor(0, 1);
            lcd.print("Vol: " + String(intBreathVolume) + " ml");
            break;
}
}