Max7219 Scoreboard

I have exhausted my searching abilities. I would like to make a score board for 2 teams that just increments the score up from 0-21 with the push of a button for each team. I have follwed a guide that originates here Arduino Scoreboard by TrevisanGMW - Thingiverse however when putting in this code I get all the max7219 leds lit up at the same time. (I have loaded other text scrolling codes to verify my wiring and understanding is correct) I have loaded the libraries and followed a wiring diagram so I'm assuming its in the code. If I can't get help thats ok I will continue trying somehow.

// Use the MD_MAX72XX library to Print some text on the display
//
// Demonstrates the use of the library to print text.
//
// User can enter text on the serial monitor and this will display as a
// message on the display.

#include <MD_MAX72xx.h>
//#include <SPI.h>

//#define  PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 4

#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS
#define BUTTON_LEFT_PIN    4 // Data Pin for Left Button
#define BUTTON_RIGHT_PIN    2 // Data Pin for Right Button
long buttonTimerR = 0;
long longPressTimeR = 500;
boolean buttonActiveR = false;
boolean longPressActiveR = false;

long buttonTimerL = 0;
long longPressTimeL = 500;
boolean buttonActiveL = false;
boolean longPressActiveL = false;

// SPI hardware interface
MD_MAX72XX mx = MD_MAX72XX(CS_PIN, MAX_DEVICES);
// Arbitrary pins
//MD_MAX72XX mx = MD_MAX72XX(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Text parameters
#define CHAR_SPACING  1 // pixels between characters

// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE  75
char message[BUF_SIZE] = {"   000"};
bool newMessageAvailable = true;
int currentScoreLeft = 0,
    currentScoreRight = 0;
int lastNumberPushup = 0;
bool resetBeforeFirstUse = true;
bool hasLeftDownState = true;
String howMuchSpace;

void printText(uint8_t modStart, uint8_t modEnd, char *pMsg) // *************** LED MATRIX PRINT FUNCTION ***************
// Print the text string to the LED matrix modules specified.
// Message area is padded with blank columns after printing.
{
  uint8_t   state = 0;
  uint8_t   curLen;
  uint16_t  showLen;
  uint8_t   cBuf[8];
  int16_t   col = ((modEnd + 1) * COL_SIZE) - 1;

  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF);

  do     // finite state machine to print the characters in the space available
  {
    switch(state)
    {
      case 0: // Load the next character from the font table
        // if we reached end of message, reset the message pointer
        if (*pMsg == '\0')
        {
          showLen = col - (modEnd * COL_SIZE);  // padding characters
          state = 2;
          break;
        }

        // retrieve the next character form the font file
        showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
        curLen = 0;
        state++;
        // !! deliberately fall through to next state to start displaying

      case 1: // display the next part of the character
        mx.setColumn(col--, cBuf[curLen++]);

        // done with font character, now display the space between chars
        if (curLen == showLen)
        {
          showLen = CHAR_SPACING;
          state = 2;
        }
        break;

      case 2: // initialize state for displaying empty columns
        curLen = 0;
        state++;
        // fall through

      case 3: // display inter-character spacing or end of message padding (blank columns)
        mx.setColumn(col--, 0);
        curLen++;
        if (curLen == showLen)
          state = 0;
        break;

      default:
        col = -1;   // this definitely ends the do loop
    }
  } while (col >= (modStart * COL_SIZE));

  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
}

void setup() // ********************* SETUP ********************
{
  mx.begin();
  // Code written for IR 06H, EN not used, so jumper should be plugged.
  // initialize the pushbutton pin as an input:
  pinMode(BUTTON_LEFT_PIN, INPUT);
  pinMode(BUTTON_RIGHT_PIN, INPUT);
  //Serial.begin(9600);  // Serial for debuggin, should be off on final to avoid delays
  Serial.begin(9600);
}



