MAX7219 Led Matrix interfacing with Arduino.

MAX7219 Led Matrix interfacing with Arduino.
The MAX7219 led matrix with Arduino is among the most widely used components for displaying text in applications like billboard messages and digital clocks. However these matrix displays come in various types and as such are among the hardest devices to program even with the already made libraries .
This tutorial is a detailed description of how to interface the MAX7219 Led matrix with Arduino using some of the common libraries and how to trouble shoot some of the problems that may arise.

The MAX7219 Led Matrix description.

We are going to use the FC-16 module which has four casacaded 8×8 LED Matrix Displays and a built-in MAX7219 LED Driver for each display.
It also uses SPI 3-wire serial interface for easy hookup to microcontrollers and you easily daisy-chain multiple modules together for larger displays
For a detailed explanation on the working of the MAX7219 led driver, you can make reference to a previous post:
  • MAX7219 8×8 LED dot Matrix with Scrolling Text
  • Appearance of the FC16 led dot matrix with four cascaded 8×8 led matrices form the front and back side.
    max7219 led dot matrix
    max7219 dot led matrix pinout

    Schematic for MAX7219 with Arduino

    NOTE:Due to the fairly high current draw of the display (up to 1A if the brightness is cranked all the way up), it is recommended to drive it directly from a power supply rather than from the microcontroller power or else be sure to keep the brightness turned down to less than 50% to avoid overheating the microcontroller voltage regulator.

    MAX7219 with Arduino Using the MD_MAX72XX.h and MD_Parola.h libaries.

    These libraries are among the best for controlling text displaying on led matrices. The major challenge with using these libraries comes from the type of hardware you are using. We need to specify the hardware type by modifying this line of code.
    #define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
    Since we are using the FC16 type led matrix, this line is going to be changed to :
    #define HARDWARE_TYPE MD_MAX72XX::FC16_HW
    The connections of the pins should not be changed since this has been embedded in the library code and if it is changed the hardware will not work. This arrangement should be as follows:
    #define CLK_PIN 13
    #define DATA_PIN 11
    #define CS_PIN 10
    The first example is for a code that displays a simple static message on the matrix.
    #include <MD_Parola.h>
    #include <MD_MAX72xx.h>
    #include <SPI.h>
    
    const uint16_t WAIT_TIME = 1000;
    
    // 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 HARDWARE_TYPE MD_MAX72XX::FC16_HW   //PAROLA_HW
    #define MAX_DEVICES 4
    #define CLK_PIN   13
    #define DATA_PIN  11
    #define CS_PIN    10
    
    // Hardware SPI connection
    MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
    // Arbitrary output pins
    // MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
    
    void setup(void)
    {
      P.begin();
    }
    
    void loop(void)
    {
      P.print("HELLO");
        
    }
    
    
    The second example is for code that displays a scrolling message received from the serial interface.That is, we write a message in the serial monitor and it is displayed on the led matrix.
    #include <MD_Parola.h>
    #include <MD_MAX72xx.h>
    #include <SPI.h>
    
    // set to 1 if we are implementing the user interface pot, switch, etc
    #define USE_UI_CONTROL 0
    
    #if USE_UI_CONTROL
    #include <MD_UISwitch.h>
    #endif
    
    // Turn on debug statements to the serial output
    #define DEBUG 0
    
    #if DEBUG
    #define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
    #define PRINTS(x) Serial.print(F(x))
    #define PRINTX(x) Serial.println(x, HEX)
    #else
    #define PRINT(s, x)
    #define PRINTS(x)
    #define PRINTX(x)
    #endif
    
    // 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
    
    //***mind the hardware type and the pins should be connected as described below
    #define HARDWARE_TYPE MD_MAX72XX::FC16_HW
    #define MAX_DEVICES 4
    #define CLK_PIN   13
    #define DATA_PIN  11
    #define CS_PIN    10
    
    // HARDWARE SPI
    MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
    // SOFTWARE SPI
    //MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
    
    // Scrolling parameters
    #if USE_UI_CONTROL
    const uint8_t SPEED_IN = A5;
    const uint8_t DIRECTION_SET = 8;  // change the effect
    const uint8_t INVERT_SET = 9;     // change the invert
    
    const uint8_t SPEED_DEADBAND = 5;
    #endif // USE_UI_CONTROL
    
    uint8_t scrollSpeed = 40;    // default frame delay value
    textEffect_t scrollEffect = PA_SCROLL_LEFT;
    textPosition_t scrollAlign = PA_LEFT;
    uint16_t scrollPause = 1000; // in milliseconds
    
    // Global message buffers shared by Serial and Scrolling functions
    #define	BUF_SIZE	75
    char curMessage[BUF_SIZE] = { "" };
    char newMessage[BUF_SIZE] = { "Hello! Enter new message?" };
    bool newMessageAvailable = true;
    
    #if USE_UI_CONTROL
    
    MD_UISwitch_Digital uiDirection(DIRECTION_SET);
    MD_UISwitch_Digital uiInvert(INVERT_SET);
    
    void doUI(void)
    {
      // set the speed if it has changed
      {
        int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 10, 150);
    
        if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
          (speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
        {
          P.setSpeed(speed);
          scrollSpeed = speed;
          PRINT("\nChanged speed to ", P.getSpeed());
        }
      }
    
      if (uiDirection.read() == MD_UISwitch::KEY_PRESS) // SCROLL DIRECTION
      {
        PRINTS("\nChanging scroll direction");
        scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
        P.setTextEffect(scrollEffect, scrollEffect);
        P.displayClear();
        P.displayReset();
      }
    
      if (uiInvert.read() == MD_UISwitch::KEY_PRESS)  // INVERT MODE
      {
        PRINTS("\nChanging invert mode");
        P.setInvert(!P.getInvert());
      }
    }
    #endif // USE_UI_CONTROL
    
    void readSerial(void)
    {
      static char *cp = newMessage;
    
      while (Serial.available())
      {
        *cp = (char)Serial.read();
        if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE-2)) // end of message character or full buffer
        {
          *cp = '\0'; // end the string
          // restart the index for next filling spree and flag we have a message waiting
          cp = newMessage;
          newMessageAvailable = true;
        }
        else  // move char pointer to next position
          cp++;
      }
    }
    
    void setup()
    {
      Serial.begin(57600);
      Serial.print("\n[Parola Scrolling Display]\nType a message for the scrolling display\nEnd message line with a newline");
    
    #if USE_UI_CONTROL
      uiDirection.begin();
      uiInvert.begin();
      pinMode(SPEED_IN, INPUT);
    
      doUI();
    #endif // USE_UI_CONTROL
    
      P.begin();
      P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
    }
    
    void loop()
    {
    #if USE_UI_CONTROL
      doUI();
    #endif // USE_UI_CONTROL
    
      if (P.displayAnimate())
      {
        if (newMessageAvailable)
        {
          strcpy(curMessage, newMessage);
          newMessageAvailable = false;
        }
        P.displayReset();
      }
      readSerial();
    }
    
    

    Using the Max72xxPanel.h library.

    The Max722xxPanel.h library is good for displaying scrolling text messages on the Led matrix. This library works with the help of the Adafruit_GFX.h and the SPI.h libraries.
    One of the challenges you may find when using this library come from the orientation of the displayed text. This is usually corrected by changing the value of the setPosition() and setRotation() functions. These functions define if and how the displays are rotated. The first display (0) is the one closest to the Arduino.
    In the example below I have shown how these functions will be used for eight cascaded led matrices but the code also works fine with the four matrices. You can try changing the values and see what happens with the displayed text.
    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Max72xxPanel.h>
    
    int pinDIN = 11;   // DIN pin of MAX7219 module
    int pinCLK = 13;   // CLK pin of MAX7219 module
    int pinCS = 10;    // CS pin of MAX7219 module
    int numberOfHorizontalDisplays=8;
    int numberOfVerticalDisplays=1;
    
    Max72xxPanel matrix= Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
    
    int scrollSpeed = 60;
    int spacer = 1;
    int width = 5+spacer;
    
    void setup(){
      Serial.begin(9600);
       matrix. setIntensity ( 1 ) ;  // Adjust the brightness between 0 and 15
       matrix. setPosition ( 0 ,  0 ,  0 ) ;  // The first display is at <0, 0>
       matrix. setPosition ( 1 ,  1 ,  0 ) ;  // The second display is at <1, 0>
       matrix. setPosition ( 2 ,  2 ,  0 ) ;  // The third display is in <2, 0>
       matrix. setPosition ( 3 ,  3 ,  0 ) ;  // The fourth display is at <3, 0>
       matrix. setPosition ( 4 ,  4 ,  0 ) ;  // The fifth display is at <4, 0>
       matrix. setPosition ( 5 ,  5 ,  0 ) ;  // The sixth display is at <5, 0>
       matrix. setPosition ( 6 ,  6 ,  0 ) ;  // The seventh display is at <6, 0>
       matrix. setPosition ( 7 ,  7 ,  0 ) ;  // The eighth display is in <7, 0>
       matrix. setPosition ( 8 ,  8 ,  0 ) ;  // The ninth display is at <8, 0>
       matrix. setRotation ( 0 ,  1 ) ;     // Display position
       matrix. setRotation ( 1 ,  1 ) ;     // Display position
       matrix. setRotation ( 2 ,  1 ) ;     // Display position
       matrix. setRotation ( 3 ,  1 ) ;     // Display position
       matrix. setRotation ( 4 ,  1 ) ;     // Display position
       matrix. setRotation ( 5 ,  1 ) ;     // Display position
       matrix. setRotation ( 6 ,  1 ) ;     // Display position
       matrix. setRotation ( 7 ,  1 ) ;     // Display position
       matrix. setRotation ( 8 ,  1 ) ;     // Display position
    }
     
    
      void loop(){
        String tape = " HELLO WORLD";
       long int time = millis();
       while(Serial.available()){
          string += char(Serial.read());
       }
        for(int i=0; i<width*tape.length()+matrix.width()-1-spacer; i++ ){
          matrix.fillScreen(LOW);
          int letter = i/width;
          int x = (matrix.width()-1)-i%width;
          int y = (matrix.height()-8)/2;
    
          while(x+width-spacer>=0 && letter>=0){
            if(letter<tape.length()){
             matrix.drawChar(x,y,tape[letter],HIGH,LOW,1);
             
              }
            letter--;
            x-= width;
            }
             matrix.write();
             delay(scrollSpeed);
          }
        }
    
    When this code is uploaded to the Arduino board, a scrolling message “HELLO WORLD” will be displayed by the led matrix.

    6 thoughts on “MAX7219 Led Matrix interfacing with Arduino.

    1. Which is latest and less complicated “https://mytectutor.com/max7219-led-matrix-interfacing-with-arduino/” or
      “https://mytectutor.com/8×8-led-matrix-max7219-with-scrolling-text/”
      It looks hardware is same for both
      for sure shot work which one should I follow

    2. I have to say this is one of the best explanations on using the max7219 display with Arduino I have found around the internet.Thanks.

      1. Try one of these depending on different types of hardware.
        #define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW
        //#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
        //#define HARDWARE_TYPE MD_MAX72XX::FC16_HW

        // SOFTWARE SPI
        MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

    3. I have the text scrolling very nicely using twelves modules. However, I would like the text to scroll from right to left and then stop at the far left leaving a complete word (up to twelve letters) display until and update command erases the word and another scrolls across. I’m so far unable to find assistance for this. There is no requirement for hardware to change speed or direction. That can be set in the software and need not be changed once set. Can someone help please.

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Back to top