Unwanted delay between multiple button presses

I am building a controller for filling liquid containers to user specific amounts, 0-450 Liters. The target amounts are set by depressing various buttons to sum up or down to a target quantity. For example depressing "Up 100" will add 100 L to the target. Depressing the button again will sum it to 200 L and so on. I have buttons for up and down 100L, up and down 10L etc.

The system seems to work so far, the switches are adding the sum totals as they should.

The issue is a delay when I depress the same switch several times in a row. I have to wait about 1 second before the system registers that I depressed the switch again. The target updates correctly but there is an unwanted delay.

If I hit a different switch, the target is updated almost immediately. The issue only occurs when hitting the same switch repeatedly.

I tried changing the numbers on the debounce timer from 50 to 1 to 10 with no effect. I also tried disabling serial.Print to no effect.

Any ideas what is causing this?

Using an Arduino Uno from the starter kit with the starter Kit LCD screen.

I attached parts of the sketch below it is too large to allow me to attach all of it.

[code]
/*
  Tote Filler Arduino Sketch Chuck Baresich
  Updated February 13th 2018

_____________________________________
  Parts of Base Sketch taken from:
  
 -- Arduino Starter Kit example  - Project 11  - Crystal Ball  by Scott Fitzgerald
 -- Sketch scorecard from Arduino community by user Scarybeard posted January 2016
 -- Debounce Sketch created by David Mellis and modified thereafter
_____________________________________
*/

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 10;

// set up constants for the input switches from control, and variables to hold the values of the switch pins

// Reset target switch
const int resetPin = 7;
int resetState;
int lastResetState = LOW;

// switches for increase and decrease by 100 count
const int up100Pin = 8;
const int up100 = 100;
int up100State;
int lastUp100State = LOW;

const int down100Pin = 10;
int down100State;
int lastDown100State = LOW;
const int down100 = -100;

// switches for increase and decrease by 10 count
const int up10Pin = A4;
int up10State;
int lastUp10State = LOW;
const int up10 = 10;

const int down10Pin = A3;
const int down10 = -10;
int down10State;
int lastDown10State = LOW;

// 450L switch
const int max450Pin = 6;
const int max450L = 450;
int max450State;
int lastMax450State = LOW;


// variable to hold the target quantity
int target = 000;
int actual = 000;
int ptarget = 000;
const int minimumL = 0;

void setup() {
  // set up the number of columns and rows on the LCD
  lcd.begin(16, 2);

  // set up the switch pin as an input
  pinMode(startPin, INPUT);
  digitalWrite(startPin, startState);
  pinMode(flow, INPUT);
  pinMode(stopPin, INPUT);
  digitalWrite(stopPin, stopState);
  pinMode(resetPin, INPUT);
  digitalWrite(resetPin, resetState);
  pinMode(up100Pin, INPUT);
  digitalWrite(up100Pin, up100State);
  pinMode(down100Pin, INPUT);
  digitalWrite(down100Pin, down100State);
  pinMode(up10Pin, INPUT);
  digitalWrite(up10Pin, up10State);
  pinMode(down10Pin, INPUT);
  digitalWrite(down10Pin, down10State);
  pinMode(max450Pin, INPUT);
  digitalWrite(max450Pin, max450State);

  lcd.setCursor(0, 0);
  lcd.print("Target:");
  lcd.setCursor(0, 1);
  lcd.print("Actual:");
}

void loop() {

  target = constrain(target, minimumL, max450L);
  lcd.setCursor(8, 0);
  lcd.print("    ");
  lcd.setCursor(8, 0);
  lcd.print(target);
  lcd.setCursor(12, 0);
  lcd.print(" L");
  lcd.setCursor(8, 1);
  lcd.print(actual);
  lcd.setCursor(12, 1);
  lcd.print(" L");

  // check the status of the switches

  // user wants to increase target by 100 L at a time
  int readUp100 = digitalRead(up100Pin);
  if (readUp100 != lastUp100State) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readUp100 != up100State) {
      up100State = readUp100;
      if (up100State == HIGH) {
        updateup100();
      }
    }
  }
  lastUp100State = readUp100;

  // user wants to decrease target by 100 L at a time
  int readDown100 = digitalRead(down100Pin);
  if (readDown100 != lastDown100State) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readDown100 != down100State) {
      down100State = readDown100;
      if (down100State == HIGH) {
        updatedown100();
      }
    }
  }
  lastDown100State = readDown100;

  // user wants 450L pumped, reset button is not pushed and stop button is not pushed
  int readMax450 = digitalRead(max450Pin);

  if (readMax450 != lastMax450State) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readMax450 != max450State) {
      max450State = readMax450;
      if (max450State == HIGH) {
        updatemax450();
      }
    }
  }
  lastMax450State = readMax450;

  //  user wants to reset target to zero

  int readReset = digitalRead(resetPin);
  // Serial.print(" Reset? ");
  // Serial.print(readReset);

  if (readReset != lastResetState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readReset != resetState) {
      resetState = readReset;
      if (resetState == HIGH) {
        //     Serial.print("reset has been pressed");
        updatereset();
      }
    }
  }
  lastResetState = readReset;

  // user wants to stop pumping liquid
  int readStop = digitalRead(stopPin);
  //Serial.print(" Stop? ");
  //Serial.println(readStop);
  if (readStop != lastStopState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readStop != stopState) {
      stopState = readStop;
      if (stopState == HIGH) {
        //    Serial.print("stop has been pressed");
        updatestopvalve();
      }
    }
  }
  lastStopState = readStop;

  // user wants to increase target by 10 L at a time
  int readUp10 = digitalRead(up10Pin);
  //Serial.print(" Up 10? ");
  // Serial.println(readUp10);
  if (readUp10 != lastUp10State) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readUp10 != up10State) {
      up10State = readUp10;
      if (up10State == HIGH) {
        //     Serial.print("Up 10 has been pressed");
        updateup10();
      }
    }
  }
  lastUp10State = readUp10;

  // user wants to decrease target by 10 L at a time
  int readDown10 = digitalRead(down10Pin);
  // Serial.print(" Down 10? ");
  // Serial.println(readDown10);
  if (readDown10 != lastDown10State) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (readDown10 != down10State) {
      down10State = readDown10;
      if (down10State == HIGH) {
        //     Serial.print("down 10 has been pressed");
        updatedown10();
      }
    }
  }
  lastDown10State = readDown10;

}

