MAX 7221 only lighting 2 lights per matrix

I am trying to wire up 5 8x8 matrices through MAX7221 chips that will be controlled by an arduino. Whenever I hook up the power to the boards, only 2 lights per matrix are lighting up. However, it's the same 2 lights per matrix. Would anyone happen to know what I could have done wrong to cause this? Is it just bad soldering where perhaps all of the pins aren't properly connected, but it just happens to be the same set of pins on every board?

Not enough information...

OK, let me see if I can be more specific. I don't know much about any of this.

I have 8x8 matrices made from single color (red) LED's. The columns are created by soldering together the negative legs of the LED's together and the rows are created by soldering the positive legs together.

A picture of the board layout is attached.

Can we see your sketch please, how you wired to the arduino etc.

That’s assuming you have done either yet! If not, don’t worry about the 2 leds coming on, its probably not important.

Paul

I don't have a sketch right now. I'll do a google search on how to create one.

I don't think it's an issue of it being wired to the arduino because, when I do connect to the arduino, only the 2 lights per matrix flash, which is pretty much the same result as when I only hook it directly to the battery. It's as if power/signal are only reaching those 2 LEDs.

Right now, I have pins 7, 8, and 9 set as my clock, load, and data pins, respectively. I have VIN coming off of a 5V pin and GND going to a GND pin.

If you don't have a sketch then what the LEDs do on switch on is totally meaningless and irrelevant. It indicates nothing.
Call back when you have a real problem

Yes, you need a sketch that sets up the MAX7221 registers telling it decode method, how many digits will be used, brightness, etc, and then you need to send some data that tells it which LEDs in each digit to turn on; there is a register per digit, so if you have 8x8 you need to send 8 registers worth of data.
Its not as complicated as it sounds - read the datasheet and do the register writes.

Also post your schematic, its a pain in the butt trying to work backwards from the board drawing.

OK, here's my update.

I traced where everything was going and compared that to the pinout for the chips. Then I emailed the person that made the boards an confirmed. The first problem is that the chip was backwards on each board because the instructions for assembly were written for a previous board version and weren't updated for v2. That explains all of my issues.

So, I de-soldered the connections and flipped the chips around. Unfortunately, now nothing comes on. I'm afraid that the chips have been damaged. Now my question is simple. How sensitive are these chips to basically being installed wrong? Should it be a simple flip it around and be ok, or is it closer to "you idiot, you just fried it." I'm pretty much guessing the latter, but input would help.

I don’t this particular chip will fry being flipped around.
That would put +5 on D3, and Gnds on SegE and SegB. Any protection diodes on D3 may be damaged.

You haven’t desrcribed your sketch yet. Nothing on could be normal.

When I got in touch with the guy that made the boards and the arduino software, he basically said as soon as it powers on that 2 rows of lights should turn on based on the way the arduino code is set up.

I’m trying to find software that includes a max chip that’ll also let me save as a picture file. I’m not actually just ignoring all of the sketch requests.

Wait… I’m an idiot. By sketch you probably mean code. Here you go. Again, please be easy on the noob.

#include "LedControl.h"
#include <Button2.h>

// Change these pin numbers as neccessary
char Pin_dataIn = 9; // data in pin
char Pin_clk = 7; // clk pin
char Pin_load = 8; // load pin
char numOfMatrices = 5; // increment this for each 7219 you've got connected.  I imagine this will be 5.
int brightness = 8; // set the brightness of the LEDs.  Use a value between 0 - 15
char screen[40];
char screenSize = 40;

char textBuffer[3][100];
char textBufferSize[3] = {90,51,66};

int pointer = 0;
long nextFrameTime = 0;
int effectType = 0;
int framePointer = 0;

// init led control object
LedControl lc = LedControl(Pin_dataIn,Pin_clk,Pin_load,numOfMatrices);
Button button = Button(4, HIGH);

/* we always wait a bit between updates of the display */
unsigned int delayTime=40;

void setup() {
  
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  for(int index=0;index<lc.getDeviceCount(); index++) {
    lc.shutdown(index,false);
    /* Set the brightness to a medium values */
    lc.setIntensity(index,brightness);
    /* and clear the display */
    lc.clearDisplay(index);
      
  }
  
  randomSeed(analogRead(0));
  button.setHoldDelay(3000);
  loadTextBuffers();
}



