MD_MAX72xx Sketch Not Looping

Hi,

I am creating a sketch which takes the input from Three potentiometers and depending on the Value for each pot, drives a series of 16 8X8 MAX7219 LED Matrices for each Potentiometer, but having trouble getting this to operate as I expect.

To keep things simple initially I have set it up with one Potentiometer on Pin A0 and only 8 MAX7219 Matrices (FC16-HW) on Pot 1

My sketch does not seem to loop continuously and doesn’t display the Columns of Leds dependant on the value of the input potentiometer (i,e, In the form of a Bar Graph)

I am probably missing the obvious but have studied the MD_MAX72xx library examples but just can’t see where I am going wrong ??

Any pointers would be greatly appreciated, thanks.

Fimez.

// INCLUDES
// Used to control a panel of MAX7219 LED displays based on the input from a Potentiometer.
#include <MD_MAX72xx.h>
//#include <SPI.h>

// DEFINES
// Turn on/off debugging
#define DEBUG  1

#if  DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTD(x) Serial.println(x, DEC)

#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTD(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
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES  8

#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS

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

// We always wait a bit between updates of the display
#define  DELAYTIME  100  // in milliseconds

// CONSTANTS
// The analogue input pins to which the potentiometers are connected.
const byte potPins[] = {A0, A1, A2};
// The total number of valves ****** Currently only one potentiometer in use ********
// Hopefully in the final sketch hope to use three Potentiometers a three lots of four 8X8 Matracies
const byte numPots = 1;

// GLOBALS
// This array will record the current reading of each input valve  **** Currently Only 1 In use *****
int currentReadings[numPots] = {};

/**
 * Initialisation
 */
void setup(){
  
    #ifdef DEBUG
    // Initialise serial communications channel with the PC
    Serial.begin(9600);
  #endif
  // Set the linear pot pins as input
  for(int i=0; i<numPots; i++){
    // Set the pin for the pot
    pinMode(potPins[i], INPUT);
  }

}

// Create a fixed map function:
long map2(long x, long in_min, long in_max, long out_min, long out_max) {
        return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min;
}

/**
 *  Read the input from the potentiometer/s and store in the currentReadings array
 */
void getInput() {
  // Read the value from the pots
  for(int i=0; i<numPots; i++){
    // Get the "raw" input, which is a value from 0-1023
    int rawValue = analogRead(potPins[i]);
    int totalColumns = mx.getColumnCount();
    // Scale the value to the number of LEDs in each strip
    int scaledValue = map2(rawValue, 0, 1023, 0, totalColumns);
    // To ensure we don't get any dodgy values, constrain the output range too
    scaledValue = constrain(scaledValue, 0, totalColumns);
    // Store the scaled value in the currentReadings array
    currentReadings[i] = scaledValue;
    // Print some debug information
    #if DEBUG
      Serial.print("Valve ");
      Serial.print(i);
      Serial.print(" raw:");
      Serial.print(rawValue);
      Serial.print(", scaled:");
      Serial.println(scaledValue);
      Serial.print(", Total Colums  ");
      Serial.println(mx.getColumnCount());
      //delay(500);
    #endif
  }
}

/**
 * Set the LEDs dependant on the scaled value */
void setDisplay() {
  // Loop over each input
  for(int pot=0; pot<numPots; pot++)
  {
      //PRINTS("nCols 0->max");
      mx.clear();
      Serial.println("Display Should Be Clear");
      for (uint8_t col=(currentReadings[pot]); col<mx.getColumnCount(); col++)
      {
        mx.setColumn(col, 0x00);
        }
       for (uint8_t col=0; col<currentReadings[pot]; col++)
        {
        mx.setColumn(col, 0xff);
        delay(500);
            }
      }
}
 /**
 * Main program loop runs indefinitely
 */
void loop()
{
  getInput();
  setDisplay();

// Future Code To Be Written Once Sketch Completed To Operate 
// With Three Potentiomenters and Three Strips of 4 8X8 Matracies
//
}

