Trouble counting and debouncing

I'm making a counter for work that counts the number of times a micro (limit) switch is pressed using an Arduino nano. The problem is that the machine has adjustable speed, and seems to skip a count every once in a while when going at higher speeds. I assume this is because the code is too slow? Anyways, I tried to solve this problem by attaching the count function to an interrupt. This however makes it count multiple times per switch press even with the deboucing code I have written. Would it be better to use an interrupt or not in my case? I think the fastest the micro switch will be pressed is 100-200ms. Also, I have the micro switch wired COM to pin 3, 5v to NC, and gnd to NO. I've seen that a 10k resistor would be good to add to connect the ground to NO, but I have it soldered together already and don't want to de-solder to add a resistor, but will this help?
I am starting to lose hope that this will work 100% of the time, should I give up instead of hoping i'll be able to make this work well enough for only a few miscounts per few thousand counts?

I attached the full code below:

//Sets the total you want for each count
float Total = 1000;
float Cup = 20;
int Batch = 100;

// ON=1; OFF=0
int CupOn = 0;

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

//Pin assignments
const int SwitchPin = 3;
const int ButtonPin = 9;
const int CounterIntPin = 12;
const int ClutchPin = 6;

const int FiveVThirteen = 13;

#define baudRate 9600

//Variables
float TotalCount = 0;
float CupCount = 0;
int BatchCount = 0;

int TotalLength = "";
int CupLength = "";
int BatchLength = "";

int ButtonState = "";
int SwitchState = "";
int CounterState = "";
int ButtonHold = 0;

int StopCount = 0;

int add = 0;

void setup() {
  //Initialize digital pins used for 5v sources
  pinMode(FiveVThirteen, OUTPUT);
  digitalWrite(FiveVThirteen, HIGH);

  //Set Switch pin and Button pin as inputs
  pinMode(SwitchPin, INPUT);
  attachInterrupt(1,Count,RISING);
  pinMode(ButtonPin, INPUT);
  pinMode(CounterIntPin, INPUT);

  //Set Clutch pin as output
  pinMode(ClutchPin, OUTPUT);
  digitalWrite(ClutchPin, HIGH);

  //Start serial communication @9600 bps
  Serial.begin(baudRate);
  uint32_t timeout = 5000;
  uint32_t startTime = millis();
  while (!Serial && millis() - startTime < timeout) {
    continue;
  }

  lcd.begin();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Total:         *=HIT");
  lcd.setCursor(0, 1);
  lcd.print("0000000 of 9999999 ");
  lcd.setCursor(0, 2);
  lcd.print("Cup:00000 of 99999 ");
  lcd.setCursor(0, 3);
  lcd.print("Batch:0000 of 9999 ");
}

void loop() {
  // put your main code here, to run repeatedly:
  if (ClutchPin == LOW) {
  } else {
    digitalWrite(ClutchPin, HIGH);
  }

  Processing();

  Clutch();

  ResetButton();

  LimitSet();

  CountSet();

}

