MAX7219 Dot Matrix 8 in 1 Display Module Nano vs UNO WiFi Rev2

I bought a board from Amazon that has eight 1088AS (8X8 LED) Modules. Each module is driven by a MAX7219 display driver. The LED sockets are perpendicular to the board rather than in line with the board. The input connection to the board is on the left, based on the IN – OUT marking on the modules.

I got the example working first with a NANO V3.

I am using the MD_Parola and MD_MAX72xx libraries. I started with the example sketch, “Parola_Scrolling”, and made minor customizations to work with the “8 in 1 Display Module”.

My customizations were:

· I used HARDWARE_TYPE: #define HARDWARE_TYPE MD_MAX72XX::FC16_HW

· I changed: #define MAX_DEVICES 8 instead of the example's 11

· I changed: uint8_t scrollSpeed = 75; instead of the default of 25 (faster)

· To reverse the scrolling direction: P.displayScroll("text", PA_LEFT, PA_SCROLL_RIGHT, 100);

· To reverse the scrolling direction: I used: scrollEffect = PA_SCROLL_RIGHT;

· P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);

· To flip the text top/bottom and left/right, I used:

o P.setZoneEffect(0, true, PA_FLIP_UD);

o P.setZoneEffect(0, true, PA_FLIP_LR);

My connections were:

#define CLK_PIN 13

#define DATA_PIN 11 // Nano: 11

#define CS_PIN 10 // Nano: 10

Now, what I want to do is be able to change the message with a web page using an “UNO WiFi Rev 2” as a web server. So I tried to get the same Parola scrolling script working on the UNO before complicating things by adding the Web Page interface. But just substituting the UNO board and using the same connections didn’t work. The display randomly gets most or all modules showing all LEDs on occasionally one is OFF. (I am using a 5v external power supply connected to the Arduino Vin connection.) The serial messages work on the UNO but the LED modules don't.

I used the same connections on the NANO and UNO as listed above.

Any ideas on what is different about the UNO WiFi Rev2?

This is my sketch. Note I kept the example's opening notes

// Use the Parola library to scroll text on the display

//

// Demonstrates the use of the scrolling function to display text received

// from the serial interface

//

// User can enter text on the serial monitor and this will display as a

// scrolling message on the display.

// Speed for the display is controlled by a pot on SPEED_IN analog in.

// Scrolling direction is controlled by a switch on DIRECTION_SET digital in.

// Invert ON/OFF is set by a switch on INVERT_SET digital in.

//

// UISwitch library can be found at 


// MD_MAX72XX library can be found at 


//

/*

I modified the library example to drive the 8-module, single board array I bought from Amazon:

EC Buying MAX7219 Dot Matrix 8 in 1 Display Module for Arduino Microcontroller - Electronic SCM Control Drive LED

The LED sockets are perpendicular to the board rather than in line with the board.




I used a different HARDWARE_TYPE: #define HARDWARE_TYPE MD_MAX72XX::FC16_HW

I changed #define MAX_DEVICES 8 instead of the example's 11

I changed uint8_t scrollSpeed = 75; instead of the default of 25 (faster)

To reverse the scrolling direction:P.displayScroll("text", PA_LEFT, PA_SCROLL_RIGHT, 100); 

I used:  scrollEffect = PA_SCROLL_RIGHT;

To reverse the scrolling direction: I used:  scrollEffect = PA_SCROLL_RIGHT;

  scrollEffect = PA_SCROLL_RIGHT;

  P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);

To flip the text top/bottom and left/right, I used:

  P.setZoneEffect(0, true, PA_FLIP_UD);

  P.setZoneEffect(0, true, PA_FLIP_LR);




I changed the text of the messages, and added a one-time message with the sketch name

*/




#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

/*

  There are four HARDWARE)TYPEs defined in MD_MAX72xx.h

    GENERIC_HW,   ///< Use 'generic' style hardware modules commonly available.

    FC16_HW,      ///< Use FC-16 style hardware module.

    PAROLA_HW,    ///< Use the Parola style hardware modules.

    ICSTATION_HW, ///< Use ICStation style hardware module.




*/