Can you post a schematic of your wiring.
Have you got any power supply decoupling on those matrix drivers?
Is your power supply up to providing the amount of current it is being asked to supply.

  // Set the linear pot pins as input
  for(int i=0; i<numPots; i++){
    // Set the pin for the pot
    pinMode(potPins[i], INPUT);
  }

You do not need to use pinMode with pins you are using as an analogue input.

Grumpy_Mike, thanks for the response, I have actually found the issue I was having so have now got the Sketch working with One Potentiometer.

I am using a separate 5Volt 2Amp Power Supply to feed the Matrices and a standard 12 Volt Power Supply feeding the Uno Board, I have a 100uF Capacitor across the Matrices Vcc / Gnd supply pins.

If I don’t need to use pinMode cn you tell me how I should define this, although it is doing what I want it to.

I now want to progress the Sketch, by adding another set of Matrices which will be controlled by a second Potentiometer connected to analogue input A2, but not sure how to do this using the Hardware SPI Interface.

I presume from some other snippets I have seen, that I can use the same CLK pin and DATA pin but use a different CS pin, but not sure how the MAX_DEVICES and HARDWARE_TYPE should be configured to add this second string of Matrices to do this.

I can put a Schematic of the hardware together tomorrow if it helps ?

Fimez.

// INCLUDES
// Used to control a panel of MAX7219 LED displays based on the input from a Potentiometer.
#include <MD_MAX72xx.h>
//#include <SPI.h>

// DEFINES
// Turn on/off debugging
#define DEBUG  1

#if  DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTD(x) Serial.println(x, DEC)

#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTD(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
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES  8

#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS

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

// We always wait a bit between updates of the display
#define  DELAYTIME  100  // in milliseconds

// CONSTANTS
// The analogue input pins to which the potentiometers are connected.
const byte potPins[] = {A0, A1, A2};
// The total number of valves ****** Currently only one potentiometer in use ********
// Hopefully in the final sketch hope to use three Potentiometers a three lots of four 8X8 Matracies
const byte numPots = 1;

// GLOBALS
// This array will record the current reading of each input valve  **** Currently Only 1 In use *****
int currentReadings[numPots] = {};

/**
 * Initialisation
 */
void setup(){
  
    mx.begin();

#if  DEBUG
  Serial.begin(57600);
#endif
  PRINTS("n[MD_MAX72XX Test & Demo]");
//  scrollText("MD_MAX72xx Test  ");

  // Set the linear pot pins as input
  for(int i=0; i<numPots; i++){
    // Set the pin for the pot
    pinMode(potPins[i], INPUT);
  }

}

// Create a fixed map function:
long map2(long x, long in_min, long in_max, long out_min, long out_max) {
        return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min;
}

/**
 *  Read the input from the potentiometer/s and store in the currentReadings array
 */
void getInput() {
  // Read the value from the pots
  for(int i=0; i<numPots; i++){
    // Get the "raw" input, which is a value from 0-1023
    int rawValue = analogRead(potPins[i]);
    int totalColumns = mx.getColumnCount();
    // Scale the value to the number of LEDs in each strip
    int scaledValue = map2(rawValue, 0, 1023, 0, totalColumns);
    // To ensure we don't get any dodgy values, constrain the output range too
    scaledValue = constrain(scaledValue, 0, totalColumns);
    // Store the scaled value in the currentReadings array
    currentReadings[i] = scaledValue;
    // Print some debug information
    #if DEBUG
      Serial.print("Valve ");
      Serial.print(i);
      Serial.print(" raw:");
      Serial.print(rawValue);
      Serial.print(", scaled:");
      Serial.println(scaledValue);
      Serial.print(", Total Colums  ");
      Serial.println(mx.getColumnCount());
      //delay(500);
    #endif
  }
}

/**
 * Set the LEDs dependant on the scaled value */
void setDisplay() {
  //mx.clear();
  // Loop over each input
  for(int pot=0; pot<numPots; pot++)
  {
      //PRINTS("nCols 0->max");
      
      Serial.println("Display Should Be Clear");
      for (uint8_t col=(currentReadings[pot]); col<mx.getColumnCount(); col++)
      {
        mx.setColumn(col, 0x00);
        }
       for (uint8_t col=0; col<currentReadings[pot]; col++)
        {
        mx.setColumn(col, 0xff);
        //delay(500);
            }
      }
}
 /**
 * Main program loop runs indefinitely
 */
