Using 2 MAX72xx

I have a 2 color 8x8 LED Matrix (common cathode) that I want to drive using 2 MAX7221s. For the columns, the matrix has 2 sets of 8 anodes - one for each color. So essentially it's like an eight digit LED with [u]16[/u] segments.

I did find a white paper on that type usage - http://www.maxim-ic.com/appnotes.cfm/appnote_number/1004 but it was pretty brief.

However, what I gather is that both chips are connected to the same 8 rows (digits, cathodes) and that each chip drives it's own set of 8 columns (segment, anode).

The paper also mentioned alternating shutdown of the two chips to prevent "ghosting".

Has anyone had any experience with this? Is this the best way to go? If so, are there any examples? I'm not sure how to code the "alternating shutdown" bit. (I'm using the LedControl library.)

Any help would be appreciated. Thanks!

Hi,

I looked at the schematic on the link, and it looks like the alphanumeric Led-displays have 2 common cathodes. I'm afraid the solution proposed in the article is not possible with your LedMatrix as you decribe it. (There are 16 Led's hooked up to a common cathode is that right?)

I don't know any solution for your problem, but maybe someone else does. But anyway the one proposed on the link doesn't work with your matrix.

Eberhard

Eberhard, thanks for your response and thanks very much for the excellent library you made.

Yes my matrix has 16 LEDs hooked to a common cathode for each row. (Here is the matrix - http://www.sparkfun.com/commerce/product_info.php?products_id=682 which has a link to the data sheet.)

Regarding the Maxim schematic, I'm not sure that there are 2 common cathodes per [u]digit[/u]. It shows [u]8[/u] 14 segment digits, and the text says "All 14 segments share the same common cathode".

However the schematic was a little confusing until I noticed that pin #'s (16 & 11) were used twice for each block of 2 digits. (Hope that makes sense!)

Anyway, if this changes your mind, please let me know. There must be some way to drive booth colors on this display!

Hi, you're right all 16 Leds have a common cathode.

The datasheet for the MAX72XX says this about the the digit-outputs:

Eight-Digit Drive Lines that sink current from the display common cathode. The MAX7219 pulls the digit outputs to V+ when turned off. The MAX7221[ch8217]s digit drivers are high-impedance when turned off.

In my interpretation that means the whole thing is possible only with the MAX7221. A Max7219 would lead to a short circuit when the digit-lines are connected in parallel. The high-impedance feature seems to be the trick here.

In your software you have to ensure that one of the max7221 is in shutdown mode at any time. The datasheet only has a timing for waking up from shutdown-mode, not going into it :-(

A piece of code for toggeling shutdown-mode could look like this :

//The address of the MAX7221 for the red leds
#define MAX_FOR_RED 0
//The address of the MAX7221 for the green leds
#define MAX_FOR_GREEN 1
//initialize the global var that tells which MAX7221 is currently off 
int maxInShutdown=MAX_FOR_RED;  


//toggle shutdown between the 2 MAX7221
void toggleShutDown() {
    //we put both devices into shutdown for safety
    lc.shutdown(MAX_FOR_RED,true);
    lc.shutdown(MAX_FOR_GREEN,true);
    //I would use a bit of delay so things can settle
    delay(2);
    //now pull the sleeping one out of shutdown mode
    lc.shutdown(maxInShutdown,false);
    // and switch to the other MAX for the next call to this function
    if(maxInShutdown==MAX_FOR_RED) {
        maxInShutdown=MAX_FOR_GREEN;
    }
    else {
        maxInShutdown=MAX_FOR_RED;
    }
}

Notes : Do not wake up the MAX7221 from shutdown in the setup routine like it is shown in the LedControl-tutorial! You have to call the toggleShutDown()-method regulary (every 10 ms ??) so you don't notice a flicker. If you know how to implement a timer interrupt ( I don't :-( ) that would be the thing to use here.

My thoughts so far, Ill keep watching for updates from you..

Eberhard

Eberhard, thanks for pursuing this further.

It's interesting that it's likely that only the MAX7221 will work in this case. I was wondering why they choose to float the pins when it was off. I thought it had something to do with reduced EMI.

Happily, the 2 samples I had already requested are the 7221. They should be here this week.

I will have plenty to do just working with a single color, however, when that is done I will add a timer interrupt and the toggle shutdown function to your LedControl-tutorial example. When I get that working, I will post it here.

While waiting for the chips, I will investigate using D. Fowler's tutorial on making an interrupt timer (http://www.uchobby.com/index.php/2007/11/24/arduino-interrupts)

John

Toggling the shutdown between the 2 MAX7221s seems to work pretty well.
(This was needed in my case because of the two color 8x8 SparkFun matrix I was using -
http://www.sparkfun.com/commerce/product_info.php?products_id=682 .)

I used a simple ISR timer that would do the toggle at 122Hz.

Below is a shortened version of the LedControl-tutorial example that demonstrates this technique.

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

// Below for MAX7221s with 2 color support
#define MAX_FOR_GREEN 0                // The address of the MAX7221 for the green leds
#define MAX_FOR_RED 1                  // The address of the MAX7221 for the red leds
int maxInShutdown=MAX_FOR_GREEN;       // tells which MAX7221 is currently off 

/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 pin 10 is connected to the DataIn 
 pin 9 is connected to the CLK 
 pin 8 is connected to LOAD (CS)
 We now have two MAX7221s 
 NOTE: MAX7219s may not work if matrix has red & green anodes tied together
 */
LedControl lc=LedControl(10,9,8,2);

/* we always wait a bit between updates of the display */
unsigned long delaytime=125;
byte light_green = true;

void setup() {
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call (NOTE: shutdown is now handled bt the interrupt)
   */

  /* Set the brightness of each set to a medium values */
  lc.setIntensity(0,8);
  lc.setIntensity(1,8);
  /* and clear both the displays */
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  /* Start the ISR timer to begin the alternate wakeup & shutdown of the two 7221s */
  runISRtimer();      // optimum setting seems to be around 122Hz
}

void loop() { 
  single();
}

/* 
 This function will light up every Led on the matrix.
 The first pass will alternate between green and red.
 The second pass will light the green LED along with already lite red LED, making orange. 
 */
void single() {
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      delay(delaytime);
      if (light_green == true) lc.setLed(0,row,col,true);
      else lc.setLed(1,row,col,true);
      light_green = !light_green;
    }
  }
  light_green = !light_green;
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      delay(delaytime/2);
      if (light_green == true) lc.setLed(0,row,col,true);
      //else lc.setLed(1,row,col,true);
      light_green = !light_green;
    }
  }
  delay(delaytime);
  lc.clearDisplay(0);                     // sometimes a row or part of one does not clear
  delay(21);                              // clear sometimes comes when MAX is shutdown ??
  lc.clearDisplay(0);                     // wait a bit and call clear again - helps!

  delay(delaytime*2);
  lc.clearDisplay(1);
  delay(21);                              // same idea for second MAX
  lc.clearDisplay(1);                     // wait a bit and call clear again
}