void loop() { 
  
  button.listen();
  
  if(button.onRelease()) {
    effectType++;
    
    if(effectType > 10) {
      effectType = 0;  
    }
    
    pointer = 0;
    framePointer = 0;
  }
  
  long current = millis();
  
  if(current > nextFrameTime) {
  
   nextFrameTime = current + delayTime; 
    
   switch(effectType) {
    case 0:
      effectThinLine();
      break;
    case 1:
       effectRandomPixels();
      break;
    case 2:
      effectScanner();
      break;  
    case 3:
      effectBlinkingEyes();
       break;
    case 4:
      effectTextScroll(0);
      break;
    case 5:
      effectTextScroll(1);
      break; 
    case 6:
      effectTextScroll(2);
      break;
    case 7:
      effectArrows();
      break;    
    case 8:
      effectECG();
      break;  
    case 9:
      effectScannerHorizontal();
      break;
    default:
      effectBlank();
      break;
  }

   display();
   
  }
   
}

void display() {
  
  unsigned char matrixID = 0;
  // screen now holds the updated values
  // write to the matrix
  for(unsigned char i = 0; i < numOfMatrices; i++) { 
    for(int j = 0; j < 8; j++) {
      
      int k = j;
       k += 1;
      if(k > 7) {
        k = 0;
      }
      
      char matrixID = 4 - i;
      //matrixID = 0;
      char bufferData = screen[((7-k)+(i*8))];
      char rowData = (bufferData >> 1) | (bufferData << 7);
     
      lc.setRow(matrixID,j,rowData);
    } 
  }
  
  /*
  for(unsigned char i = 0; i < screenSize; i++) {
   matrixID = floor(i/8);
    lc.setColumn(matrixID,i,screen[i]);
  }
  
   for(unsigned char i = 0; i < numOfMatrices; i++) { 
    for(unsigned char j = 0; j < 8; j++) {
      char matrixID = 4 - i;
      //matrixID = 0;
      lc.setColumn(matrixID,j,screen[(j+(i*8))]);
    }  
  }
  */
}

void scrollFromRight(int bufferNum) {
int offset = screenSize - pointer;
  for(unsigned char i = 0; i < screenSize; i++) {  
    screen[i] = getBufferData(bufferNum, i-offset);     
  }  
}

void scrollFromLeft(int bufferNum) {
int offset = (0-textBufferSize[bufferNum]) + pointer;
  for(unsigned char i = 0; i < screenSize; i++) {  
    screen[i] = getBufferData(bufferNum, i-offset);   
  }  
}

void staticCenter(int bufferNum) {
  int offset = round((screenSize - textBufferSize[bufferNum]) / 2);	
   for(unsigned char i = 0; i < screenSize; i++) {
    screen[i] = getBufferData(bufferNum, i-offset); 		
   }

}


char getBufferData(int bufferNum, int pos) {
    char tmp;
    if((pos >= 0) && ((pos) < textBufferSize[bufferNum])) {
      return textBuffer[bufferNum][pos];
    } else {
      return B00000000;
    }
}

void effectThinLine() {

  for(int i = 0; i < 40; i++) {
    screen[i] = B00011000;
  }
}  


void effectRandomPixels() {
  for(int i = 0; i < 40; i++) {
    screen[i] = random(256);
  }
}

void effectScanner() {
  for(int i = 0; i < 40; i++) {
    screen[i] = B00000000;
  }
  
  
  int tmpPointer = framePointer;
  
  if(framePointer > 37) {
    tmpPointer = 37 - (framePointer - 37);
  }
  
  for(int i = tmpPointer; i < (tmpPointer+3); i++) {
    screen[i] = B11111111;  
  }
  
  framePointer++;
  
  if(framePointer > 73) {
    framePointer = 0;
  }
  
}