void updatemax450()
{
  target = max450L;
  lcd.setCursor(8, 0);
  lcd.print(target);
  // Serial.print(target);
}
void updatereset()
{
  target = 0;
  lcd.setCursor(8, 0);
  lcd.print(target);
  lcd.setCursor(8, 0);
  lcd.print("    ");

}
void updateup100()
{
  target = target + up100;
  lcd.setCursor(8, 0);
  lcd.print(target);
}
void updatedown100()
{
  if (target >= minimumL) {
    ptarget = target;
    target = ptarget + down100;
    lcd.setCursor(8, 0);
    lcd.print("    ");
    lcd.setCursor(8, 0);
    lcd.print(target);
  }
  else if (target <= minimumL) {
    target = minimumL;
    lcd.setCursor(8, 0);
    lcd.print("    ");
    lcd.print(target);
  }
}
void updatestopvalve()
{
  // do something

}
void updateup10()
{
  target = target + up10;
  lcd.setCursor(8, 0);
  lcd.print(target);
}
void updatedown10()
{
  ptarget = target;
  target = ptarget + down10;
  lcd.setCursor(8, 0);
  lcd.print(target);
}

[/code]

"lastDebounceTime" needs to be a separate variable for each of your debounce timers.

  int readUp100 = digitalRead(up100Pin);
  if (readUp100 != lastUp100State) {
    up100DebounceTime = millis();
  }
  if ((millis() - up100DebounceTime) > debounceDelay) {

Use a counter and increment or decrement when the counter count to desire value.

#define counter 40

int val = counter;

void loop(){
...
...
Val --;
if(val <=0){
Val = counter;
    if (down10State == HIGH) {
       //     Serial.print("down 10 has been pressed");
       updatedown10();
     }
  }
}

I tried the suggestion from Hutkikz to give unique values to the lastDebounceTime but that had no effect.

Instead I "forced" the state to LOW for the input switch which seems to have helped, but it is still not perfect.

It's still not perfect though.

I have not tried the counter method yet.

A further note - there is also a delay on getting the Arduino to recognize the HIGH signal I am wondering if the issue is in the board itself.

  // user wants to increase target by 10 L at a time
  int readUp10 = digitalRead(up10Pin);
  //Serial.print(" Up 10? ");
  // Serial.println(readUp10);
  if (readUp10 != lastUp10State) {
    lastUp10DebounceTime = millis();
  }
  if ((millis() - lastUp10DebounceTime) > debounceDelay) {
    if (readUp10 != up10State) {
      up10State = readUp10;
      if (up10State == HIGH) {
        //     Serial.print("Up 10 has been pressed");
        updateup10();        
      }
    }
  }
//here is what I added
  up10State = LOW;

  lastUp10State = readUp10;

How are your buttons wired?

It appears you expecting the digitalRead() to be HIGH on a button press?

Is there an external pulldown to ground the pin when the button is not pressed?

If this was my project i would read all the buttons one after the other and have a single short interval (perhaps 50 millisecs) between successive reads to deal with bounce - something like

if (millis() - prevButtonRead >= 50) {
   prevButtonRead += 50;
   readUp100 = digitalRead(up100Pin);
   readDown100 = digitalRead(down100Pin);
   readMax450 = digitalRead(max450Pin);
   readStop = digitalRead(stopPin);
   readUp10 = digitalRead(up10Pin);
   readDown10 = digitalRead(down10Pin);
}

...R

Ok Robin2 I will try recoding as you suggest to see how that works.

In answer to cattledog, the buttons are wired with 5V going to one side of switch, other side of switch is connected to digital pins of Uno. In addition, a 10ohm resistor is connected on the output side of the switch as well. This resistor is connected to ground.

The Arduino will see the switch is depressed as a HIGH signal.

@emmanobot,
Apart from the issues in your code snippet - please help everyone by using tags.

Robin2 - I edited my sketch based on your suggestion and it is improved. it is more reliable for reading each click. I still see some hesitation but based on watching the serial print screen I am seeing fluctuation (bounce) due to the way I am mocking the board up. I think a cleaner wiring job will tidy it up.

Last question - do you think switching to pull up on the digital pins is a more stable way to build this? I note that most of the examples are done this way (i.e. see the button when reading LOW vs HIGH)? i.e. will it read cleaner results over time?

[code]
const int debounceDelay = 10;

[/code]

[code]
[code]
void loop() {

  target = constrain(target, minimumL, max450L);

  // print on LCD the target and actual rates until buttons pushed
  lcd.setCursor(8, 0);
  lcd.print("    ");
  lcd.setCursor(8, 0);
  lcd.print(target);
  lcd.setCursor(12, 0);
  lcd.print(" L");
  lcd.setCursor(8, 1);
  lcd.print(actual);
  lcd.setCursor(12, 1);
  lcd.print(" L");

  // check the status of the switches

  Serial.print("Target: ");
  Serial.print(target);
  startState = digitalRead(startState);
  Serial.print(" Start?: ");

  Serial.print(" Up 100? ");
  Serial.print(up100State);

  Serial.print(" Down 100? ");
  Serial.print(down100State);
  Serial.print(" Up 10? ");
  Serial.print(up10State);

  Serial.print(" Down 10? ");
  Serial.print(down10State);

  if (millis() - debounceDelay >= 0) {

    int readUp100 = digitalRead(up100Pin);
    Serial.print(" Up 100? ");
    Serial.print(readUp100);

    int readDown100 = digitalRead(down100Pin);
    Serial.print(" Down 100? ");
    Serial.print(readDown100);

    int readMax450 = digitalRead(max450Pin);
    Serial.print(" Max 450? ");
    Serial.print(readMax450);

    int readReset = digitalRead(resetPin);
    Serial.print(" Reset? ");
    Serial.print(readReset);

    int readStop = digitalRead(stopPin);
    Serial.print(" Stop? ");
    Serial.println(readStop);

    int readDown10 = digitalRead(down10Pin);
    Serial.print(" Down 10? ");
    Serial.println(readDown10);

    int readUp10 = digitalRead(up10Pin);
    Serial.print(" Up 10? ");
    Serial.println(readUp10);

    // user wants to increase target by 100 L at a time

    if (readUp100 != up100State) {
      up100State = readUp100;
      if (up100State == HIGH) {
        Serial.print("Up 100 has been pressed");
        updateup100();
      }
    }
    up100State = LOW;
    lastUp100State = readUp100;

    // user wants to decrease target by 100 L at a time

    if (readDown100 != down100State) {
      down100State = readDown100;
      if (down100State == HIGH) {
        Serial.print("Down 100 has been pressed");
        updatedown100();
      }
    }
    down100State = LOW;
    lastDown100State = readDown100;

    // user wants 450L pumped, reset button is not pushed and stop button is not pushed
    if (readMax450 != max450State) {
      max450State = readMax450;
      if (max450State == HIGH) {
        Serial.print("Max 450 has been pressed");
        updatemax450();
      }
    }
    lastMax450State = readMax450;

    //  user wants to reset target to zero
    if (readReset != resetState) {
      resetState = readReset;
      if (resetState == HIGH) {
        Serial.print("reset has been pressed");
        updatereset();
      }
    }
    lastResetState = readReset;

    // user wants to stop pumping liquid

    if (readStop != stopState) {
      stopState = readStop;
      if (stopState == HIGH) {
        Serial.print("stop has been pressed");
        updatestopvalve();
      }
    }
    lastStopState = readStop;

    // user wants to increase target by 10 L at a time

    if (readUp10 != up10State) {
      up10State = readUp10;
      if (up10State == HIGH) {
        Serial.print("Up 10 has been pressed");
        updateup10();
      }
    }
    up10State = LOW;
    lastUp10State = readUp10;

    // user wants to decrease target by 10 L at a time

    if (readDown10 != down10State) {
      down10State = readDown10;
      if (down10State == HIGH) {
        Serial.print("down 10 has been pressed");
        updatedown10();
      }
    }
    down10State = LOW;
    lastDown10State = readDown10;
  }

  Litres = pulseIn(flow, HIGH);
}

[/code][/code]

SandFarmer:
Robin2 - I edited my sketch based on your suggestion and it is improved. it is more reliable for reading each click. I still see some hesitation but based on watching the serial print screen I am seeing fluctuation (bounce) due to the way I am mocking the board up.

You need to post the complete code for the latest version of your program. The devil is in the detail.

...R