void runISRtimer(){                       // ISR timer preset for 122 ISRs/sec BEST setting
  TCCR2A = 0;                             // set mode=0
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;   // set prescaler=1024
  TIMSK2 = 1<<TOIE2;            // set interrupts=enabled (calls ISR(TIMER2_OVF_vect) )
  TCNT2 = 128;  //reset timer -seting should match in runISRtimer() & ISR -higher = faster
}

ISR(TIMER2_OVF_vect) {                    // called 122 times per second (16Meg/1024)/128)
  TCNT2 = 128;  //reset timer -seting should match in runISRtimer() & ISR - higher = faster
  //toggle shutdown between the 2 MAX7221
  lc.shutdown(MAX_FOR_RED,true);          // put both devices into shutdown for safety
  lc.shutdown(MAX_FOR_GREEN,true);        // does not work without doing this tnx Eberhard!
  lc.shutdown(maxInShutdown,false);       // pull the sleeping one out of shutdown mode
  if(maxInShutdown==MAX_FOR_RED) maxInShutdown=MAX_FOR_GREEN; // switch for next call
  else maxInShutdown=MAX_FOR_RED;
}

It’s not perfect - sometimes a row driven by one of the 7221’s is not turned off. However, it suits my purpose just fine.
My thanks to all who helped.

In case someone finds this useful, I just tried this with 2 MAX7219's rather than the MAX7221's and they seem to work just as well.