void effectScannerHorizontal() {
  
   int tmpPointer = framePointer;
    
    if(framePointer > 6) {
        tmpPointer = 6 - (framePointer - 6);
     }
  
  for(int i = 0; i < 40; i++) {
    screen[i] = B10000000 >> (tmpPointer + 1);
  }
  
  display();
  delay(50);
  
  framePointer++;
  
  if(framePointer > 11) {
    framePointer = 0;
  }
  
}

void effectBlank() {
  for(int i = 0; i < 40; i++) {
    screen[i] = B00000000;
  }
}

void effectTextScroll(char bufferNum) {
   pointer += 1;
   
   if(pointer > (textBufferSize[bufferNum] + screenSize)) {
     pointer = 0;  
   }
   
   scrollFromRight(bufferNum);
}

void effectBlinkingEyes() {
  if(random(50) == 0) {

        
screen[0] =  B00000000;
screen[1] =  B00000000;
screen[2] =  B00000000;
screen[3] =  B00000000;
screen[4] =  B00000000;
screen[5] =  B00000000;
screen[6] =  B00000000;
screen[7] =  B00000000;
screen[8] =  B00011000;
screen[9] =  B00011000;
screen[10] = B00011000;
screen[11] = B00011000;
screen[12] = B00011000;
screen[13] = B00011000;
screen[14] = B00011000;
screen[15] = B00011000;
screen[16] = B00000000;
screen[17] = B00000000;
screen[18] = B00000000;
screen[19] = B00000000;

screen[20] = B00000000;
screen[21] = B00000000;
screen[22] = B00000000;
screen[23] = B00000000;
screen[24] = B00011000;
screen[25] = B00011000;
screen[26] = B00011000;
screen[27] = B00011000;
screen[28] = B00011000;
screen[29] = B00011000;
screen[30] = B00011000;
screen[31] = B00011000;
screen[32] = B00000000;
screen[33] = B00000000;
screen[34] = B00000000;
screen[35] = B00000000;
screen[36] = B00000000;
screen[37] = B00000000;
screen[38] = B00000000;
screen[39] = B00000000;

  display();
  
  delay(random(200, 350));
  }  else {
     screen[0] = B00000000;
screen[1] = B00000000;
screen[2] = B00000000;
screen[3] = B00000000;
screen[4] = B00000000;
screen[5] = B00000000;
screen[6] = B00000000;
screen[7] = B00000000;
screen[8] = B00011000;
screen[9] = B00111100;
screen[10] = B01100110;
screen[11] = B01100110;
screen[12] = B01100110;
screen[13] = B01100110;
screen[14] = B00111100;
screen[15] = B00011000;
screen[16] = B00000000;
screen[17] = B00000000;
screen[18] = B00000000;
screen[19] = B00000000;

screen[20] = B00000000;
screen[21] = B00000000;
screen[22] = B00000000;
screen[23] = B00000000;
screen[24] = B00011000;
screen[25] = B00111100;
screen[26] = B01100110;
screen[27] = B01100110;
screen[28] = B01100110;
screen[29] = B01100110;
screen[30] = B00111100;
screen[31] = B00011000;
screen[32] = B00000000;
screen[33] = B00000000;
screen[34] = B00000000;
screen[35] = B00000000;
screen[36] = B00000000;
screen[37] = B00000000;
screen[38] = B00000000;
screen[39] = B00000000;

  }
}

if(framePointer > 40) {
for(int i = 0; i < (framePointer-40); i++) {
  screen[i] = B00000000;
} 
}

framePointer++;

if(framePointer > 80) {
  framePointer = 0;
}


}

