Controlling an LED Matrix with Buttons

I am creating a simple score board using the following parts:

I am using the five buttons with the following uses:
Add Point to Home Score
Subtract Point to Home Score
Add Point to Away Score
Subtract Point from Away Score
Clear All Scores

My problem: I can write code to add and subtract to the home score, but when I use the same code to modify the away score it just continuously adds or subtracts without the button being pressed. Below are two snippets of code, the first is the working code for the home score, the code below it is with an away score button that doesnt work.

Working. Responds to button presses

#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library

#define CLK 11
#define LAT A3
#define OE  10
#define A   A0
#define B   A1
#define C   A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
int homeScoreFirstDigit;
int homeScoreSecondDigit;
int awayScoreFirstDigit;
int awayScoreSecondDigit;
uint8_t homeScoreAddDebounce = 0;
uint8_t homeScoreSubtractDebounce = 0;
uint8_t awayScoreAddDebounce = 0;
uint8_t awayScoreSubtractDebounce = 0;

void setup() {
  matrix.begin();
  digitalWrite(A4, LOW);
  digitalWrite(A5, LOW);
  digitalWrite(10, LOW);
  digitalWrite(11, LOW);
  matrix.fillScreen(0);
}

void loop() {
  if(digitalRead(A4) == HIGH) {
    homeScoreAddDebounce = 0;
    return;
  }
  
  if(++homeScoreAddDebounce >= 5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit++;
  
    if (homeScoreSecondDigit > 9) {
      homeScoreSecondDigit = 0;
      homeScoreFirstDigit++;
    }
    
    delay(100);
    matrix.fillScreen(0);
    homeScoreAddDebounce = 0;
  }
  
  else {
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('H');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('M');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('E');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(homeScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7));  
    matrix.print(homeScoreSecondDigit);
  
    matrix.setCursor(1, 9);   // next line
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('A');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('W');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('Y');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreSecondDigit);
    delay(100);
  }
  
  if(digitalRead(A5) == HIGH) {
    homeScoreSubtractDebounce = 0;
    return;
  }
  
  if (++homeScoreSubtractDebounce >=5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit--;
    if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit > 0)) {
      homeScoreSecondDigit = 9;
      homeScoreFirstDigit--;
      if (homeScoreFirstDigit < 0) {
       homeScoreFirstDigit = 0; 
      }
    }
  else if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit == 0)) {
    homeScoreSecondDigit = 0;
  }
  delay(200);
  matrix.fillScreen(0);
  homeScoreSubtractDebounce = 0;
  }
}

Not working. Away score continuously adding points without button engaged.

#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library

#define CLK 11
#define LAT A3
#define OE  10
#define A   A0
#define B   A1
#define C   A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
int homeScoreFirstDigit;
int homeScoreSecondDigit;
int awayScoreFirstDigit;
int awayScoreSecondDigit;
uint8_t homeScoreAddDebounce = 0;
uint8_t homeScoreSubtractDebounce = 0;
uint8_t awayScoreAddDebounce = 0;
uint8_t awayScoreSubtractDebounce = 0;
uint8_t clearScoreDebounce = 0;

void setup() {
  matrix.begin();
  digitalWrite(A4, LOW);
  digitalWrite(A5, LOW);
  digitalWrite(A6, LOW);
  digitalWrite(A7, LOW);
  matrix.fillScreen(0);
}

void loop() {
  if(digitalRead(A4) == HIGH) {
    homeScoreAddDebounce = 0;
    return;
  }
  
  if(++homeScoreAddDebounce >= 5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit++;
  
    if (homeScoreSecondDigit > 9) {
      homeScoreSecondDigit = 0;
      homeScoreFirstDigit++;
    }
    
    delay(100);
    matrix.fillScreen(0);
    homeScoreAddDebounce = 0;
  }
  
  else {
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('H');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('M');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('E');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(homeScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7));  
    matrix.print(homeScoreSecondDigit);
  
    matrix.setCursor(1, 9);   // next line
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('A');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('W');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('Y');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreSecondDigit);
    delay(100);
  }
  
  if(digitalRead(A5) == HIGH) {
    homeScoreSubtractDebounce = 0;
    return;
  }
  
  if (++homeScoreSubtractDebounce >=5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit--;
    if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit > 0)) {
      homeScoreSecondDigit = 9;
      homeScoreFirstDigit--;
      if (homeScoreFirstDigit < 0) {
       homeScoreFirstDigit = 0; 
      }
    }
  else if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit == 0)) {
    homeScoreSecondDigit = 0;
  }
  delay(200);
  matrix.fillScreen(0);
  homeScoreSubtractDebounce = 0;
  }
  