void loop() // ********************* LOOP ********************
{
  int buttonStateLeft = digitalRead(BUTTON_LEFT_PIN);
  int buttonStateRight = digitalRead(BUTTON_RIGHT_PIN);
  Serial.println(buttonStateRight);

  if (true == true) // LED Matrix Updater
  {
    String messageUpdater;


    // Space Manager
    if (currentScoreLeft <= 9 && currentScoreRight <= 9){
      howMuchSpace =  "       ";
    } else if (currentScoreLeft >= 10 && currentScoreRight <= 9){
      howMuchSpace =  "     ";
    } else if (currentScoreLeft <= 9 && currentScoreRight >= 10){
      howMuchSpace =  "     ";
    } else if (currentScoreLeft >= 10 && currentScoreRight >= 10){
      howMuchSpace =  "   ";
    } else {
      howMuchSpace =  "   ";
    }

    messageUpdater = String(currentScoreLeft) + howMuchSpace + String(currentScoreRight); // Creates space between numbers
    messageUpdater.toCharArray(message,10); // how many numbers to load
    printText(0, MAX_DEVICES-1, message); // update message using LED Matrix Function
    newMessageAvailable = false;
  }



  // RIGHT BUTTON CODE ******************************************************************
   if (buttonStateRight == HIGH) {
    if (buttonActiveR == false) {
      buttonActiveR = true;
      buttonTimerR = millis();
    }
    if ((millis() - buttonTimerR > longPressTimeR) && (longPressActiveR == false)) {
      longPressActiveR = true;
      currentScoreRight = 0;
      delay(300);
    }
  } else {
    if (buttonActiveR == true) {
      if (longPressActiveR == true) {
        longPressActiveR = false;
      } else {
        currentScoreRight = currentScoreRight + 1;
        delay(300);
      }
      buttonActiveR = false;
    }
  }


  // LEFT BUTTON CODE ******************************************************************
   if (buttonStateLeft == HIGH) {
    if (buttonActiveL == false) {
      buttonActiveL = true;
      buttonTimerL = millis();
    }
    if ((millis() - buttonTimerL > longPressTimeL) && (longPressActiveL == false)) {
      longPressActiveL = true;
      currentScoreLeft = 0;
      delay(300);
    }
  } else {
    if (buttonActiveL == true) {
      if (longPressActiveL == true) {
        longPressActiveL = false;
      } else {
        currentScoreLeft = currentScoreLeft + 1;
        delay(300);
      }
      buttonActiveL = false;
    }
  }
}
  • Always show us a good schematic of your proposed circuit, post it here.
    Show us good images of your ‘actual’ wiring.
    Give links to components.

Please test the Max7219 dot matrix module with the default example given in the library. See how the display behaves.


I have run other programs such as scrolling text and everything worked accordingly.

Also I did as you said and ran some examples from the libraries folder and they work.

// Use the MD_MAX72XX library to Print some text on the display
//
// Demonstrates the use of the library to print text.
//
// User can enter text on the serial monitor and this will display as a
// message on the display.

#include <MD_MAX72xx.h>
//#include <SPI.h>

//#define  PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 4
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW

#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS
#define BUTTON_LEFT_PIN    4 // Data Pin for Left Button
#define BUTTON_RIGHT_PIN    2 // Data Pin for Right Button
long buttonTimerR = 0;
long longPressTimeR = 500;
boolean buttonActiveR = false;
boolean longPressActiveR = false;

long buttonTimerL = 0;
long longPressTimeL = 500;
boolean buttonActiveL = false;
boolean longPressActiveL = false;

// SPI hardware interface
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE , CS_PIN, MAX_DEVICES);
// Arbitrary pins
//MD_MAX72XX mx = MD_MAX72XX(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Text parameters
#define CHAR_SPACING  1 // pixels between characters

// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE  75
char message[BUF_SIZE] = {"   000"};
bool newMessageAvailable = true;
int currentScoreLeft = 0,
    currentScoreRight = 0;
int lastNumberPushup = 0;
bool resetBeforeFirstUse = true;
bool hasLeftDownState = true;
String howMuchSpace;

void printText(uint8_t modStart, uint8_t modEnd, char *pMsg) // *************** LED MATRIX PRINT FUNCTION ***************
// Print the text string to the LED matrix modules specified.
// Message area is padded with blank columns after printing.
{
  uint8_t   state = 0;
  uint8_t   curLen;
  uint16_t  showLen;
  uint8_t   cBuf[8];
  int16_t   col = ((modEnd + 1) * COL_SIZE) - 1;

  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF);

  do     // finite state machine to print the characters in the space available
  {
    switch(state)
    {
      case 0: // Load the next character from the font table
        // if we reached end of message, reset the message pointer
        if (*pMsg == '\0')
        {
          showLen = col - (modEnd * COL_SIZE);  // padding characters
          state = 2;
          break;
        }

        // retrieve the next character form the font file
        showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
        curLen = 0;
        state++;
        // !! deliberately fall through to next state to start displaying

      case 1: // display the next part of the character
        mx.setColumn(col--, cBuf[curLen++]);

        // done with font character, now display the space between chars
        if (curLen == showLen)
        {
          showLen = CHAR_SPACING;
          state = 2;
        }
        break;

      case 2: // initialize state for displaying empty columns
        curLen = 0;
        state++;
        // fall through

      case 3: // display inter-character spacing or end of message padding (blank columns)
        mx.setColumn(col--, 0);
        curLen++;
        if (curLen == showLen)
          state = 0;
        break;

      default:
        col = -1;   // this definitely ends the do loop
    }
  } while (col >= (modStart * COL_SIZE));

  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
}