void loop()
{
  getInput();
  setDisplay();

// Future Code To Be Written Once Sketch Completed To Operate 
// With Three Potentiomenters and Three Strips of 4 8X8 Matracies
//
}

Sorry, had Alerts and Emails turned off, still finding my way around the Forum :slight_smile:

Fimez.

If I don't need to use pinMode cn you tell me how I should define this, although it is doing what I want it to.

Not sure what you mean. You can still use the array to define what analogue input you want to read, it is just that there is no need to define them as inputs. As soon as you use an analogRead call they get switched automatically to analogue inputs no matter what they were before, so pinMode is unnecessary.

I presume from some other snippets I have seen, that I can use the same CLK pin and DATA pin but use a different CS pin, but not sure how the MAX_DEVICES and HARDWARE_TYPE should be configured to add this second string of Matrices to do this.

You need to create an other instance of the MD_MAX72XX class.
You use this line

 MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

Only change mx to another name and what number pin you use for the CS_PIN, like

 MD_MAX72XX mx2 = MD_MAX72XX(HARDWARE_TYPE, 7,);

And also change the number of MAX_DEVICES if this is different.
Note here ou can use numbers in place of the defined constants or define new constants and put them in your new class declaration. Then everywhere You use A0 you use A1.

I fact you can use an array for the class declaration if you like and cut down on any repetition.

Thanks Grumpy_Mike, I will try adding the second set of LED Matrices and second pot today following your advice and see how I get on.

I was a little confused by which pins were reserved for the SPI Hardware interface, but looking back at my sketch it looks like the SPI Include is hashed out anyway so not using SPI as such in this instance.

I was interested in what you were saying about using numbers in place of the defined constants but couldn't quite grasp what you meant.

Grumpy_Mike:
Note here ou can use numbers in place of the defined constants or define new constants and put them in your new class declaration. Then everywhere You use A0 you use A1.

I fact you can use an array for the class declaration if you like and cut down on any repetition.

Will let you know how I get on with the rest of the sketch and thanks again for the feedback.

Fimez.

Grumpy_Mike, well I think I am almost there, I didn’t have much luck creating another MD_MAX72XX instance using common pins (except the CS Pin), so to keep things simple I created two totally separate instances as follows which seems to work in a modified MD_MAX72XX_Test example which was supplied with the library.

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES  8

#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS
#define CLK_PIN1   9  // or SCK1
#define DATA_PIN1  7  // or MOSI1
#define CS_PIN1    6  // or SS1

// SPI hardware interface
//MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary pins
MD_MAX72XX mx0 = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
MD_MAX72XX mx1 = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN1, CLK_PIN1, CS_PIN1, MAX_DEVICES);
// We always wait a bit between updates of the display
#define  DELAYTIME  100  // in milliseconds

But the bit I am struggling with now is trying to address both instances in a loop, probably due to my lack of knowledge of Arduino coding as you can see from this extract.

/**
 * Set the LEDs dependant on the scaled value */
void setDisplay() {
  int totalColumns = 64;
  // Loop over each input
  for(int pot=0; pot<numPots; pot++)
  {
      //PRINTS("\nCols 0->max");
      
      Serial.println("Display Should Be Clear");
      for (uint8_t col=(currentReadings[pot]); col<totalColumns; col++)
      {
        mx[pot].setColumn(col, 0x00);
        }
       for (uint8_t col=0; col<currentReadings[pot]; col++)
        {
        mx[pot].setColumn(col, 0xff);
        //delay(500);
            }
      }
}

Is it possible to address the different MD_MAX72XX instances in a loop like this, or am I trying to achieve the impossible, as I am just getting compile errors:-

exit status 1

‘mx’ was not declared in this scope

To avoid wading through lots of code I have not included the whole sketch, but hopefully you can see what I am trying to achieve with two Potentiometers and two chains of MD_MAX72XX Matrices.

Fimez.

mx' was not declared in this scope

You used

 mx[i]