void effectECG() {
  
screen[0] =  B00001100;
screen[1] =  B00011000;
screen[2] =  B00110000;
screen[3] =  B01100000;
screen[4] =  B00110000;
screen[5] =  B00011000;
screen[6] =  B00001100;
screen[7] =  B00000110;
screen[8] =  B00001100;
screen[9] =  B00011000;
screen[10] = B00110000;
screen[11] = B01100000;
screen[12] = B00110000;
screen[13] = B00011000;
screen[14] = B00001100;
screen[15] = B00000110;
screen[16] = B00001100;
screen[17] = B00011000;
screen[18] = B00110000;
screen[19] = B01100000;
screen[20] = B00110000;
screen[21] = B00011000;
screen[22] = B00001100;
screen[23] = B00000110;
screen[24] = B00001100;
screen[25] = B00011000;
screen[26] = B00110000;
screen[27] = B01100000;
screen[28] = B00110000;
screen[29] = B00011000;
screen[30] = B00001100;
screen[31] = B00000110;
screen[32] = B00001100;
screen[33] = B00011000;
screen[34] = B00110000;
screen[35] = B01100000;
screen[36] = B00110000;
screen[37] = B00011000;
screen[38] = B00001100;
screen[39] = B00000110;

for(int i = framePointer; i < 40; i++) {
  screen[i] = B00000000;
} 


if(framePointer > 40) {
for(int i = 0; i < (framePointer-40); i++) {
  screen[i] = B00000000;
} 
}

framePointer++;

if(framePointer > 80) {
  framePointer = 0;
}


}

void loadTextBuffers() {
//stuff for words in here, truncated for character count limit
}

Well, I’m not gonna pretend I can follow all that uncommented code, maybe one of the software guys can.

This part:

void setup() {
  
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  for(int index=0;index<lc.getDeviceCount(); index++) {
    lc.shutdown(index,false);
    /* Set the brightness to a medium values */
    lc.setIntensity(index,brightness);
    /* and clear the display */
    lc.clearDisplay(index);
      
  }
  
  randomSeed(analogRead(0));
  button.setHoldDelay(3000);
  loadTextBuffers();
}

Is there something in this library
#include “LedControl.h”

that sets up the other control registers?
“On initial power-up, all control registers are reset, the
display is blanked, and the MAX7219/MAX7221 enter
shutdown mode. Program the display driver prior to
display use. Otherwise, it will initially be set to scan one
digit, it will not decode data in the data registers, and
the intensity register will be set to its minimum value.”

Shutdown - this one looks to be addressed
Intensity - this one looks to be addressed

Decode Mode - ??
Scan Limit - ??
Display Test - ??

And here - why cripple yourself? Things would go a lot faster if SPI was used:
char Pin_dataIn = 9; // data in pin
char Pin_clk = 7; // clk pin
char Pin_load = 8; // load pin
This part works great with default SPI settings at 4 MHz transfer rate.

How long will this run for? This may be an issue if left powered up long enough, when millis rolls over from 0xFFFF to 0x0001 I think it will look to freeze up while nextFrameTime is 0xFFC0 or similar:

long current = millis(); << time elements should be unsigned long, that’s what millis returns.