if(digitalRead(A6) == HIGH) {
    awayScoreAddDebounce = 0;
    return;
  }
  
  if(++awayScoreAddDebounce >=5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    awayScoreSecondDigit++;
    
    if(awayScoreSecondDigit > 9) {
      awayScoreSecondDigit = 0;
      awayScoreFirstDigit++;
    }
    
    delay(100);
    matrix.fillScreen(0);
    awayScoreAddDebounce = 0;
  }
}

My problem: I can write code to add and subtract to the home score, but when I use the same code to modify the away score it just continuously adds or subtracts without the button being pressed.

I am almost certain that this is a hardware issue, and floating pin. You need to describe how the switches are wired, and why you are not using the internal pullup resistors and simpler wiring.

Since you just have code snippets i am just curious why home score does not have --- uint8_t clearScoreDebounce = 0; --- as the away score does.

PaulS:

My problem: I can write code to add and subtract to the home score, but when I use the same code to modify the away score it just continuously adds or subtracts without the button being pressed.

I am almost certain that this is a hardware issue, and floating pin. You need to describe how the switches are wired, and why you are not using the internal pullup resistors and simpler wiring.

I have wired the button so that one end goes to the pin on the arduino the other to ground. I don't know about pullup resistors but I am interested if you have materials you can point me to. The buttons are normally open according to the labeling on the button.

I have wired the button so that one end goes to the pin on the arduino the other to ground.

So, when the switch is pressed, the pin is pulled LOW (to ground). What is the pin level when the switch is not pressed?

It is undefined.

Set the mode of the pin to INPUT_PULLUP, to turn on the internal pullup resistor. Then, when the switch is not pressed, the pin is pulled up to HIGH. It is pulled LOW when the switch is pressed.

Right at the begining of your loop you have

if(digitalRead(A4) == HIGH) 
  {
    homeScoreAddDebounce = 0;
    return;
  }