void setup() // ********************* SETUP ********************
{
  mx.begin();
  // Code written for IR 06H, EN not used, so jumper should be plugged.
  // initialize the pushbutton pin as an input:
  pinMode(BUTTON_LEFT_PIN, INPUT_PULLUP);
  pinMode(BUTTON_RIGHT_PIN, INPUT_PULLUP);
  //Serial.begin(9600);  // Serial for debuggin, should be off on final to avoid delays
  Serial.begin(9600);
}



void loop() // ********************* LOOP ********************
{
  int buttonStateLeft = !digitalRead(BUTTON_LEFT_PIN);
  int buttonStateRight = !digitalRead(BUTTON_RIGHT_PIN);
  Serial.println(buttonStateRight);

  if (true == true) // LED Matrix Updater
  {
    String messageUpdater;


    // Space Manager
    if (currentScoreLeft <= 9 && currentScoreRight <= 9){
      howMuchSpace =  "       ";
    } else if (currentScoreLeft >= 10 && currentScoreRight <= 9){
      howMuchSpace =  "     ";
    } else if (currentScoreLeft <= 9 && currentScoreRight >= 10){
      howMuchSpace =  "     ";
    } else if (currentScoreLeft >= 10 && currentScoreRight >= 10){
      howMuchSpace =  "   ";
    } else {
      howMuchSpace =  "   ";
    }

    messageUpdater = String(currentScoreLeft) + howMuchSpace + String(currentScoreRight); // Creates space between numbers
    messageUpdater.toCharArray(message,10); // how many numbers to load
    printText(0, MAX_DEVICES-1, message); // update message using LED Matrix Function
    newMessageAvailable = false;
  }



  // RIGHT BUTTON CODE ******************************************************************
   if (buttonStateRight == HIGH) {
    if (buttonActiveR == false) {
      buttonActiveR = true;
      buttonTimerR = millis();
    }
    if ((millis() - buttonTimerR > longPressTimeR) && (longPressActiveR == false)) {
      longPressActiveR = true;
      currentScoreRight = 0;
      delay(300);
    }
  } else {
    if (buttonActiveR == true) {
      if (longPressActiveR == true) {
        longPressActiveR = false;
      } else {
        currentScoreRight = currentScoreRight + 1;
        delay(300);
      }
      buttonActiveR = false;
    }
  }


  // LEFT BUTTON CODE ******************************************************************
   if (buttonStateLeft == HIGH) {
    if (buttonActiveL == false) {
      buttonActiveL = true;
      buttonTimerL = millis();
    }
    if ((millis() - buttonTimerL > longPressTimeL) && (longPressActiveL == false)) {
      longPressActiveL = true;
      currentScoreLeft = 0;
      delay(300);
    }
  } else {
    if (buttonActiveL == true) {
      if (longPressActiveL == true) {
        longPressActiveL = false;
      } else {
        currentScoreLeft = currentScoreLeft + 1;
        delay(300);
      }
      buttonActiveL = false;
    }
  }
}

my variant:

#include <MD_MAX72xx.h>
#define MAX_DEVICES 4

#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS
#define BUTTON_LEFT_PIN    4 // Data Pin for Left Button
#define BUTTON_RIGHT_PIN    2 // Data Pin for Right Button

MD_MAX72XX mx(2, CS_PIN, MAX_DEVICES);

#define CHAR_SPACING  2 // pixels between characters

char message[] = "88-88";

