Analog Debounce, Overflowing Variable?

Hello, I’m newer to Arduino programming. Right now I’m on a group project. The task is to build a little robot that moves ping-pong balls from two diffrent positions to one target-position.
I’ve built a test circuit on a breadboard for the IR-sensor, Buttons, shiftregsiter and LED we are going to use. Unfortunately I have encountered a problem with my buttons (or I guess it’s the buttons).

I am using a Arduino UNO and I am using 3 digital pins for a shiftregister to control eight LED. I have connected two IR sensor breakouts to the analog pins A1 and A2 and my buttons to the analog pins A4 and A5.

I am using my buttons on analog pins because for the final version of the project we are using all digital pins for other things.

The code I am using:

#define RESET 5
#define START 4
#define IR1 1
#define IR2 2

#define dataPinLed 10
#define latchPinLed 11
#define clockPinLed 12

byte flashLedState = 0;
unsigned long lastLedFlash = 0;
const unsigned long flashDelay = 500;

byte activeLedBitMask = B01010100;

//IR variable
byte ballPosition = 0; //0 == no ball; 1 == ball at A1; 2 == ball at A2

//debouncing Reset-Button
//byte lastResetReading = LOW;
unsigned long lastResetDebounceTime = 0;
const unsigned long resetDebounceDelay = 40;
int resetButtonState = 0;
int lastResetButtonState = 0;

//debouncing Start-Button
//byte lastStartReading = LOW;
unsigned long lastStartDebounceTime = 0;
const unsigned long startDebounceDelay = 40;
int startButtonState = 0;
int lastStartButtonState = 0;


void setup() {
  pinMode(RESET, INPUT);
  pinMode(START, INPUT);
  pinMode(IR1, INPUT);
  pinMode(IR2, INPUT);
  
  pinMode(dataPinLed, OUTPUT);
  pinMode(latchPinLed, OUTPUT);
  pinMode(clockPinLed, OUTPUT);

  updateShiftRegister(dataPinLed, clockPinLed, latchPinLed, activeLedBitMask);

  Serial.begin(9600);
}


void loop() {
  
  if (getResetSignal() == true) {
    checkIR();
  }
  
  if (getStartSignal() == true) {
    
  }
  
  flashLED();
}


void flashLED() {
  //Led-state is only changed every 'flashDelay'-seconds
  if ((millis() - lastLedFlash) > flashDelay) {
    if (flashLedState == 0) {
      activeLedBitMask = activeLedBitMask | B00000001;
      flashLedState = 1;
    }
    else if (flashLedState == 1) {
      activeLedBitMask = activeLedBitMask & B11111110;
      flashLedState = 0;
    }
    updateShiftRegister(dataPinLed, clockPinLed, latchPinLed, activeLedBitMask);
    lastLedFlash = millis();
  }
}


void updateShiftRegister(byte dataPin, byte clockPin, byte latchPin, byte updateBitMask) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, updateBitMask);
  digitalWrite(latchPin, HIGH);
}


boolean getResetSignal() {
  int resetReading = analogRead(RESET); //saves the current state
  
  //digitalize the analog output
  if(resetReading > 800){
    resetReading = 1;
  }
  else {
    resetReading = 0;
  }
  
  //did the state change since last check?
  if (resetReading != lastResetButtonState) {
    lastResetDebounceTime = millis(); //resets debouncing timer
  }

  //is the debounce delay time reached?
  if ((millis() - lastResetDebounceTime) > resetDebounceDelay) {

    //did the state change since last time?
    if (resetReading != resetButtonState) {
      resetButtonState = resetReading;
      
      if (resetButtonState == 1) {
        return true;  //returns if the button is pressed
      }
      else {
        return false;
      }
    }
  }

  lastResetButtonState = resetReading;
}


