Advice needed for Max 7221 and Arduino Uno

Hi,
I am hoping that one of your very intelligent people can help me. I am attempting to make a simple LED matrix of 8 x 8 using a Max 7221 chip and a PCB that has been made for the purpose. I am following instructions but the matrix is simply doing nothing. This is a picture of the board with the components on:
http://www.flickr.com/photos/105962916@N05/10371735036/
and here is the board with the LED and other wires attached:
http://www.flickr.com/photos/105962916@N05/10372213463/

I am using this code:

//We always have to include the library
#include "LedControl.h"

/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 pin 12 is connected to the DataIn 
 pin 11 is connected to the CLK 
 pin 10 is connected to LOAD 
 We have only a single MAX72XX.
 */
LedControl lc=LedControl(12,11,10,1);

/* we always wait a bit between updates of the display */
unsigned long delaytime=100;

void setup() {
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,8);
  /* and clear the display */
  lc.clearDisplay(0);
}

/*
 This method will display the characters for the
 word "Arduino" one after the other on the matrix. 
 (you need at least 5x7 leds to see the whole chars)
 */
void writeArduinoOnMatrix() {
  /* here is the data for the characters */
  byte a[5]={B01111110,B10001000,B10001000,B10001000,B01111110};
  byte r[5]={B00111110,B00010000,B00100000,B00100000,B00010000};
  byte d[5]={B00011100,B00100010,B00100010,B00010010,B11111110};
  byte u[5]={B00111100,B00000010,B00000010,B00000100,B00111110};
  byte i[5]={B00000000,B00100010,B10111110,B00000010,B00000000};
  byte n[5]={B00111110,B00010000,B00100000,B00100000,B00011110};
  byte o[5]={B00011100,B00100010,B00100010,B00100010,B00011100};

  /* now display them one by one with a small delay */
  lc.setRow(0,0,a[0]);
  lc.setRow(0,1,a[1]);
  lc.setRow(0,2,a[2]);
  lc.setRow(0,3,a[3]);
  lc.setRow(0,4,a[4]);
  delay(delaytime);
  lc.setRow(0,0,r[0]);
  lc.setRow(0,1,r[1]);
  lc.setRow(0,2,r[2]);
  lc.setRow(0,3,r[3]);
  lc.setRow(0,4,r[4]);
  delay(delaytime);
  lc.setRow(0,0,d[0]);
  lc.setRow(0,1,d[1]);
  lc.setRow(0,2,d[2]);
  lc.setRow(0,3,d[3]);
  lc.setRow(0,4,d[4]);
  delay(delaytime);
  lc.setRow(0,0,u[0]);
  lc.setRow(0,1,u[1]);
  lc.setRow(0,2,u[2]);
  lc.setRow(0,3,u[3]);
  lc.setRow(0,4,u[4]);
  delay(delaytime);
  lc.setRow(0,0,i[0]);
  lc.setRow(0,1,i[1]);
  lc.setRow(0,2,i[2]);
  lc.setRow(0,3,i[3]);
  lc.setRow(0,4,i[4]);
  delay(delaytime);
  lc.setRow(0,0,n[0]);
  lc.setRow(0,1,n[1]);
  lc.setRow(0,2,n[2]);
  lc.setRow(0,3,n[3]);
  lc.setRow(0,4,n[4]);
  delay(delaytime);
  lc.setRow(0,0,o[0]);
  lc.setRow(0,1,o[1]);
  lc.setRow(0,2,o[2]);
  lc.setRow(0,3,o[3]);
  lc.setRow(0,4,o[4]);
  delay(delaytime);
  lc.setRow(0,0,0);
  lc.setRow(0,1,0);
  lc.setRow(0,2,0);
  lc.setRow(0,3,0);
  lc.setRow(0,4,0);
  delay(delaytime);
}

/*
  This function lights up a some Leds in a row.
 The pattern will be repeated on every row.
 The pattern will blink along with the row-number.
 row number 4 (index==3) will blink 4 times etc.
 */