void printText(uint8_t modStart, uint8_t modEnd, char *pMsg)
// Print the text string to the LED matrix modules specified.
// Message area is padded with blank columns after printing.
{
  uint8_t   state = 0;
  uint8_t   curLen;
  uint16_t  showLen;
  uint8_t   cBuf[8];
  int16_t   col = ((modEnd + 1) * COL_SIZE) - 1;

  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF);

  do     // finite state machine to print the characters in the space available
  {
    switch (state)
    {
      case 0: // Load the next character from the font table
        // if we reached end of message, reset the message pointer
        if (*pMsg == '\0')
        {
          showLen = col - (modEnd * COL_SIZE);  // padding characters
          state = 2;
          break;
        }

        // retrieve the next character form the font file
        showLen = mx.getChar(*pMsg++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
        curLen = 0;
        state++;
      // !! deliberately fall through to next state to start displaying

      case 1: // display the next part of the character
        mx.setColumn(col--, cBuf[curLen++]);

        // done with font character, now display the space between chars
        if (curLen == showLen)
        {
          showLen = CHAR_SPACING;
          state = 2;
        }
        break;

      case 2: // initialize state for displaying empty columns
        curLen = 0;
        state++;
      // fall through

      case 3:  // display inter-character spacing or end of message padding (blank columns)
        mx.setColumn(col--, 0);
        curLen++;
        if (curLen == showLen)
          state = 0;
        break;

      default:
        col = -1;   // this definitely ends the do loop
    }
  } while (col >= (modStart * COL_SIZE));
  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
}

void setup() {
  mx.begin();
  pinMode(BUTTON_LEFT_PIN, INPUT_PULLUP);
  pinMode(BUTTON_RIGHT_PIN, INPUT_PULLUP);
  printText(0, MAX_DEVICES - 1, message);
  delay(1000);
}

void loop() {
  static int currentScoreLeft = 0;
  static int currentScoreRight = 0;
  static bool OldButStaL = 1;
  static bool OldButStaR = 0;
  
  bool buttonStateLeft = !digitalRead(BUTTON_LEFT_PIN);
  bool buttonStateRight = !digitalRead(BUTTON_RIGHT_PIN);

  if ((OldButStaL != buttonStateLeft) || (OldButStaR != buttonStateRight)) {
    if (buttonStateLeft)currentScoreLeft++;
    if (buttonStateRight)currentScoreRight++;

    message[0] = currentScoreLeft / 10 + 48;
    message[1] = currentScoreLeft % 10 + 48;

    message[3] = currentScoreRight / 10 + 48;
    message[4] = currentScoreRight % 10 + 48;

    //messageUpdater = String() + howMuchSpace + String(); // Creates space between numbers
    printText(0, MAX_DEVICES - 1, message); // update message using LED Matrix Function
    OldButStaL = buttonStateLeft;
    OldButStaR = buttonStateRight;
    delay(200);
  }
}
1 Like

This was closer than anything i've had but each button increased by 2 and it repeated as if there were only 2 max7219 panels not 4. I tried doing something with chat gpt but that isn't working either.

show picture

orientation is not same as by me

MD_MAX72XX mx(2, CS_PIN, MAX_DEVICES);

try to change first number to

GENERIC_HW, FC16_HW,  PAROLA_HW, ICSTATION_HW

I apologize, do you mean change the number "2" with GENERIC_HW, FC16_HW, PAROLA_HW, ICSTATION_HW ? I can copy and paste but not too familiar with code.

yes, or just 0 or 1, or 3, bc PAROLA_HW = 2

So I plugged in your code into the wokwi and it's working perfectly. I must have a wiring issue however other projects worked just fine on the max7219. I am baffled. I am using an elegoo uno r3 which I'm assuming is the same thing as an adruino uno.

post sketch theirs here

This code scrolls "hello" across my screen just fine without changing any wiring. However I had to install the parola library. P.s. thank you so much for taking the time to look at my stuff. It means alot to me as I know no one personally (I'm even an electrician) who could could help.

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
 
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW
 
#define MAX_DEVICES 4
#define CS_PIN 10
 
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
 
void setup() {
 
  myDisplay.begin();
  myDisplay.setIntensity(4);
  myDisplay.displayClear();
  myDisplay.displayScroll("hello", PA_CENTER, PA_SCROLL_LEFT, 200);
}
 
void loop() {
  if (myDisplay.displayAnimate()) {
    myDisplay.displayReset();
  }
}

ok. post#7, first sketch

Yes! It started working I had 0 on left and 0 on right. Once I clicked it past 9 I got an error, but I'm thinking that I may have bumped a wire here. I need to double check my breadboard. Definitly some progress! Thank you!

So basically I need to figure out how to move the left number to the right 1 screen and it would be working. - edit. i was wrong this is set up correctly my bad. I think I got it from here thank you so much. If you got a venmo or something I can buy you a beer, coffee, pop (from minnesota here) Theres one from me!

From United States of America ?