So reading between the lines, (I don't know how your hardware works) Will A4 be high when no keys are being pressed? If so, why is it just homeScoreDebounce that you set to zero? Why don't you also set awayScoreDebounce back to zero.

I'm also confused as to why you have variables called xxAdddebounce and xxSubtractDebounce. You seem to use AddDebounce for the homescore but subtractDebounce for the away score. I suspect you only need one "debounce" variable per key,

PaulS:

I have wired the button so that one end goes to the pin on the arduino the other to ground.

So, when the switch is pressed, the pin is pulled LOW (to ground). What is the pin level when the switch is not pressed?

It is undefined.

Set the mode of the pin to INPUT_PULLUP, to turn on the internal pullup resistor. Then, when the switch is not pressed, the pin is pulled up to HIGH. It is pulled LOW when the switch is pressed.

Below is my updated code and I was able to get a button to work for adding points to the away score! Digital pin 2 is used to add points, pin 3 will be used for subtracting points. Unfortunately, I can’t get pin 3 to work using the same method as pin 2, I’ve tried many different configurations.

#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library

#define CLK 11
#define LAT A3
#define OE  10
#define A   A0
#define B   A1
#define C   A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
int homeScoreFirstDigit;
int homeScoreSecondDigit;
int awayScoreFirstDigit;
int awayScoreSecondDigit;
uint8_t homeScoreAddDebounce = 0;
uint8_t homeScoreSubtractDebounce = 0;
uint8_t awayScoreAddDebounce = 0;
uint8_t awayScoreSubtractDebounce = 0;
uint8_t clearScoreDebounce = 0;

void setup() {
  matrix.begin();
  digitalWrite(A4, LOW);
  digitalWrite(A5, LOW);
  digitalWrite(A6, LOW);
  digitalWrite(A7, LOW);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  matrix.fillScreen(0);
}

void loop() {
  if(digitalRead(A4) == HIGH) {
    homeScoreAddDebounce = 0;
    return;
  }
  
  if(++homeScoreAddDebounce >= 5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit++;
  
    if (homeScoreSecondDigit > 9) {
      homeScoreSecondDigit = 0;
      homeScoreFirstDigit++;
    }
    
    delay(100);
    matrix.fillScreen(0);
    homeScoreAddDebounce = 0;
  }
  
  else {
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('H');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('M');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('E');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(homeScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7));  
    matrix.print(homeScoreSecondDigit);
  
    matrix.setCursor(1, 9);   // next line
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('A');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('W');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('Y');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreSecondDigit);
    delay(100);
  }
  
  if(digitalRead(A5) == HIGH) {
    homeScoreSubtractDebounce = 0;
    return;
  }
  
  if (++homeScoreSubtractDebounce >=5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit--;
    if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit > 0)) {
      homeScoreSecondDigit = 9;
      homeScoreFirstDigit--;
      if (homeScoreFirstDigit < 0) {
       homeScoreFirstDigit = 0; 
      }
    }
  else if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit == 0)) {
    homeScoreSecondDigit = 0;
  }
  delay(200);
  matrix.fillScreen(0);
  homeScoreSubtractDebounce = 0;
  }
  
  if(digitalRead(2) == HIGH) {
    awayScoreAddDebounce = 0;
    return;
  }
  
  if(++awayScoreAddDebounce >= 5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    awayScoreSecondDigit++;
    
    if(awayScoreSecondDigit > 9) {
      awayScoreSecondDigit = 0;
      awayScoreFirstDigit++;
    }
    
    delay(100);
    matrix.fillScreen(0);
    awayScoreAddDebounce = 0;
  }
  
  if(digitalRead(3) == LOW) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    awayScoreSecondDigit--;
    delay(100);
    matrix.fillScreen(0);
    awayScoreSubtractDebounce = 0;
  }
}

KenF: Right at the begining of your loop you have

if(digitalRead(A4) == HIGH) 
  {
    homeScoreAddDebounce = 0;
    return;
  }

So reading between the lines, (I don't know how your hardware works) Will A4 be high when no keys are being pressed? If so, why is it just homeScoreDebounce that you set to zero? Why don't you also set awayScoreDebounce back to zero.

I'm also confused as to why you have variables called xxAdddebounce and xxSubtractDebounce. You seem to use AddDebounce for the homescore but subtractDebounce for the away score. I suspect you only need one "debounce" variable per key,

I have a debounce variable for each button: homeScoreAddDebounce, homeScoreSubtractDebounce, etc. I did this so each button doesnt contaminate the other button's debounce. Not sure if this is best practice, but I saw someone else do it on the forum.

I know it's not bad wiring, because I can change alter the pins the code looks at and the other buttons will work. For example: right now the add-points-to-away button works but the subtract points button does not. If I change which button pin it's looking toward, the new button will work just fine. I am perplexed.

But if digitalRead(4) is high you then exit the loop and ignore whatever is going on with the away score button. So you are only going to look at the away score button if the home score button is being held down at the same time!

How might I prevent that?

I solved the problem by blocking my buttons into individual functions! Thank you KenF and PaulS, you both helped out a huge deal. Here is the final code that works:

#include <Adafruit_GFX.h>   
#include <RGBmatrixPanel.h>

#define CLK 11
#define LAT A3
#define OE  10
#define A   A0
#define B   A1
#define C   A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
int homeScoreFirstDigit;
int homeScoreSecondDigit;
int awayScoreFirstDigit;
int awayScoreSecondDigit;
uint8_t homeScoreAddDebounce = 0;
uint8_t homeScoreSubtractDebounce = 0;
uint8_t awayScoreAddDebounce = 0;
uint8_t awayScoreSubtractDebounce = 0;
uint8_t clearScoreDebounce = 0;

void setup() {
  matrix.begin();
  digitalWrite(A4, LOW);
  digitalWrite(A5, LOW);
  digitalWrite(A6, LOW);
  digitalWrite(A7, LOW);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  matrix.fillScreen(0);
}

void loop() {
  addHomeButton();
  subtractHomeButton();
  addAwayButton();
  subtractAwayButton();
  
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('H');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('M');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('E');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(homeScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7));  
    matrix.print(homeScoreSecondDigit);
  
    matrix.setCursor(1, 9);   // next line
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('A');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('W');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('Y');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreFirstDigit);
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(awayScoreSecondDigit);
    delay(100);
}