void rows() {
  for(int row=0;row<8;row++) {
    delay(delaytime);
    lc.setRow(0,row,B10100000);
    delay(delaytime);
    lc.setRow(0,row,(byte)0);
    for(int i=0;i<row;i++) {
      delay(delaytime);
      lc.setRow(0,row,B10100000);
      delay(delaytime);
      lc.setRow(0,row,(byte)0);
    }
  }
}

/*
  This function lights up a some Leds in a column.
 The pattern will be repeated on every column.
 The pattern will blink along with the column-number.
 column number 4 (index==3) will blink 4 times etc.
 */
void columns() {
  for(int col=0;col<8;col++) {
    delay(delaytime);
    lc.setColumn(0,col,B10100000);
    delay(delaytime);
    lc.setColumn(0,col,(byte)0);
    for(int i=0;i<col;i++) {
      delay(delaytime);
      lc.setColumn(0,col,B10100000);
      delay(delaytime);
      lc.setColumn(0,col,(byte)0);
    }
  }
}

/* 
 This function will light up every Led on the matrix.
 The led will blink along with the row-number.
 row number 4 (index==3) will blink 4 times etc.
 */
void single() {
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      delay(delaytime);
      lc.setLed(0,row,col,true);
      delay(delaytime);
      for(int i=0;i<col;i++) {
        lc.setLed(0,row,col,false);
        delay(delaytime);
        lc.setLed(0,row,col,true);
        delay(delaytime);
      }
    }
  }
}

void loop() { 
  writeArduinoOnMatrix();
  rows();
  columns();
  single();
}

which is some simple demo code supplied with the LED library. I have made sure to the best of my knowledge that I have connected the correct pin sequence here:
http://www.flickr.com/photos/105962916@N05/10371719304/

I have connected power through a 5v voltage regulator. I have used a multimeter to check the 5v is getting to the board and the chip which it is. I have used the multimeter on the LED strips and appear to be getting around 1v per strip.

The sequence I have used to get the code to the board is as follows:
Open Arduino 1.0.5 on my Mac with the LED library included and paste in the code
Connect the Arduino PIN outs to the PCB
Plug the Arduino into my Mac via USB
Supply power to my PCB
Click 'upload' on the Arduino software on my Mac
It reports data upload complete and the Uno flashes for a minute and then has the constant amber light
Then......nothing. I get no response from the matrix. I have clicked the reset button, again the Arduino flashes but no response from the matrix.

Am I doing something wrong? If not, could somebody advice me of the fault finding process from here.

Thank you for reading my massive post lol.

Code tags, please.

Read this before posting a programming question

How to use this forum

Sorry, updated.

Your slide-show reveals this is the "Daft Punk" project. I think the original idea is to use transparent plastic to support the matrices so that you can at least see a little through it.

Someone else here is having great trouble with the "LedControl" library but this should not affect you - I don't think.

I do however suggest you might care to try a simple sketch which I have been using as a test, using no library as such, you just have to set your control pins at the start.

/* code for max 7219 from maxim, 
reduced and optimised for using more then one 7219 in a row,
______________________________________

General notes: 


-if you are only using one max7219, then use the function maxSingle to control
 the little guy ---maxSingle(register (1-8), collum (0-255))

-if you are using more then one max7219, and they all should work the same, 
then use the function maxAll ---maxAll(register (1-8), collum (0-255))

-if you are using more than one max7219 and just want to change something
at one little guy, then use the function maxOne
---maxOne(Max you wane controll (1== the first one), register (1-8), 
collum (0-255))

/* During initiation, be sure to send every part to every max7219 and then
 upload it.
For example, if you have five max7219's, you have to send the scanLimit 5 times
before you load it-- other wise not every max7219 will get the data. the
function maxInUse  keeps track of this, just tell it how many max7219 you are
using.
*/

#include <Wire.h> 

int dataIn = 2;            // "DIN" on module
int load = 3;              // "CS" on module
int clock = 4;             // ""CLK" on module
const int ledPin =  13;    // the number of the LED pin

int maxInUse = 1;    //change this variable to set how many MAX7219's you'll use
int ledState = LOW;         // ledState used to set the LED

int e = 0;                 // just a varialble

                     // define max7219 registers