But you never created an array called mx. You created two instances called mx1 and mx2.
That is not an array.

Thanks Grumpy_Mike, I think you have probably guessed my next question, is it possible to put MD_MAX7219 instances into an array or do I need to find a different way to loop through the two (or more) instances that I have.

MD_MAX72XX mx0 = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
MD_MAX72XX mx1 = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN1, CLK_PIN1, CS_PIN1, MAX_DEVICES);

Using them in a loop would make my overall Sketch much cleaner and easier to use, I hope.

/**
 * Set the LEDs dependant on the scaled value */
void setDisplay() {
  int totalColumns = 64;
  // Loop over each input
  for(int pot=0; pot<numPots; pot++)
  {
      //PRINTS("\nCols 0->max");
      
      Serial.println("Display Should Be Clear");
      for (uint8_t col=(currentReadings[pot]); col<totalColumns; col++)
      {
        mx[pot].setColumn(col, 0x00);
        }
       for (uint8_t col=0; col<currentReadings[pot]; col++)
        {
        mx[pot].setColumn(col, 0xff);
        //delay(500);
            }
      }
}

Schematic Attached..............Hope to use three Potentiometers and three sets of Displays in the finished project.

Thanks in advance,

Fimes

, is it possible to put MD_MAX7219 instances into an array

Yes it is.
They variable type is MD_MAX72XX so make an array of this type called mx

 MD_MAX72XX mx[2];

Then put the instances in them

 MD_MAX72XX mx[0] = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
MD_MAX72XX mx[1] = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN1, CLK_PIN1, CS_PIN1, MAX_DEVICES);

I have not compiled, as I am on a mobile devise so there may be a slight syntax error In it.

Thanks for the schematic. I think 100uF is way too small. I would use at lease 450uF on each end of each strip, so at least four of them. And check the current of one strip before adding the other two.

Why would you use a 12 V supply to power the Arduino if you have a proper regulated 5 V supply? :roll_eyes:

I don't even put 5V regulators in many projects - just power them from 5V wallwart.

I'll just chip in here and say that it may be easier to create one display of 12 matrices and divided it into 3 zones of 4. One connection to the display(s) and the software takes care of where the displays start and end.

However, there may be good reason to do using 3 separate CS pins which are not clear to me.

EDIT: Zones are automatic in MD_Parola, this is using MD_MAX72xx, that is a good reason :). It would not be hard, however, to have the matrix updates takes care of in the same way within the sketch, as the requirement is just to show LED 'bars' moving.

Grumpy_Mike, thanks for the array tips, so obvious when you see it written down, will try it out this evening but been tied up most of the day with other mundane stuff, will let you know how I get on.

I took your point about the decoupling Capacitors and have some larger ones on order. :slight_smile:

marco_c, feel free to chip in as much as you like, I have looked at the MD_Parola library and it would probably be another good option to use one large matrix with Zones, but I am only just getting my head around the MD_MAX7219 library after realising that the Led_Control library I was originally using was far to limited in it's abilities.

I am planning more projects along similar lines in the near future so will start to play with MD_Parola library and Zones in those projects as it looks very useful, thanks for the tips.

Paul__B, the only reason I used a 12V Power Supply was that I have experienced issues in the past using a 5V Power Supply for the Arduino in the past on Circuits which were drawing a significant amount of current such that the 5V Supply was dropping down significantly to below 4 Volts in some instances causing issues.

As the Arduino has it's own onboard 5V Regulator and I had a spare 12V Power Supply to hand it seemed sensible to use it. You are correct a decent 5V Regulated Power Supply would do the job, but I just feel that it's better to have a few spare volts available just in case of any loading issues :slight_smile:

CrossRoads, Not sure what you mean by a 5V Wallwart, not a term I have come across in the U.K. I am tending to use which ever power supplies are most suitable and which I have readily to hand for bench testing before purchasing the final components for the finished project but thanks for the input.

5V wallwart example:

Easy to find one with the appropriate input voltage and plug style for your country.

Grumpy_Mike, still struggling a little with the MD_MAX7219 arrays, with compilation errors which as you suspected, is probably due to syntax mistakes on my part.