void Processing() {
  Serial.flush();
  if (Serial.available()) {    //serial data is available to read
    char val = Serial.read();  //stores character read

    //Code for recieving total amount from processing
    if (val == 't') {
      delay(5);
      int m = Serial.read();
      int n = int(m) - '0';
      int value[n + 1];
      int falue[n + 1];
      for (int i = 1; i <= n; i++) {
        value[i] = Serial.read();
        falue[i] = int(value[i]) - '0';
      }
      if (n == 2) {
        Total = (falue[1] * 10.0) + (falue[2] * 1.0);
      } else if (n == 3) {
        Total = (falue[1] * 100.0) + (falue[2] * 10.0) + (falue[3] * 1.0);
      } else if (n == 4) {
        Total = (falue[1] * 1000.0) + (falue[2] * 100.0) + (falue[3] * 10.0) + (falue[4] * 1.0);
      } else if (n == 5) {
        Total = (falue[1] * 10000.0) + (falue[2] * 1000.0) + (falue[3] * 100.0) + (falue[4] * 10.0) + (falue[5] * 1.0);
      } else if (n == 6) {
        Total = (falue[1] * 100000.0) + (falue[2] * 10000.0) + (falue[3] * 1000.0) + (falue[4] * 100.0) + (falue[5] * 10.0) + (falue[6] * 1.0);
      } else if (n == 7) {
        Total = (falue[1] * 1000000.0) + (falue[2] * 100000.0) + (falue[3] * 10000.0) + (falue[4] * 1000.0) + (falue[5] * 100.0) + (falue[6] * 10.0) + (falue[7] * 1.0);
      } else if (n == 1) {
        Total = falue[1] * 1.0;
      }
      Serial.println(Total);  //Line 6
    }
    //Code for recieving cup amount from processing
    else if (val == 'c') {
      delay(5);
      int q = Serial.read();
      int r = int(q) - '0';

      int Walue[r + 1];
      int calue[r + 1];
      for (int i = 1; i <= r; i++) {
        Walue[i] = Serial.read();
        calue[i] = int(Walue[i]) - '0';
      }

      if (r == 2) {
        Cup = (calue[1] * 10.0) + (calue[2] * 1.0);
      } else if (r == 3) {
        Cup = (calue[1] * 100.0) + (calue[2] * 10.0) + (calue[3] * 1.0);
      } else if (r == 4) {
        Cup = (calue[1] * 1000.0) + (calue[2] * 100.0) + (calue[3] * 10.0) + (calue[4] * 1.0);
      } else if (r == 5) {
        Cup = (calue[1] * 10000.0) + (calue[2] * 1000.0) + (calue[3] * 100.0) + (calue[4] * 10.0) + (calue[5] * 1.0);
      } else if (r == 1) {
        Cup = calue[1] * 1.0;
      }
    }
    //Code for recieving batch amount from processing
    else if (val == 'b') {
      delay(5);
      int o = Serial.read();
      int p = int(o) - '0';

      int Value[p];
      int balue[p];
      for (int i = 1; i <= p; i++) {
        Value[i] = Serial.read();
        balue[i] = int(Value[i]) - '0';
      }
      if (p == 2) {
        Batch = (balue[1] * 10) + balue[2];
      } else if (p == 3) {
        Batch = (balue[1] * 100) + (balue[2] * 10) + balue[3];
      } else if (p == 4) {
        Batch = (balue[1] * 1000) + (balue[2] * 100) + (balue[3] * 10) + balue[4];
      } else if (p == 1) {
        Batch = balue[1];
      }
    }
    //Code for recieving cup or no cup from processing
    else if (val == 'y') {
      CupOn = 1;
      lcd.setCursor(0, 2);
      lcd.print("Cup:      of       ");
    } else if (val == 'n') {
      CupOn = 0;
    }
  }
  Serial.flush();
}

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 10; // Adjust debounce delay as needed
int lastCounterState = LOW;        // Initialize the last counter state
int lastSwitchState = LOW;         // Initialize the last switch state

void Count() {
  if (StopCount == 0) {
    unsigned long currentTime = millis();

    // Read the state of the counter pin
    int counterState = digitalRead(CounterIntPin);

    // Check if the counter state has changed since the last read
    if (counterState != lastCounterState) {
      lastDebounceTime = currentTime; // Reset the debounce timer
    }

    // Check if the debounce delay has elapsed
    if ((currentTime - lastDebounceTime) >= debounceDelay) {
      // If enough time has passed, and the counter state is HIGH, register a count
      if (counterState == HIGH) {
        // Read the state of the switch
        int switchState = digitalRead(SwitchPin);
        // If the switch is HIGH (pressed), and it wasn't pressed before, register a count
        if (switchState == HIGH) {
          TotalCount++;
          CupCount++;
          BatchCount++;
        }
        // Update the last switch state
        lastSwitchState = switchState;
      }
    }

    // Remember the current counter state for the next iteration
    lastCounterState = counterState;
  }
}

