daisychaining MAX7219

I have got my single 7x5 matrix going OK using Crossroads example from last year.

Unfortunately when I laid out my PCB, I have my rows in the wrong order for the MD_MAX or other libraries.

( I havn't connected to the 14, 16, and 21 pins of the MAX )

As you can see from the sketch below, I have made a start on the array for my characters - I have made the pattern for "G" to display on my arrays.

I am having trouble getting my head around the daisychaining for the next matrix.

It would appear I could just take the CS low, send out the setup data twice, and take the CS high again.

To send the character pattern would appear to be the same, but I just can't seem to get it to the second matrix ( which has all the LEDs lit at the moment.)

I dont want to use a separate CS line for each matrix, as there will be quite a lot of matrices matrii ?.

Can anyone suggest what to do as per the test sketch below ? ( I have removed all my useless attempts - this just displays one "G" )

    #include <SPI.h>
    byte ss0 = 10;
    byte x;
    // define variables
    // bytes to send to MAX7219s, with some initial data
    byte displayArrayG[] = {  0x13,0x88,0x80,0x80,0x99,0x88,0x13 };
  // char letter[] = {'A', 'B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S'
 //  ,'T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9','.','-',' ','t' };
    // define 7219 register addresses for setup
    byte NOOP = 0x0;
    byte decode_mode = 0x09; // 0x00 = No decode for digits 7-0
    byte intensity_level = 0x0A; // 0x08 = mid level. Range is 0x00 to 0x0F
    byte scan_limit = 0x0B; // 0x07 for all columns
    byte shutdown_normal = 0x0C; // 0x00 - shutdown, 0x01 = normal
    byte display_test = 0x0F; // 0x00 = normal, 0x01 = display test mode all on full
    // ************************************ //

    void setup(){
    
      pinMode (ss0, OUTPUT);
      digitalWrite (ss0, HIGH);    
      Serial.begin(9600);
      SPI.begin();
      SPI.setClockDivider(SPI_CLOCK_DIV8);
    
      /*  set up MAX7219 registers  */
    
      // decode to No decode mode
      digitalWrite (ss0, LOW);
      SPI.transfer (decode_mode);
      SPI.transfer (0x00);
      digitalWrite (ss0, HIGH);    
      Serial.println("No decode mode");
    
      // intensity to mid level
      digitalWrite (ss0, LOW);
      SPI.transfer (intensity_level);
      SPI.transfer (0x0f);
      digitalWrite (ss0, HIGH);   
      Serial.println("Intensity");
    
      // scan limit to all 7 columns
      digitalWrite (ss0, LOW);
      SPI.transfer (scan_limit);
      SPI.transfer (0x06);
      digitalWrite (ss0, HIGH);    
      Serial.println("Scan Limit");
      digitalWrite (ss0, LOW);
      SPI.transfer (display_test);
      SPI.transfer (0x01);
      digitalWrite (ss0, HIGH);
      delay(200);  
      Serial.println("Display test on");
    
      // dispay test to normal
      digitalWrite (ss0, LOW);
      SPI.transfer (display_test);
      SPI.transfer (0x00);
      digitalWrite (ss0, HIGH);
      delay(200);  
      Serial.println("Display test off");
      // shutdown to Normal mode
      digitalWrite (ss0, LOW);
      SPI.transfer (shutdown_normal);
      SPI.transfer (0x01);
      digitalWrite (ss0, HIGH);   
      Serial.println("Normal mode"); 
      delay(250); 
      Serial.println("setup done");    
    }   
   void loop(){
    
     delay(1000);
    for (x = 1; x<9; x=x+1){ //          clear display
        digitalWrite (ss0, LOW);
        SPI.transfer (x);   // row 
        SPI.transfer(0x00);// array 0 to 7
        digitalWrite (ss0, HIGH);
      }
    
     for (x = 1; x<8; x=x+1){
    digitalWrite (ss0, LOW);
    SPI.transfer (x);
    SPI.transfer(displayArrayG [x-1]);// array 0 to 7
    digitalWrite (ss0, HIGH);
  }
     
    } // end loop

Well, if, for example, you have 4 max7219, you would do something like this:

    for (x = 1; x<8; x=x+1){
      digitalWrite (ss0, LOW);
      for (int m=0; m<4, m++) {
        SPI.transfer (x);
        SPI.transfer(displayArrayG [x-1]);// array 0 to 7
      }
      digitalWrite (ss0, HIGH);
    }

Paul

Thanks Paul

I swapped transition connectors, to edge connectors when I assembled the boards, and the data in/ out pins didnt go through to the next board.

Your suggestion is working, and even the Sfiftout try also works. But I will leave it SPI.

I can now write to both matrices , using the sketch below.
If both letters are the same its fine and stable, but if they are different, then the second one ( I am feeding in from the right ) has errors, and both displays have odd LEDs flickering.

( I still have to figure out the bitmap array I just have 2 letters so far )

#include <SPI.h>
const int CHIP_COUNT = 2;  // how many MAX7219s
byte ss0 = 10;
byte x;
// define variables
// bytes to send to MAX7219s, with some initial data
// byte displayArrayG[] = {  0x13,0x88,0x80,0x80,0x99,0x88,0x13,0x00 };
byte displayArrayG[] = {  
  19,136,128,153,137,136,19 };
byte displayArrayA[] = {  
  1,18,136,136,155,136,136};
//   char letter[] = {'A', 'B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1
,'2'
// ,'3','4','5','6','7','8','9','.','-',' ','t' };
// define 7219 register addresses for setup
byte NOOP = 0x0;
byte decode_mode = 0x09; // 0x00 = No decode for digits 7-0
byte intensity_level = 0x0A; // 0x08 = mid level. Range is 0x00 to 0x0F
byte scan_limit = 0x0B; // 0x07 for all columns
byte shutdown_normal = 0x0C; // 0x00 - shutdown, 0x01 = normal
byte display_test = 0x0F; // 0x00 = normal, 0x01 = display test mode all on full
// ************************************ //

void setup(){

  pinMode (ss0, OUTPUT);
  digitalWrite (ss0, HIGH);   
  Serial.begin(9600);
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV8);  
  /*  set up MAX7219 registers  */
  // decode to No decode mode
  digitalWrite (ss0, LOW);

  for (int m=0; m<2 ; m++ ){
    SPI.transfer (decode_mode);
    SPI.transfer (0x00);
  }
  digitalWrite (ss0, HIGH);    
  Serial.println("No decode mode");  
  // intensity to mid level
  digitalWrite (ss0, LOW);
  for (int m=0; m<2 ; m++ ){
    SPI.transfer (intensity_level);
    SPI.transfer (0x0F);
  }
  digitalWrite (ss0, HIGH);    
  Serial.println("Intensity");   
  // scan limit to all 7 columns
  digitalWrite (ss0, LOW);
  for (int m=0; m<2 ; m++ ){
    SPI.transfer (scan_limit);
    SPI.transfer (0x06);
  }
  digitalWrite (ss0, HIGH);  
  Serial.println("Scan Limit");
  // dispay test On
  digitalWrite (ss0, LOW);
  for (int m=0; m<2 ; m++ ){
    SPI.transfer (display_test);
    SPI.transfer (0x01);
  }
  digitalWrite (ss0, HIGH);
  delay(200);   
  Serial.println("Display test on");   
  digitalWrite (ss0, LOW);
  for (int m=0; m<2 ; m++ ){
    SPI.transfer (display_test);
    SPI.transfer (0x00);
  }
  digitalWrite (ss0, HIGH);
  delay(200); 
  Serial.println("Display test off");  
  // shutdown to Normal mode
  digitalWrite (ss0, LOW);
  for (int m=0; m<2 ; m++ ){
    SPI.transfer (shutdown_normal);
    SPI.transfer (0x01);
  }
  digitalWrite (ss0, HIGH);  
  Serial.println("Normal mode");  
  delay(250);

  Serial.println("setup done");

}
// ************************************ //