boolean getStartSignal() {
  int startReading = analogRead(START); //saves the current state

  //digitalize the analog output
  if(startReading > 800){
    startReading = 1;
  }
  else {
    startReading = 0;
  }
  
  //did the state change since last check?
  if (startReading != lastStartButtonState) {
    lastStartDebounceTime = millis(); //resets debouncing timer
  }

  //is the debounce delay time reached?
  if ((millis() - lastStartDebounceTime) > startDebounceDelay) {

    //did the state change since last time?
    if (startReading != startButtonState) {
      startButtonState = startReading;

      if (startButtonState == 1) {
        return true;  //returns if the button is pressed
      }
      else {
        return false;
      }
    }
  }

  lastStartButtonState = startReading;
}


void checkIR() {
  int ir1Value = analogRead(IR1);
  int ir2Value = analogRead(IR2);

  Serial.println(ir1Value);
  Serial.println(ir2Value);
  
  if (ir1Value < 1000) {
    activeLedBitMask = activeLedBitMask | B10000000;
    activeLedBitMask = activeLedBitMask & B10111111;
    ballPosition = 1;
  }
  if (ir2Value < 1000) {
    activeLedBitMask = activeLedBitMask | B00100000;
    activeLedBitMask = activeLedBitMask & B11101111;
    ballPosition = 2;
  }
  if (((ir1Value > 1000) && (ir2Value > 1000)) || ((ir1Value < 1000) && (ir2Value < 1000))) {
    activeLedBitMask = activeLedBitMask | B01010000;
    activeLedBitMask = activeLedBitMask & B01011111;
    ballPosition = 0;
  }

  Serial.println(ballPosition);

  updateShiftRegister(dataPinLed, clockPinLed, latchPinLed, activeLedBitMask);
}

I’ve copied the debounce code from here: Debounce
and changed only the digitalRead() to a analogRead() and translated the analog values to the digital values 1 and 0.

the buttons are connected like this:

Now the Problem:

I am printing 3 values to the Serial Monitor. So if I press the button they appear once as something like “1023 1022 0” (or other values as needed if the sensors are reacting)

if I wait about 60 seconds doing nothing the Serial Monitor suddenly gets flooded with a lot of these 3 values. It is as if the button is pressed very fast very often.

I first thougth it’s something about an overflow from an unsigned int variable. That would fit ~64000ms…

I’ve added the UL to my unsigned long variables, but that changed nothing.

unsigned long lastResetDebounceTime = 0UL;
const unsigned long resetDebounceDelay = 40UL;
int resetButtonState = 0;
int lastResetButtonState = 0;

After that I did some further google research and found that I can use the digitalRead() on analog pins.
So I changed the code to this:

#define RESET 19
...
boolean getResetSignal() {
  int resetReading = digitalRead(RESET); //saves the current state
/*
  //digitalize the analog output
  if(resetReading > 800){
    resetReading = 1;
  }
  else {
    resetReading = 0;
  }
*/
  //did the state change since last check?
  if (resetReading != lastResetButtonState) {
    lastResetDebounceTime = millis(); //resets debouncing timer
  }

  //is the debounce delay time reached?
  if ((millis() - lastResetDebounceTime) > resetDebounceDelay) {

    //did the state change since last time?
    if (resetReading != resetButtonState) {
      resetButtonState = resetReading;
      
      if (resetButtonState == HIGH) {
        return true;  //returns if the button is pressed
      }
      else {
        return false;
      }
    }
  }

  lastResetButtonState = resetReading;
}

This did solve my Problem. The programm stopped flooding the Serial Monitor. But with this version the checkIR() is called multiple times as long as I keep the button pressed. With the analog version I could press it as long as I wanted and it only called it once.

I don’t get what happens here and I need help to understand it correctly. It doesn’t matter to me wether I use the analogRead() or the digitalRead() but I like to activate the action only once.

Please ask for any further information if needed.
Thanks.

I am using my buttons on analog pins because for the final version of the project we are using all digital pins for other things.

The analog pins are multifunctional, and work as digital pins as well. Just use digitalRead() with them.

jremington: The analog pins are multifunctional, and work as digital pins as well. Just use digitalRead() with them.

And pinMode(... , INPUT_PULLUP); works too. So you don't need that external 10k resistor.