void Clutch() {
  //Turn off clutch when total count equals the total limit
  if (TotalCount == Total) {
    digitalWrite(ClutchPin, LOW);
    StopCount = 1;
    lcd.setCursor(18, 1);
    lcd.print(" *");
  }
  //Turn off clutch when cup count equals the cup limit
  if (CupOn == 1) {
    if (CupCount == Cup) {
      digitalWrite(ClutchPin, LOW);
      StopCount = 1;
      lcd.setCursor(18, 2);
      lcd.print(" *");
    }
  }
  //Turn off clutch when batch count equals the batch limit
  if (BatchCount == Batch) {
    digitalWrite(ClutchPin, LOW);
    StopCount = 1;
    lcd.setCursor(18, 3);
    lcd.print(" *");
  }
}

void ResetButton() {
  //Reset Button Code
  ButtonState = digitalRead(ButtonPin);
  if (ButtonState == HIGH) {
    if (CupOn == 1) {
      if (TotalCount >= Total) {
        while (ButtonHold <= 2) {
          ButtonState = digitalRead(ButtonPin);
          if (ButtonState == HIGH) {
            ButtonHold = ButtonHold + 1;
            delay(1000);
          } else {
            ButtonHold = 0;
          }
        }
        ButtonHold = 0;
        TotalCount = 0;
        CupCount = 0;
        BatchCount = 0;
        lcd.setCursor(18, 3);
        lcd.print("  ");
        lcd.setCursor(18, 2);
        lcd.print("  ");
        lcd.setCursor(18, 1);
        lcd.print("  ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      } else if (CupCount >= Cup) {
        while (ButtonHold <= 1) {
          ButtonState = digitalRead(ButtonPin);
          if (ButtonState == HIGH) {
            ButtonHold = ButtonHold + 1;
            delay(500);
          } else {
            ButtonHold = 0;
          }
        }
        ButtonHold = 0;
        CupCount = 0;
        BatchCount = 0;
        lcd.setCursor(19, 2);
        lcd.print(" ");
        lcd.setCursor(19, 3);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);

      } else {
        BatchCount = 0;
        lcd.setCursor(19, 3);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      }
    } else {
      if (TotalCount >= Total) {
        while (ButtonHold <= 2) {
          ButtonState = digitalRead(ButtonPin);
          if (ButtonState == HIGH) {
            ButtonHold = ButtonHold + 1;
            delay(1000);
          } else {
            ButtonHold = 0;
          }
        }
        ButtonHold = 0;
        TotalCount = 0;
        CupCount = 0;
        BatchCount = 0;
        lcd.setCursor(19, 3);
        lcd.print(" ");
        lcd.setCursor(19, 2);
        lcd.print(" ");
        lcd.setCursor(19, 1);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      } else {
        BatchCount = 0;
        lcd.setCursor(19, 3);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      }
    }
  }
}

void LimitSet() {
  //Total limit Set
  if (Total <= 9999999.9) {
    lcd.setCursor(11, 1);
    if (Total <= 9.9) {
      lcd.print("000000");
      lcd.setCursor(17, 1);
    } else if (Total <= 99.9) {
      lcd.print("00000");
      lcd.setCursor(16, 1);
    } else if (Total <= 999.9) {
      lcd.print("0000");
      lcd.setCursor(15, 1);
    } else if (Total <= 9999.9) {
      lcd.print("000");
      lcd.setCursor(14, 1);
    } else if (Total <= 99999.9) {
      lcd.print("00");
      lcd.setCursor(13, 1);
    } else if (Total <= 999999.9) {
      lcd.print("0");
      lcd.setCursor(12, 1);
    }
    lcd.print(Total, 0);
  } else {
    lcd.setCursor(11, 1);
    lcd.print("0000000");
  }

  //Cup Limit Set
  if (CupOn == 1) {
    lcd.setCursor(13, 2);
    if (Cup <= 99999.9) {
      if (Cup <= 9.9) {
        lcd.print("0000");
        lcd.setCursor(17, 2);
      } else if (Cup <= 99.9) {
        lcd.print("000");
        lcd.setCursor(16, 2);
      } else if (Cup <= 999.9) {
        lcd.print("00");
        lcd.setCursor(15, 2);
      } else if (Cup <= 9999.9) {
        lcd.print("0");
        lcd.setCursor(14, 2);
      }
      lcd.print(Cup, 0);
    } else {
      lcd.print("00000");
    }
  }

  //Batch Limit Set
  lcd.setCursor(14, 3);
  if (Batch <= 9999.9) {
    if (Batch <= 9.9) {
      lcd.print("000");
      lcd.setCursor(17, 3);
    } else if (Batch <= 99.9) {
      lcd.print("00");
      lcd.setCursor(16, 3);
    } else if (Batch <= 999.9) {
      lcd.print("0");
      lcd.setCursor(15, 3);
    }
    lcd.print(Batch);
  } else {
    lcd.print("0000");
  }
}