void loop(){

  delay(500);
  for (x = 1; x<8; x=x+1){ //          clear display
    digitalWrite (ss0, LOW);
    for (int m=0; m<CHIP_COUNT ; m++ ) 
    {        
      SPI.transfer (x);   // row 
      SPI.transfer(0x00);// array 0 to 7
    }
    digitalWrite (ss0, HIGH);
  }

  ////////////*********************************
  //delay(5);

  for (x = 1; x<8; x=x+1){    //   
    digitalWrite (ss0, LOW);    
    //  for (int m=0; m<2 ; m++ ) {       
    SPI.transfer (x);
    SPI.transfer(displayArrayA [x-1]);// array 0 to 6  
    // }
    digitalWrite (ss0, HIGH);
  }   
  for (x = 1; x<8; x=x+1){//   
    digitalWrite (ss0, LOW);   
    //  for (int m=0; m<2 ; m++ ) 
    // {          
    SPI.transfer (x);
    SPI.transfer(displayArrayA[x-1]);// array 0 to 6  
    // }
    digitalWrite (ss0, HIGH);
  }   
} // end loop

Looks like you're getting close. Need to transfer some NOPs so one display ignores data intended for the 2nd?

Thanks Nick, I have studied that , you said

To make use of this you basically have to treat them like a serial of shift register