byte max7219_reg_noop        = 0x00;
byte max7219_reg_digit0      = 0x01;
byte max7219_reg_digit1      = 0x02;
byte max7219_reg_digit2      = 0x03;
byte max7219_reg_digit3      = 0x04;
byte max7219_reg_digit4      = 0x05;
byte max7219_reg_digit5      = 0x06;
byte max7219_reg_digit6      = 0x07;
byte max7219_reg_digit7      = 0x08;
byte max7219_reg_decodeMode  = 0x09;
byte max7219_reg_intensity   = 0x0a;
byte max7219_reg_scanLimit   = 0x0b;
byte max7219_reg_shutdown    = 0x0c;
byte max7219_reg_displayTest = 0x0f;



void putByte(byte data) {
  byte i = 8;
  byte mask;
  while(i > 0) {
    mask = 0x01 << (i - 1);      // get bitmask
    digitalWrite( clock, LOW);   // tick
    if (data & mask){            // choose bit
      digitalWrite(dataIn, HIGH);// send 1
    }else{
      digitalWrite(dataIn, LOW); // send 0
    }
    digitalWrite(clock, HIGH);   // tock
    --i;                         // move to lesser bit
  }
}

void maxSingle( byte reg, byte col) {    
//maxSingle is the "easy"  function to use for a     //single max7219

  digitalWrite(load, LOW);       // begin     
  putByte(reg);                  // specify register
  putByte(col);        //((data & 0x01) * 256) + data >> 1); // put data   
  digitalWrite(load,HIGH); 
}

void maxAll( byte reg, byte col) {    // initialize  all  MAX7219's in the system
  int c = 0;
  digitalWrite(load, LOW);  // begin     
  for ( c =1; c<= maxInUse; c++) {
  putByte(reg);                  // specify register
  putByte(col);             //((data & 0x01) * 256) + data >> 1); // put data
    }
  digitalWrite(load,HIGH);
}

void maxOne(byte maxNr, byte reg, byte col) {    
//maxOne is for adressing different MAX7219's, 
//while having a couple of them cascaded

  int c = 0;
  digitalWrite(load, LOW);  // begin     

  for ( c = maxInUse; c > maxNr; c--) {
    putByte(0);    // means no operation
    putByte(0);    // means no operation
  }

  putByte(reg);  // specify register
  putByte(col);//((data & 0x01) * 256) + data >> 1); // put data 

  for ( c = maxNr-1; c >= 1; c--) {
    putByte(0);    // means no operation
    putByte(0);    // means no operation
  }

  digitalWrite(load,HIGH); 
}

void putCol( byte colno, byte coldat) {
// Interprets colno as (zero ref) index in combined array
    byte t;
    t = colno >> 3;
    byte u;
    u = colno & 0x07;
    maxOne(t+1, u+1, coldat);
}


void dispon () {
 maxAll(max7219_reg_shutdown, 0x01);               // Display on
}  

void dispoff () {
 maxAll(max7219_reg_shutdown, 0x00);              // Display off
}  

byte irow = 0;          // Row index
byte icol = 0;          // Column index
byte pattern;           // bit mask
byte lcol;              // left border
byte rcol;              // right border
byte trow;              // top row marker
byte brow;              // bottom row marker

int s_vert;             // Vertical switch
int s_horz;             // Horizontal switch

// the follow variable is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 40;           // interval at which to blink (milliseconds)
long previousMillis = 0;      // will store last time LED was updated
int scantype = 0;             // switch mode

void worker () {

  if (pattern == 0) pattern = trow;            // pattern must be set
  if (s_vert != 0) {
    if (s_vert == -1) {                     // moving upward
      pattern = pattern >> 1;
      if (pattern == trow) {                   // hit the top
        s_vert = 0; s_horz = 1;
      }
    } else {
      pattern = pattern << 1;               // moving downward
      if (pattern == brow) {                // hit the bottom
        s_vert = 0; s_horz = -1;
      }
    }
    putCol(icol,pattern);              // Show the column.
    return;
  }

  if (s_horz != 0) {
    putCol(icol,0);                    // blank previous column.
    if (s_horz == -1) {                     // moving left
      icol--;
      if (icol == lcol) {                      // hit the side
        s_horz = 0; s_vert = -1;
      }
    } else {
      icol++;                               // moving right
      if (icol == rcol) {                      // hit the side
        s_horz = 0; s_vert = 1;
      }
    }
    putCol(icol,pattern);              // Show the column.
  }
 }
  