void CountSet() {
  // Find length of Total limit float
  TotalLength = TotalCount == 0 ? 0 : (int)log10(TotalCount) + 1;

  // Find length of Cup limit float
  CupLength = CupCount == 0 ? 0 : (int)log10(CupCount) + 1;

  // Find length of Batch limit integer
  BatchLength = BatchCount == 0 ? 0 : (int)log10(BatchCount) + 1;

  //Displays new total count
  if (TotalLength == 0) {
    lcd.setCursor(0, 1);
    lcd.print("0000000 ");
  } else {
    lcd.setCursor((7 - TotalLength), 1);
    lcd.print(TotalCount, 0);
    lcd.setCursor(7,1);
    lcd.print(" ");
  }
  //Displays new cup count
  if (CupOn == 1) {
    if (CupLength == 0) {
      lcd.setCursor(4, 2);
      lcd.print("00000 ");
    } else {
      lcd.setCursor((9 - CupLength), 2);
      lcd.print(CupCount, 0);
      lcd.setCursor(9,2);
      lcd.print(" ");
    }
  } else {
    lcd.setCursor(0, 2);
    lcd.print("                    ");
  }
  //Displays new batch count
  if (BatchLength == 0) {
    lcd.setCursor(6, 3);
    lcd.print("0000 ");
  } else {
    lcd.setCursor((10 - BatchLength), 3);
    lcd.print(BatchCount);
    lcd.setCursor(10,3);
    lcd.print(" ");
  }
}

You can use that switch as two switches, one for pressed and one for released. Connect COM to GND, NC and NO to two input pins with pullups. Then use flip-flop code like this:

if (digitalRead(NO)==0) { if (!pressed) count++; pressed = true; }
else if (digitalRead(NC)==0) pressed = false;

It would be great if you posted a wiring schematic of your project.
Drawing speaks much better than words.

What do these other "keys" do in your project?

Hello rouset

I´ve made a small code review and here are my comments:

The usage of the delay() function in combination with the millis() function will inhibit the expected realtime behaiviour of the sketch.