int MD_MAX72XX mx[2];


exit status 1
expected initializer before 'mx'

I am also a little unsure where in the code is the best place to declare the MD_MAZ7219 arrays and instances.

I have attached the entire sketch if it helps and of course you have the time and inclination to help me out again.

Fimez.

// INCLUDES
// Used to control a panel of MAX7219 LED displays based on the input from a Potentiometer.
#include <MD_MAX72xx.h>

// DEFINES
// Turn on/off debugging
#define DEBUG  1

#if  DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTD(x) Serial.println(x, DEC)

#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTD(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

// SPI hardware interface
//MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary pins
int MD_MAX72XX mx[2];
#define  DELAYTIME  100  // in milliseconds
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES  8
#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS
#define CLK_PIN1   9  // or SCK1
#define DATA_PIN1  7  // or MOSI1
#define CS_PIN1    6  // or SS1
MD_MAX72XX mx[0] = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
MD_MAX72XX mx[1] = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN1, CLK_PIN1, CS_PIN1, MAX_DEVICES);
// We always wait a bit between updates of the display

// CONSTANTS
// The analogue input pins to which the potentiometers are connected.
const byte potPins[] = {A0, A2, A4};
// The total number of valves ****** Currently only two potentiometers in use ********
// Hopefully in the final sketch hope to use three Potentiometers a three lots of four 8X8 Matracies
const byte numPots = 2;

// GLOBALS
// This array will record the current reading of each input valve  **** Currently Only 2 In use *****
int currentReadings[numPots] = {};
/**
 * Initialisation
 */
void setup(){
    mx[0].begin();
    mx[1].begin();
#if  DEBUG
  Serial.begin(57600);
#endif
  PRINTS("\n[MD_MAX72XX Test & Demo]");

  // Set the linear pot pins as input
  for(int i=0; i<numPots; i++){
    // Set the pin for the pot
    pinMode(potPins[i], INPUT);
  }

}

// Create a fixed map function:
long map2(long x, long in_min, long in_max, long out_min, long out_max) {
        return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min;
}

/**
 *  Read the input from the potentiometer/s and store in the currentReadings array
 */
void getInput() {
  int totalColumns = 64;
  // Read the value from the pots
  for(int i=0; i<numPots; i++){
    // Get the "raw" input, which is a value from 0-1023
    int rawValue = analogRead(potPins[i]);
    // Scale the value to the number of LEDs in each strip
    int scaledValue = map2(rawValue, 0, 1023, 0, totalColumns);
    // To ensure we don't get any dodgy values, constrain the output range too
    scaledValue = constrain(scaledValue, 0, totalColumns);
    // Store the scaled value in the currentReadings array
    currentReadings[i] = scaledValue;
    // Print some debug information
    #if DEBUG
      //Serial.print("Valve ");
      //Serial.print(i);
      //Serial.print(" raw:");
      //Serial.print(rawValue);
      //Serial.print(", scaled:");
      //Serial.println(scaledValue);
      //Serial.print(", Total Columns  ");
      //Serial.println(totalColumns);
      //delay(500);
    #endif
  }
}

/**
 * Set the LEDs dependant on the scaled value */
void setDisplay() {
  int totalColumns = 64;
  // Loop over each input
  for(int pot=0; pot<numPots; pot++)
  {
      //PRINTS("\nCols 0->max");
      
      Serial.println("Display Should Be Clear");
      for (uint8_t col=(currentReadings[pot]); col<totalColumns; col++)
      {
        mx[pot].setColumn(col, 0x00);
        }
       for (uint8_t col=0; col<currentReadings[pot]; col++)
        {
        mx[pot].setColumn(col, 0xff);
        //delay(500);
            }
      }
}
 /**
 * Main program loop runs indefinitely
 */
void loop()
{
  getInput();
  setDisplay();

}

int MD_MAX72XX mx[2];

I didn’t say int did I?

No you didn’t say int, but I tried both with and without and some other various things but still get compile errors unfortunately :confused:

Using int is wrong. What error do you get without it?

Without it I get ............

exit status 1
no matching function for call to 'MD_MAX72XX::MD_MAX72XX()'