void setup () {

  pinMode(dataIn, OUTPUT);
  pinMode(clock,  OUTPUT);
  pinMode(load,   OUTPUT);
  pinMode(ledPin, OUTPUT);      

  //Serial begin(9600);
  digitalWrite(13, HIGH);  

//initiation of the max 7219
  maxAll(max7219_reg_displayTest, 0x00); // no display test
  maxAll(max7219_reg_scanLimit, 0x07);      
  maxAll(max7219_reg_decodeMode, 0x00);  // using an led matrix (not digits)
  maxAll(max7219_reg_shutdown, 0x01);    // not in shutdown mode
  for (e=1; e<=8; e++) {        // empty registers, turn all LEDs off 
    maxAll(e,0);
  }
  maxAll(max7219_reg_intensity, 0x08 & 0x0f);    // the first 0x0f is the value you can set
                                                 // range: 0x00 to 0x0f
                                                 
  pattern = 0;
  scantype = 0;
  s_vert = 0;
  s_horz = 1;
  lcol = 1;              // left border
  rcol = 6;              // right border
  trow = 0x02;           // top row marker
  brow = 0x40;           // bottom row marker      
      
}  

void loop () {


  //if you use just one MAX7219 it should look like this
   /*  
   maxSingle(1,1);                       //  + - - - - - - -
   maxSingle(2,2);                       //  - + - - - - - -
   maxSingle(3,4);                       //  - - + - - - - -
   maxSingle(4,8);                       //  - - - + - - - -
   maxSingle(5,16);                      //  - - - - + - - -
   maxSingle(6,32);                      //  - - - - - + - -
   maxSingle(7,64);                      //  - - - - - - + -
   maxSingle(8,128);                     //  - - - - - - - +
  */
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    // Alternate 1

    }
    else {
      ledState = LOW;

    // Alternate 2
    // set the LED with the ledState of the variable:
    // Timed process:
    
    worker();

    }

    digitalWrite(ledPin, ledState);

    }

}

Hi,
Thanks for your reply. I am indeed working on that project. Harrison originally placed rubber supports under his boards as his visor was made from aluminium, however the one that I have from him is wood, so I believe they will be fine mounted straight onto the wood.

As for the code you posted, thank you. I found that somewhere else. Forgive my noobness but do I copy the entire code into the Arduino program and upload it as I saw it mention to only use maxSingle? I am not sure how to pull that bit out on it's own.

I was referring to using transparent plastic rather than opaque as you appear to have done, for the part into which the LEDs are placed, so that you can see through it between the LEDs.

My suggestion to try the code was that you simply put the code I posted into a new IDE sketch window, change the three control pins to match your allocation, and see what it does when you load it.

If it then seems to be more useful that what you have before, you might need to pick it to pieces to see what you can use. But I mean it primarily as a test.

The Parola project might be useful too.

Ah, I see. It is clear, it just had protective film over it.

Ah ok, cool. Thanks, I will try that.

Still nothing :frowning:

Just no response from the matrix at all. I feel like I am doing something wrong with the Arduino. Do I simply paste the code into a new sketch and then click upload? The L light is flashing amber rapidly now.

Is this your first sketch?

You need to be familiar with uploading sketches to your board, and then you wouldn't need to ask how to do it.

Pin 13 is the SCK line, and it wouldn't be too surprising if it flashed.

This is my page on the MAX7219 chip:

addypearce:
Just no response from the matrix at all. I feel like I am doing something wrong with the Arduino. Do I simply paste the code into a new sketch and then click upload? The L light is flashing amber rapidly now.

The D13 or "L" light flashing rapidly indicates that the sketch itself has loaded and is working. Granted that you have the three control lines correctly allocated in the first part of the code, the fact that it is not working does suggest a problem in the wiring to the MAX7221(s).