// NOTE: These pin numbers will probably not work with your hardware and may

// need to be adapted

//#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW

//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW

//#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW




#define MAX_DEVICES 8

#define CLK_PIN   13

#define DATA_PIN  11 // Nano: 11

#define CS_PIN    10 // Nano: 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 = 25;    // default frame delay value is 25. bigger number is slower.

textEffect_t scrollEffect = PA_SCROLL_LEFT;

textPosition_t scrollAlign = PA_LEFT;

uint16_t scrollPause = 2000; // in milliseconds




// Global message buffers shared by Serial and Scrolling functions

#define BUF_SIZE  75

char curMessage[BUF_SIZE] = { "Parola_Scrolling_Example_Modified.ino" };

char newMessage[BUF_SIZE] = { "Hello! Enter new message in the Serial Monitor." };

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(115200);

  Serial.print("\n[Parola_Scrolling_Example_Modified.ino]\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();




// To reverse the scrolling direction:P.displayScroll("text", PA_LEFT, PA_SCROLL_RIGHT, 100); 

  scrollEffect = PA_SCROLL_RIGHT;

  P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);

  P.setZoneEffect(0, true, PA_FLIP_UD);

  P.setZoneEffect(0, true, PA_FLIP_LR);

}




void loop()

{

#if USE_UI_CONTROL

  doUI();

#endif // USE_UI_CONTROL




  if (P.displayAnimate())

  {

    if (newMessageAvailable)

    {

      strcpy(curMessage, newMessage);

      newMessageAvailable = false;

    }

    P.displayReset();

  }

  readSerial();

}


Sorry, I will not read a sketch that is 50% vertical white space. I would not recommend an UNO, one of the Nano's with WiFi like the Nano 33 IOT would be a better bet.
When you say connections, what do you mean. Take a photo so we can read the pin numbers.

I am sorry that white spaces in code listings are distasteful to you. I did that to be able to pick out the functional parts of the program. In the sketch code, that you won't read, you would have seen:

#define CLK_PIN   13
#define DATA_PIN  11 // Nano: 11
#define CS_PIN    10 // Nano: 10

Since there are only three wires connecting the LED board to the Arduino, I don't think a photo will shed any more light on my problem.

I spent much time reading up on the UNO, SPI and the MAX7219 before I reached out for help. I wasn't inviting some snarky, condescending bloviation.

But thanks for your reply.

I think I know exactly what you have, but whenever I "know" something is when I am most wrong. The verbose description is confusing. Post a photo or a link to the device.

Post #1 code, un-white-spaced, 130 lines of code and 50 lines of comment
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Speed for the display is controlled by a pot on SPEED_IN analog in.
// Scrolling direction is controlled by a switch on DIRECTION_SET digital in.
// Invert ON/OFF is set by a switch on INVERT_SET digital in.
//
// UISwitch library can be found at
// MD_MAX72XX library can be found at

//
/*
I modified the library example to drive the 8-module, single board array I bought from Amazon:
EC Buying MAX7219 Dot Matrix 8 in 1 Display Module for Arduino Microcontroller - Electronic SCM Control Drive LED
The LED sockets are perpendicular to the board rather than in line with the board.
I used a different HARDWARE_TYPE: #define HARDWARE_TYPE MD_MAX72XX::FC16_HW
I changed #define MAX_DEVICES 8 instead of the example's 11
I changed uint8_t scrollSpeed = 75; instead of the default of 25 (faster)
To reverse the scrolling direction:P.displayScroll("text", PA_LEFT, PA_SCROLL_RIGHT, 100); 
I used:  scrollEffect = PA_SCROLL_RIGHT;
To reverse the scrolling direction: I used:  scrollEffect = PA_SCROLL_RIGHT;
 scrollEffect = PA_SCROLL_RIGHT;
 P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
To flip the text top/bottom and left/right, I used:
 P.setZoneEffect(0, true, PA_FLIP_UD);
 P.setZoneEffect(0, true, PA_FLIP_LR);
I changed the text of the messages, and added a one-time message with the sketch name
*/