void addHomeButton() {
    if(digitalRead(A4) == HIGH) {
    homeScoreAddDebounce = 0;
    return;
  }
  
  if(++homeScoreAddDebounce >= 5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit++;
  
    if (homeScoreSecondDigit > 9) {
      homeScoreSecondDigit = 0;
      homeScoreFirstDigit++;
    }
    
    delay(100);
    matrix.fillScreen(0);
    homeScoreAddDebounce = 0;
  }
}

void subtractHomeButton() {
    if(digitalRead(A5) == HIGH) {
    homeScoreSubtractDebounce = 0;
    return;
  }
  
  if (++homeScoreSubtractDebounce >=5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    homeScoreSecondDigit--;
    if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit > 0)) {
      homeScoreSecondDigit = 9;
      homeScoreFirstDigit--;
      if (homeScoreFirstDigit < 0) {
       homeScoreFirstDigit = 0; 
      }
    }
  else if ((homeScoreSecondDigit < 0) && (homeScoreFirstDigit == 0)) {
    homeScoreSecondDigit = 0;
  }
  delay(200);
  matrix.fillScreen(0);
  homeScoreSubtractDebounce = 0;
  }
}

void addAwayButton() {
    if(digitalRead(2) == HIGH) {
    awayScoreAddDebounce = 0;
    return;
  }
  
  if(++awayScoreAddDebounce >= 5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    awayScoreSecondDigit++;
    
    if(awayScoreSecondDigit > 9) {
      awayScoreSecondDigit = 0;
      awayScoreFirstDigit++;
    }
    
    delay(100);
    matrix.fillScreen(0);
    awayScoreAddDebounce = 0;
  }
}
  
void subtractAwayButton() {
    if(digitalRead(3) == HIGH) {
    awayScoreSubtractDebounce = 0;
    return;
  }
  
  if (++awayScoreSubtractDebounce >=5) {
    matrix.setCursor(1,0);
    matrix.setTextSize(1);
    awayScoreSecondDigit--;
    if ((awayScoreSecondDigit < 0) && (awayScoreFirstDigit > 0)) {
      awayScoreSecondDigit = 9;
      awayScoreFirstDigit--;
      if (awayScoreFirstDigit < 0) {
       awayScoreFirstDigit = 0; 
      }
    }
  else if ((awayScoreSecondDigit < 0) && (awayScoreFirstDigit == 0)) {
    awayScoreSecondDigit = 0;
  }
  delay(200);
  matrix.fillScreen(0);
  awayScoreSubtractDebounce = 0;
  }
}

That's better. I was about to suggest something along these lines

void loop()
{
bool updateRequired=false;

homeScoreAddDebounce=(digitalRead(A4) == HIGH)? 0:homeScoreAddDebounce++;
if(homeScoreAddDebounce>5)
  {homescore++;
   updateRequired=true;
  }

awayScoreAddDebounce = (digitalRead(2) == HIGH)? 0:awayScoreAddDebounce++;
if(awayScoreAddDebounce>5)
  {homescore++;
   updateRequired=true;
  }

if (updateRequired)
  {
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('H');
    matrix.setTextColor(matrix.Color333(7,0,0)); 
    matrix.print('M');
    matrix.setTextColor(matrix.Color333(7,0,0));
    matrix.print('E');
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(int(homescore/10));
    matrix.setTextColor(matrix.Color333(7,0,7));  
    matrix.print(homescore%10);

    matrix.setCursor(1, 9);   // next line
    matrix.setTextColor(matrix.Color333(7,0,7)); 
    matrix.print(int(homescore/10));
    matrix.setTextColor(matrix.Color333(7,0,7));  
    matrix.print(homescore%10); 

  }

delay(100);
}

But splitting it into separate functions is a good idea.