I just had to go back and check that sketch code is written for the MAX7221 as well as the MAX7219 as they are slightly different. But it is correct.

It has just occurred to me on looking at your photos, that I cannot see the ground wire from the volpinprops board to your Arduino. :astonished:

Thanks for the link, I have read up on the chips as much as I can, it's just very little I've found offers practical fault finding when it's on a PCB.

The ground from my board is connected to the negative terminal of my voltage regulator. Is that not right? I have read up on Arduino but I have very little time as I run 3 businesses, plus this is my first ever attempt at even soldering, plus my first attempt at any electronics.

I really appreciate your help.

addypearce:
The ground from my board is connected to the negative terminal of my voltage regulator. Is that not right?

You must connect the ground of the Arduino to the ground of the volpinprops board, otherwise the other three control wires mean nothing.

Ah, that's clearly the problem then. So the positive from my voltage regulator can go through to the VIN on my PCB, then the other 3 PIN outs go from the Arduino to the CLK, CS and DIN on my board, then the ground goes from my board to the Arduino.

Have I got that right?

I have tried wiring it up that way but still nothing. I have also tried taking the 5v and ground from the Arduino but again, nothing.

How do I know if the chip itself is ok? Is there a way of testing it with a multimeter?

addypearce:
Ah, that's clearly the problem then. So the positive from my voltage regulator can go through to the VIN on my PCB, then the other 3 PIN outs go from the Arduino to the CLK, CS and DIN on my board, then the ground goes from my board to the Arduino.

Have I got that right?

Not sure at all that you have. The Arduino is powered from the USB connection. The volpinprops board is powered from your power supply by connecting both the +5V and negative from the power supply directly to that board.

In order for the signals to be conveyed to the volpinprops board from the Arduino, you must have not only the three control wires, but you must connect the Arduino ground to the volpinprops board ground. There must be a continuity of connections between the power supply ground, the volpinprops board ground, and the Arduino.

Oh ok. Thank you for your response. So I now have the ground wire from the ground of the Arduino board going to the ground of the Volpin board. I have another wire connected to the same ground on the Volpin board and going to the negative of the power supply. Still nothing.

Well, it was worth a try - and is certainly a pre-requisite for things to work.

I know what you mean, I am just worried about blowing something, so I didn't want to go trying every combination. I am starting to understand a little more:
So the positive would come from the power supply.
Go to the left hand VCC on the volpin board.
Then the ground from GND on the right of the volpin board would go to the ground on the Arduino.
Then ground would go from the second ground on the Arduino back to the power supply, completing the circuit.
Then the CLK, CS and DIN would go to the relevant points on the volpin board.

I have read over the playground document again and it indicates that the Arduino should be able to power a matrix from it's own feed. Maybe I would be best to try the second board, just using the Arduino and forget about the power supply to make things easier for a test?

I appreciate your patience trying to help me, I am very much out of my depth.

Using my test program, the Arduino indicates it is powered by blinking the "L" LED.

If you verify 5V on the "volpinprops" board, and it is connected correctly - both to the Arduino and I hope you have the LED matrices connected with the right polarity - then I cannot think of much else to check.

I have been unable to find a description or images of that board. Hopefully it has no defects. You should test the LED matrices with a 5V supply and a 330 ohm series resistor. It will probably be OK to do this whist soldered to the un-powered driver board.

Thank you so much for taking the time to check that your end. It is reassuring.

The polarity of the LEDs is correct as I actually wired up a matrix and when I came to fit it, found it was the wrong way around. I double checked that I had followed the instructions from Harrison (Volpin) and I had. When I contacted him, he said that he had actually got it wrong and that was why he labelled the boards for clarity. I then changed the matrix and subsequent ones and really thoroughly checked everything to make sure that I had got it right.

Thank you also for suggesting checking the matrix with a separate power and resistor, I will be sure to do that. I have been checking every LED as I went along with a 9V battery and 390 ohm resistor. I will indeed check this on the matrix too, although one that is not wired up yet.

My mum noticed a couple of dry joints and so I have sorted those but with no change. I am going to go back and try the second board in a lot more careful and controlled way to see if I can get a response from the second matrix.

Thanks again so much for your time and patience.