#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
/*
 There are four HARDWARE)TYPEs defined in MD_MAX72xx.h
   GENERIC_HW,   ///< Use 'generic' style hardware modules commonly available.
   FC16_HW,      ///< Use FC-16 style hardware module.
   PAROLA_HW,    ///< Use the Parola style hardware modules.
   ICSTATION_HW, ///< Use ICStation style hardware module.
*/
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
//#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW
//#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11  // Nano: 11
#define CS_PIN 10    // Nano: 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 = 25;  // default frame delay value is 25. bigger number is slower.
textEffect_t scrollEffect = PA_SCROLL_LEFT;
textPosition_t scrollAlign = PA_LEFT;
uint16_t scrollPause = 2000;  // in milliseconds

// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
char curMessage[BUF_SIZE] = { "Parola_Scrolling_Example_Modified.ino" };
char newMessage[BUF_SIZE] = { "Hello! Enter new message in the Serial Monitor." };
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(115200);
  Serial.print("\n[Parola_Scrolling_Example_Modified.ino]\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();
  // To reverse the scrolling direction:P.displayScroll("text", PA_LEFT, PA_SCROLL_RIGHT, 100);
  scrollEffect = PA_SCROLL_RIGHT;
  P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
  P.setZoneEffect(0, true, PA_FLIP_UD);
  P.setZoneEffect(0, true, PA_FLIP_LR);
}

void loop() {
#if USE_UI_CONTROL
  doUI();
#endif  // USE_UI_CONTROL

  if (P.displayAnimate()) {
    if (newMessageAvailable) {
      strcpy(curMessage, newMessage);
      newMessageAvailable = false;
    }
    P.displayReset();
  }
  readSerial();
}

No, @sonofcy would have seen

#define CLK_PIN   13

#define DATA_PIN  11 // Nano: 11

#define CS_PIN    10 // Nano: 10

I can understand and endorse blank lines between functional parts of a sketch but for some reason your sketch as posted has blank lines between each line of code.

Does it look like that in the IDE and, if not, how did you copy it to paste here ?

No problem, good luck.

I think this is problem. The Uno's VIN input requires a minimum of 7v.
If you apply 5v to it, the board will operate erratically or not start at all.

I see what you are talking about. Now, thinking about it, the extra white space may have been caused by the way I composed my post. I wrote it out in MS Word, then copied and pasted it into the forum. That may have brought the word processor’s line formatting along with the text, even when I inserted the forum’s code block structure. When I included my sketch, I inserted a code block, went to the IDE, selected all, copied, and pasted it into the code block. I do have a lot of blank lines between parts of my code, but not between those specific define lines.

In any case, in the future, I will “launder” my text through a simple text editor to avoid unexpected formatting from a word processor.

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

You could also use:

No need to do that, either in the IDE use Edit/Copy for Forum then a simple paste in your reply works, the other way is conventional copy (CTL/CMD-C) from the IDE then paste into the < CODE > tag.
No need to go the extra step.

I wasn’t aware of the 7 volts minimum Vin. But I am still confused, because the NANO works fine with just the USB connector’s power. Adding an external power supply, with my setup and only 5v Vin, the script is running (based in the serial monitor messages) and the LEDs are very bright.

It looks like post 7 is your solution.

I think we are off on a tangent. I write my sketches in the Arduino IDE. I only used Word to compose my post, because I am skilled with Word, and used it so my post would be flawless. Apparently, that didn’t work.

I am still trying to understand why the same sketch works on the NANO but not on the UNO WiFi Rev2

Good advice. Thanks.

Different boards, different components, different power consumption.

When you connect power via the VIN, it's fed to the input of the voltage converter. Any converter operates with a difference between the input and output voltages, but this difference varies from one converter to another.
So in both cases your boards were running at a reduced voltage, but perhaps the Nano uses a more modern converter with lower losses, so the residual voltage was sufficient for the microcontroller to operate.
In any case, 7V is the VIN voltage that ensures stable operation on UNO/Nano boards.

Word adds stuff with every "save." Also, Word has fonts, functions and settings to format text in "console style" with "nolinefeed" Things you would want to learn.

No, I was trying to advise you where to format your code for posting on the forum. You just do not take advice well. It takes a few tries.