Search "delay" (15 hits in 1 file of 1 searched) [Normal]
  new 3 (15 hits)
	Line 104:       delay(5);
	Line 132:       delay(5);
	Line 157:       delay(5);
	Line 190: unsigned long debounceDelay = 10; // Adjust debounce delay as needed
	Line 206:     // Check if the debounce delay has elapsed
	Line 207:     if ((currentTime - lastDebounceTime) >= debounceDelay) {
	Line 264:             delay(1000);
	Line 284:         delay(200);
	Line 291:             delay(500);
	Line 308:         delay(200);
	Line 320:         delay(200);
	Line 329:             delay(1000);
	Line 349:         delay(200);
	Line 360:         delay(200);

I have not considered the use of the while() function any further, but you should also analyse more closely here when the termination condition is or will be fulfilled.

Search "while" (9 hits in 1 file of 1 searched) [Normal]
  new 3 (9 hits)
	Line  61:   while (!Serial && millis() - startTime < timeout) {
	Line 260:         while (ButtonHold <= 2) {
	Line 281:         while (ButtonState == HIGH) {
	Line 287:         while (ButtonHold <= 1) {
	Line 305:         while (ButtonState == HIGH) {
	Line 317:         while (ButtonState == HIGH) {
	Line 325:         while (ButtonHold <= 2) {
	Line 346:         while (ButtonState == HIGH) {
	Line 357:         while (ButtonState == HIGH) {

Have a nice day and enjoy coding in C++.

You call this twice yet there's no outgoing serial data to wait for. Probably not the fix you need for the button presses, I just don't know that you need this at all.

https://www.arduino.cc/reference/tr/language/functions/communication/serial/flush/

I see, i tried connecting to only COM and NO before but i didnt work. I just tried again with the pullup and it seems to work. But now it counts like 5-10 hits for every time i press the switch though. Also it jumps when i press as well as when i release. Do you think adding this flip flop code will fix the issues I'm having if I were to recode and rewire it?

yeah you're right. i just figured why change it if its working.

1 Like

Then it's of inferior quality, not usable for flip-flop operation.

suggest using a hall effect switch

I'll work on a diagram, but i don't think it really will help solve my problem. The switchpin is the micro switch, buttonpin resets the count, counter interrupt stops the micro switch from being able to count, and clutch pin sends a signal out to turn on or off a clutch using a relay.

that has to do with the hardware not the code? Its a microswitch from McMaster Carr.

Do you have an example of a hall effect switch i can use in place of a micro switch? I was hoping to just make this work with what i have already. or is my hardware the issue?

Right. The switch is not a break-before-make type.

I see. Do you think a different switch would make the difference between if this will count every hit or not? I've used these microswitches with other counters that i didn't make before and they work fine. should I look for a micro switch that is break-before-make?

Right.

I got it working well with this code. It just doesn't let me turn the speed above 5.2 on the speed dial, while I would like to reach speeds of up to about 6. I don't understand why it's having trouble at higher speeds, 5.2 is about 350-360ms between pressing the switch, and 6 is about 300ms. Is that not enough time between hits? I even added extra count functions in the main loop to help count more often in the code. This code doesn't use interrupts because missing one count is better than adding 2-5 counts.

//Sets the total you want for each count
float Total = 1000;
float Cup = 20;
int Batch = 100;

// ON=1; OFF=0
int CupOn = 0;

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

//Pin assignments
const int SwitchPin = 3;
const int ButtonPin = 9;
const int CounterIntPin = 12;
const int ClutchPin = 6;

const int FiveVThirteen = 13;

#define baudRate 9600

//Variables
float TotalCount = 0;
float CupCount = 0;
int BatchCount = 0;

int TotalLength = "";
int CupLength = "";
int BatchLength = "";

int ButtonState = "";
int SwitchState = "";
int CounterState = "";
int ButtonHold = 0;

int StopCount = 0;

int LastState = "";
int add = 0;

void setup() {
  //Initialize digital pins used for 5v sources
  pinMode(FiveVThirteen, OUTPUT);
  digitalWrite(FiveVThirteen, HIGH);

  //Set Switch pin and Button pin as inputs
  pinMode(SwitchPin, INPUT_PULLUP);
  pinMode(ButtonPin, INPUT);
  pinMode(CounterIntPin, INPUT);

  //Set Clutch pin as output
  pinMode(ClutchPin, OUTPUT);
  digitalWrite(ClutchPin, HIGH);

  //Start serial communication @9600 bps
  Serial.begin(baudRate);
  uint32_t timeout = 5000;
  uint32_t startTime = millis();
  while (!Serial && millis() - startTime < timeout) {
    continue;
  }

  lcd.begin();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Total:         *=HIT");
  lcd.setCursor(0, 1);
  lcd.print("0000000 of 9999999 ");
  lcd.setCursor(0, 2);
  lcd.print("Cup:00000 of 99999 ");
  lcd.setCursor(0, 3);
  lcd.print("Batch:0000 of 9999 ");
}

void loop() {
  // put your main code here, to run repeatedly:
  if (ClutchPin == LOW) {
  } else {
    digitalWrite(ClutchPin, HIGH);
  }

  Count();
  Processing();
  Count();
  Clutch();
  Count();
  ResetButton();
  Count();
  LimitSet();
  Count();
  CountSet();
  Count();
}

void Processing() {
  if (Serial.available()) {    //serial data is available to read
    char val = Serial.read();  //stores character read

    //Code for recieving total amount from processing
    if (val == 't') {
      delay(5);
      int m = Serial.read();
      int n = int(m) - '0';
      int value[n + 1];
      int falue[n + 1];
      for (int i = 1; i <= n; i++) {
        value[i] = Serial.read();
        falue[i] = int(value[i]) - '0';
      }
      if (n == 2) {
        Total = (falue[1] * 10.0) + (falue[2] * 1.0);
      } else if (n == 3) {
        Total = (falue[1] * 100.0) + (falue[2] * 10.0) + (falue[3] * 1.0);
      } else if (n == 4) {
        Total = (falue[1] * 1000.0) + (falue[2] * 100.0) + (falue[3] * 10.0) + (falue[4] * 1.0);
      } else if (n == 5) {
        Total = (falue[1] * 10000.0) + (falue[2] * 1000.0) + (falue[3] * 100.0) + (falue[4] * 10.0) + (falue[5] * 1.0);
      } else if (n == 6) {
        Total = (falue[1] * 100000.0) + (falue[2] * 10000.0) + (falue[3] * 1000.0) + (falue[4] * 100.0) + (falue[5] * 10.0) + (falue[6] * 1.0);
      } else if (n == 7) {
        Total = (falue[1] * 1000000.0) + (falue[2] * 100000.0) + (falue[3] * 10000.0) + (falue[4] * 1000.0) + (falue[5] * 100.0) + (falue[6] * 10.0) + (falue[7] * 1.0);
      } else if (n == 1) {
        Total = falue[1] * 1.0;
      }
      Serial.println(Total);  //Line 6
    }
    //Code for recieving cup amount from processing
    else if (val == 'c') {
      delay(5);
      int q = Serial.read();
      int r = int(q) - '0';

      int Walue[r + 1];
      int calue[r + 1];
      for (int i = 1; i <= r; i++) {
        Walue[i] = Serial.read();
        calue[i] = int(Walue[i]) - '0';
      }

      if (r == 2) {
        Cup = (calue[1] * 10.0) + (calue[2] * 1.0);
      } else if (r == 3) {
        Cup = (calue[1] * 100.0) + (calue[2] * 10.0) + (calue[3] * 1.0);
      } else if (r == 4) {
        Cup = (calue[1] * 1000.0) + (calue[2] * 100.0) + (calue[3] * 10.0) + (calue[4] * 1.0);
      } else if (r == 5) {
        Cup = (calue[1] * 10000.0) + (calue[2] * 1000.0) + (calue[3] * 100.0) + (calue[4] * 10.0) + (calue[5] * 1.0);
      } else if (r == 1) {
        Cup = calue[1] * 1.0;
      }
    }
    //Code for recieving batch amount from processing
    else if (val == 'b') {
      delay(5);
      int o = Serial.read();
      int p = int(o) - '0';

      int Value[p];
      int balue[p];
      for (int i = 1; i <= p; i++) {
        Value[i] = Serial.read();
        balue[i] = int(Value[i]) - '0';
      }
      if (p == 2) {
        Batch = (balue[1] * 10) + balue[2];
      } else if (p == 3) {
        Batch = (balue[1] * 100) + (balue[2] * 10) + balue[3];
      } else if (p == 4) {
        Batch = (balue[1] * 1000) + (balue[2] * 100) + (balue[3] * 10) + balue[4];
      } else if (p == 1) {
        Batch = balue[1];
      }
    }
    //Code for recieving cup or no cup from processing
    else if (val == 'y') {
      CupOn = 1;
      lcd.setCursor(0, 2);
      lcd.print("Cup:      of       ");
    } else if (val == 'n') {
      CupOn = 0;
    }
  }
}

void Count() {
  if (StopCount == 0) {
    CounterState = digitalRead(CounterIntPin);
    if (CounterState == HIGH) {
      SwitchState = digitalRead(SwitchPin);
      if (SwitchState == LOW) {
        TotalCount++;
        CupCount++;
        BatchCount++;
      }
      while (SwitchState == LOW) {
        SwitchState = digitalRead(SwitchPin);
      }
      SwitchState = HIGH;
      delay(10);
    }
  }
}

void Clutch() {
  //Turn off clutch when total count equals the total limit
  if (TotalCount == Total) {
    digitalWrite(ClutchPin, LOW);
    StopCount = 1;
    lcd.setCursor(18, 1);
    lcd.print(" *");
  }
  //Turn off clutch when cup count equals the cup limit
  if (CupOn == 1) {
    if (CupCount == Cup) {
      digitalWrite(ClutchPin, LOW);
      StopCount = 1;
      lcd.setCursor(18, 2);
      lcd.print(" *");
    }
  }
  //Turn off clutch when batch count equals the batch limit
  if (BatchCount == Batch) {
    digitalWrite(ClutchPin, LOW);
    StopCount = 1;
    lcd.setCursor(18, 3);
    lcd.print(" *");
  }
}

void ResetButton() {
  //Reset Button Code
  ButtonState = digitalRead(ButtonPin);
  if (ButtonState == HIGH) {
    if (CupOn == 1) {
      if (TotalCount >= Total) {
        while (ButtonHold <= 2) {
          ButtonState = digitalRead(ButtonPin);
          if (ButtonState == HIGH) {
            ButtonHold = ButtonHold + 1;
            delay(1000);
          } else {
            ButtonHold = 0;
          }
        }
        ButtonHold = 0;
        TotalCount = 0;
        CupCount = 0;
        BatchCount = 0;
        lcd.setCursor(18, 3);
        lcd.print("  ");
        lcd.setCursor(18, 2);
        lcd.print("  ");
        lcd.setCursor(18, 1);
        lcd.print("  ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      } else if (CupCount >= Cup) {
        while (ButtonHold <= 1) {
          ButtonState = digitalRead(ButtonPin);
          if (ButtonState == HIGH) {
            ButtonHold = ButtonHold + 1;
            delay(500);
          } else {
            ButtonHold = 0;
          }
        }
        ButtonHold = 0;
        CupCount = 0;
        BatchCount = 0;
        lcd.setCursor(19, 2);
        lcd.print(" ");
        lcd.setCursor(19, 3);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);

      } else {
        BatchCount = 0;
        lcd.setCursor(19, 3);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      }
    } else {
      if (TotalCount >= Total) {
        while (ButtonHold <= 2) {
          ButtonState = digitalRead(ButtonPin);
          if (ButtonState == HIGH) {
            ButtonHold = ButtonHold + 1;
            delay(1000);
          } else {
            ButtonHold = 0;
          }
        }
        ButtonHold = 0;
        TotalCount = 0;
        CupCount = 0;
        BatchCount = 0;
        lcd.setCursor(19, 3);
        lcd.print(" ");
        lcd.setCursor(19, 2);
        lcd.print(" ");
        lcd.setCursor(19, 1);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      } else {
        BatchCount = 0;
        lcd.setCursor(19, 3);
        lcd.print(" ");
        StopCount = 0;
        ButtonState = digitalRead(ButtonPin);
        while (ButtonState == HIGH) {
          ButtonState = digitalRead(ButtonPin);
        }
        delay(200);
        digitalWrite(ClutchPin, HIGH);
      }
    }
  }
}

void LimitSet() {
  //Total limit Set
  if (Total <= 9999999.9) {
    lcd.setCursor(11, 1);
    if (Total <= 9.9) {
      lcd.print("000000");
      lcd.setCursor(17, 1);
    } else if (Total <= 99.9) {
      lcd.print("00000");
      lcd.setCursor(16, 1);
    } else if (Total <= 999.9) {
      lcd.print("0000");
      lcd.setCursor(15, 1);
    } else if (Total <= 9999.9) {
      lcd.print("000");
      lcd.setCursor(14, 1);
    } else if (Total <= 99999.9) {
      lcd.print("00");
      lcd.setCursor(13, 1);
    } else if (Total <= 999999.9) {
      lcd.print("0");
      lcd.setCursor(12, 1);
    }
    lcd.print(Total, 0);
  } else {
    lcd.setCursor(11, 1);
    lcd.print("0000000");
  }

  //Cup Limit Set
  if (CupOn == 1) {
    lcd.setCursor(13, 2);
    if (Cup <= 99999.9) {
      if (Cup <= 9.9) {
        lcd.print("0000");
        lcd.setCursor(17, 2);
      } else if (Cup <= 99.9) {
        lcd.print("000");
        lcd.setCursor(16, 2);
      } else if (Cup <= 999.9) {
        lcd.print("00");
        lcd.setCursor(15, 2);
      } else if (Cup <= 9999.9) {
        lcd.print("0");
        lcd.setCursor(14, 2);
      }
      lcd.print(Cup, 0);
    } else {
      lcd.print("00000");
    }
  }

  //Batch Limit Set
  lcd.setCursor(14, 3);
  if (Batch <= 9999.9) {
    if (Batch <= 9.9) {
      lcd.print("000");
      lcd.setCursor(17, 3);
    } else if (Batch <= 99.9) {
      lcd.print("00");
      lcd.setCursor(16, 3);
    } else if (Batch <= 999.9) {
      lcd.print("0");
      lcd.setCursor(15, 3);
    }
    lcd.print(Batch);
  } else {
    lcd.print("0000");
  }
}

void CountSet() {
  // Find length of Total limit float
  TotalLength = TotalCount == 0 ? 0 : (int)log10(TotalCount) + 1;

  // Find length of Cup limit float
  CupLength = CupCount == 0 ? 0 : (int)log10(CupCount) + 1;

  // Find length of Batch limit integer
  BatchLength = BatchCount == 0 ? 0 : (int)log10(BatchCount) + 1;

  //Displays new total count
  if (TotalLength == 0) {
    lcd.setCursor(0, 1);
    lcd.print("0000000 ");
  } else {
    lcd.setCursor((7 - TotalLength), 1);
    lcd.print(TotalCount, 0);
    lcd.setCursor(7, 1);
    lcd.print(" ");
  }
  //Displays new cup count
  if (CupOn == 1) {
    if (CupLength == 0) {
      lcd.setCursor(4, 2);
      lcd.print("00000 ");
    } else {
      lcd.setCursor((9 - CupLength), 2);
      lcd.print(CupCount, 0);
      lcd.setCursor(9, 2);
      lcd.print(" ");
    }
  } else {
    lcd.setCursor(0, 2);
    lcd.print("                    ");
  }
  //Displays new batch count
  if (BatchLength == 0) {
    lcd.setCursor(6, 3);
    lcd.print("0000 ");
  } else {
    lcd.setCursor((10 - BatchLength), 3);
    lcd.print(BatchCount);
    lcd.setCursor(10, 3);
    lcd.print(" ");
  }
}

It pretty consistent too. At 5.6 it skips every third count.

At least this

  if (ClutchPin == LOW) {
  } else {
    digitalWrite(ClutchPin, HIGH);
  }

is nonsense. ClutchPin is constant, it will never equal LOW, thus the code is exactly the same as

  digitalWrite(ClutchPin, HIGH);

What were you hoping that would do otherwise?

a7

Good switches bounce less than 20 ms.

yeah, i only have a 10ms delay for debouncing. seems to work pretty well. the problem is that it only counts 2 of three hits when the hits are around 300ms apart, while it counts every hit when they are 350ms apart.