With TPIC6B595 chips daisychained I just send all displays data through at once if I want to udpate all displays.
The datasheet seemed to imply that this can be done :-

For the MAX7219, serial data at DIN, sent in 16-bit packets, is shifted into the internal 16-bit shift register with each rising edge of CLK regardless of the state of
LOAD. The data is then latched into either the digit or control registers on the rising edge of LOAD/CS.
LOAD/CS must go high concurrently with or after the 16th rising clock edge, but before the next rising clock edge or data will be lost. Data at DIN is propagated through the shift register and appears at DOUT 16.5 clock cycles later.

I read about the NOOP but you said that was for updating just one chip in the chain.
So if want to update say 8 chips with new text, I have to send the 16 bytes of new data for each chip, along with 14 NOOPs ?

Thats 210 bytes to update the text?

But reading again, you say I can send REGISTER/DATA x number of times without a NOOP, it will just push on through, or do I need to raise the LOAD pin for each chip?

Your sendString routine only raises the LOAD after you have sent all the data.
Rather than NOOPs, I would think that just feeding enough data into the first DATAin would clear all the chips anyway?

Please bear with me here, I just find the old shift reg/latch chips so easy, and its taking me some time to get my head around these chips.
( I did try a lot of experiments with the questions above, but the interpcb wiring was faulty at the time , so it was wasted time )

I haven't daisychained them yet, I'll defer to Nick on this one.

Thanks, I will have another play with them this morning, I still need to see if I can use Nicks PROGREM array storage for my bitmaps

Er, no, you don't have to send a lot of useless NOPs.

The NOPs are filler if you just one to update one chip, for example the third one in the chain, so you send the data you want plus enough NOPs to make that data reach the third chip.

I think my example was generic in that you could say "update chip 2, character 5 to read '7' ".

You could do it with a minimal number of sends, you just have to get them in the right order (taking into account your row/column data and which order you have arranged them visually).

Thanks guys,
Interestingly enough, there is no problem with sending using Shiftout .

I think I will wire up a few more pcbs and test both SPI and Shiftout.
I need two x 8 character team names for this project, but the next job has 24 characters.
( This current project also has 28 x 7seg displays which I will use TPICs for. )

for (x = 1; x<8; x=x+1){
         digitalWrite (latchPin, LOW);
           shiftOut(dataPin, clockPin, MSBFIRST, x);  
           shiftOut(dataPin, clockPin, MSBFIRST, (displayArrayG [x-1]));
            shiftOut(dataPin, clockPin, MSBFIRST, x);  
           shiftOut(dataPin, clockPin, MSBFIRST, (displayArrayA [x-1]));    
          digitalWrite (latchPin, HIGH);

}

Right, its working with 4 displays now, so it should be easy with 8 ( or all 16 )

The displays ( which I call tiles ) all plug together and will eventually have a +5 and ground bus soldered between them.

The tiles are clicked into a specially manufactured top and bottom rail. er OK , I confess, they are the covers from 16mm electrical trunking that pcbs happen to fit tightly into the grooves :slight_smile:

Whilst my Grandkids think this display is " cool " I have only made the letters G and A for my array library so far . I am not a Lady Gaga fan ..

Thanks for the help.

Cool 8)

Oh dear, you can only make 4-letter words? Well I'm sure you'll be able to think of a few more. :slight_smile:

I tell you what Nick, the family has heard a few such words while I have been struggling with getting this going !

Now I must finish the alphabet ..