if(current > nextFrameTime) { << better is to use if ( (current - nextFrameTime) >= delayTime) { and then nextFrateTime = nextFrameTime + delayTime;

I'm using the standard ledcontrol library from Arduino Playground - LedControl. This is supposed to run for maybe a couple hours at a time, but the button would likely be pressed every few minutes to scroll through different things. Right now, my first priority is getting this to turn on and display SOMETHING and fine tuning can come after. But I do appreciate the input.

In the library, it mentions the scan limit but I don't see anything about decode or display test.

A decent chunk of the library code is below

class LedControl {
 private :
    /* The array for shifting the data to the devices */
    byte spidata[16];
    /* Send out a single command to the device */
    void spiTransfer(int addr, byte opcode, byte data);

    /* We keep track of the led-status for all 8 devices in this array */
    byte status[64];
    /* Data is shifted out of this pin*/
    int SPI_MOSI;
    /* The clock is signaled on this pin */
    int SPI_CLK;
    /* This one is driven LOW for chip selectzion */
    int SPI_CS;
    /* The maximum number of devices we use */
    int maxDevices;
    
 public:
    /* 
     * Create a new controler 
     * Params :
     * dataPin		pin on the Arduino where data gets shifted out
     * clockPin		pin for the clock
     * csPin		pin for selecting the device 
     * numDevices	maximum number of devices that can be controled
     */
    LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);

    /*
     * Gets the number of devices attached to this LedControl.
     * Returns :
     * int	the number of devices on this LedControl
     */
    int getDeviceCount();

    /* 
     * Set the shutdown (power saving) mode for the device
     * Params :
     * addr	The address of the display to control
     * status	If true the device goes into power-down mode. Set to false
     *		for normal operation.
     */
    void shutdown(int addr, bool status);

    /* 
     * Set the number of digits (or rows) to be displayed.
     * See datasheet for sideeffects of the scanlimit on the brightness
     * of the display.
     * Params :
     * addr	address of the display to control
     * limit	number of digits to be displayed (1..8)
     */
    void setScanLimit(int addr, int limit);

    /* 
     * Set the brightness of the display.
     * Params:
     * addr		the address of the display to control
     * intensity	the brightness of the display. (0..15)
     */
    void setIntensity(int addr, int intensity);

    /* 
     * Switch all Leds on the display off. 
     * Params:
     * addr	address of the display to control
     */
    void clearDisplay(int addr);

    /* 
     * Set the status of a single Led.
     * Params :
     * addr	address of the display 
     * row	the row of the Led (0..7)
     * col	the column of the Led (0..7)
     * state	If true the led is switched on, 
     *		if false it is switched off
     */
    void setLed(int addr, int row, int col, boolean state);

    /* 
     * Set all 8 Led's in a row to a new state
     * Params:
     * addr	address of the display
     * row	row which is to be set (0..7)
     * value	each bit set to 1 will light up the
     *		corresponding Led.
     */
    void setRow(int addr, int row, byte value);

    /* 
     * Set all 8 Led's in a column to a new state
     * Params:
     * addr	address of the display
     * col	column which is to be set (0..7)
     * value	each bit set to 1 will light up the
     *		corresponding Led.
     */
    void setColumn(int addr, int col, byte value);

    /* 
     * Display a hexadecimal digit on a 7-Segment Display
     * Params:
     * addr	address of the display
     * digit	the position of the digit on the display (0..7)
     * value	the value to be displayed. (0x00..0x0F)
     * dp	sets the decimal point.
     */
    void setDigit(int addr, int digit, byte value, boolean dp);

    /* 
     * Display a character on a 7-Segment display.
     * There are only a few characters that make sense here :
     *	'0','1','2','3','4','5','6','7','8','9','0',
     *  'A','b','c','d','E','F','H','L','P',
     *  '.','-','_',' ' 
     * Params:
     * addr	address of the display
     * digit	the position of the character on the display (0..7)
     * value	the character to be displayed. 
     * dp	sets the decimal point.
     */
    void setChar(int addr, int digit, char value, boolean dp);
};

Also, I just looked in the CPP file. This snippet should answer the questions about decode, scan, and displaytest.

LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
SPI_MOSI=dataPin;
SPI_CLK=clkPin;
SPI_CS=csPin;
if(numDevices<=0 || numDevices>8 )
numDevices=8;
maxDevices=numDevices;
pinMode(SPI_MOSI,OUTPUT);
pinMode(SPI_CLK,OUTPUT);
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
for(int i=0;i<64;i++)
status*=0x00;*

  • for(int i=0;i<maxDevices;i++) {*
  • spiTransfer(i,OP_DISPLAYTEST,0);*
  • //scanlimit is set to max on startup*
  • setScanLimit(i,7);*
  • //decode is done in source*
  • spiTransfer(i,OP_DECODEMODE,0);*
  • clearDisplay(i);*
  • //we go into shutdown-mode on startup*
  • shutdown(i,true);*
  • }*
    }
    int LedControl::getDeviceCount() {
  • return maxDevices;*
    }
    void LedControl::shutdown(int addr, bool b) {
  • if(addr<0 || addr>=maxDevices)*
  • return;*
  • if(b)*
  • spiTransfer(addr, OP_SHUTDOWN,0);*
  • else*
  • spiTransfer(addr, OP_SHUTDOWN,1);*
    }

void LedControl::setScanLimit(int addr, int limit) {

  • if(addr<0 || addr>=maxDevices)*
  • return;*
  • if(limit>=0 || limit<8)*
  • spiTransfer(addr, OP_SCANLIMIT,limit);*
    }
    void LedControl::setIntensity(int addr, int intensity) {
  • if(addr<0 || addr>=maxDevices)*
  • return;*
  • if(intensity>=0 || intensity<16) *
  • spiTransfer(addr, OP_INTENSITY,intensity);*

}[/quote]