Multiplex MAX72xx Code

So, BroHogan put up the great multiplex code to be used with a matrix, but its only for 2 colors. I have tried to implent a third one, but i cant get it working, even tho i cant see anything wrong with my code.

Any pointers, tips?

Here is the Multiplex MAX72xx code:
http://www.arduino.cc/playground/Main/MultiplexMAX72xx

And here is my edit of the togShutdown:

void togShutdown(void) {    //This ISR toggles shutdown between the 3 MAX7221's
  switch (maxInShutdown) {
    case RED: 
      lc.shutdown(GREEN,true);
      lc.shutdown(BLUE,true);
      lc.shutdown(RED,false);
      maxInShutdown=GREEN;
      break;
    case GREEN:
      lc.shutdown(RED,true);
      lc.shutdown(BLUE,true);
      lc.shutdown(GREEN,false);
      maxInShutdown=BLUE;
      break;  
    case BLUE: 
      lc.shutdown(RED,true);
      lc.shutdown(GREEN,true);
      lc.shutdown(BLUE,false);
      maxInShutdown=RED;
      }
}

Worth mentioning is i also tried this:

void togShutdown(void) {    //This ISR toggles shutdown between the 3 MAX7221's
  if(maxInShutdown==GREEN){
    lc.shutdown(RED,true);
    lc.shutdown(BLUE,true);
    lc.shutdown(GREEN,false);
    maxInShutdown=RED;
  }
  else if(maxInShutdown==RED) {
    lc.shutdown(GREEN,true);
    lc.shutdown(BLUE,true);
    lc.shutdown(RED,false);
    maxInShutdown=BLUE;
  }
  else {
    lc.shutdown(RED,true);
    lc.shutdown(GREEN,true);
    lc.shutdown(BLUE,false);
    maxInShutdown=GREEN;
  }
}

By "can't get it working" what does this mean?
Do you have this wired up? If, yes, what happens?
If you can give a better definition of the problem and background you will get better help.

Just some thoughts . . .

If you have 3 chips, make sure you have set the LedControl lib to 3 MAX -
"LedControl lc=LedControl(10,9,8,3); // pins 10=DataIn, 9=CLK, 8=LOAD + 3 MAX7221s

Make sure you have your first color initialized.

(I would also rename the var "maxInShutdown" to something like "activeMax". This is just to avoid confusion since with 3 colors, you will always have 2 max in shutdown.)

I think the case statement will work OK in an ISR - unless the "break" dosn't break out. (I will try it myself later.)

Your problem could definitely be how it's wired.

To check your switch, you could set a counter for each color and do a serial print after say 1000 changes. (Note you can't use delay() in an ISR)

Hope this helps you troubleshoot.

Sorry, i will try to be more detailed in the future.
I have it all wired up of course, and i have set the LedControl to 3 max's.
And, its working just fine with the LedControl Examples - Cascadingdevices. I.e, i can see 3 different colors.

What happens with my 2 shutdown toggles from above^, is that the RGB LED glows very dimmed with only the color red, and nothing else.

int MaxInShutdown=RED -- makes the first color initialized, right? This is what im using anyway. (as i have put the first max in the chain for the color red)

Havent had time to try the counter suggestion, will do it as soon as i can.

Thanks for replying.

And, its working just fine with the LedControl Examples - Cascadingdevices. I.e, i can see 3 different colors.

I couldn't find a reference to "Cascadingdevices", but I take it that it proves to you that the wiring is OK.

I did try your switch statements in the ISR, it works fine for me but I only have 2 colors. It wouldn't hurt to add a "break;" at the end of case BLUE, but I don't think it will help either.

Also make sure you have "lc.setIntensity(BLUE,15);" in setup() and "lc.clearDisplay(BLUE);" in ClearMatrix().

I also assume you have -> #define BLUE 2, right?

I had the edits in the code, as you menitioned. But there was one thing i had not tried, and that was changing the MsTimer2!
It accured to me, that perhaps the ISR needed a bit more time to read the now longer code, so i changed the speed from 1ms to 2ms. And then it worked!
1 ms would be better of course.

Here is my code so far:

/* RG Matrix Example 
 * Demos 3 color 8x8 matrix driven by 3 MAX7821's 
 * THIS VERSION USES MsTIMER2 INSTEAD OF FrequencyTimer2
 */
#include <MsTimer2.h>                   // used to trigger the ISR
#include "LedControl.h"                 // to drive the matrix

#define RED 0                         // The address of the MAX7221 for the green leds
#define GREEN 1                           // The address of the MAX7221 for the red leds
#define BLUE 2
int maxActive=RED;                // tells which MAX7221 is currently on 

LedControl lc=LedControl(10,9,8,3); // pins 10=DataIn, 9=CLK, 8=LOAD + 3 MAX7221s 

void togShutdown(void) {    //This ISR toggles shutdown between the 3 MAX7221's
  switch (maxActive) {
    case RED: 
      lc.shutdown(GREEN,true);
      lc.shutdown(BLUE,true);
      lc.shutdown(RED,false);
      maxActive=GREEN;
      break;
    case GREEN:
      lc.shutdown(RED,true);
      lc.shutdown(BLUE,true);
      lc.shutdown(GREEN,false);
      maxActive=BLUE;
      break;  
    case BLUE: 
      lc.shutdown(RED,true);
      lc.shutdown(GREEN,true);
      lc.shutdown(BLUE,false);
      maxActive=RED;
      break;
      }
}  

void setup() {
  lc.setIntensity(RED,8);           // red needs less brightness
  lc.setIntensity(GREEN,8);             // 0 = dim, 15 = full brightness
  lc.setIntensity(BLUE,8);
  // set ISR speed 1Ms (1KHz) typ. + define the ISR
  MsTimer2::set(2, togShutdown); 
  MsTimer2::start();
}

void loop() { 
  SetLed(RED,0,1,true);
  delay(500);
  SetLed(GREEN,0,1,true);
  delay(500);
  SetLed(BLUE,0,1,true);
  delay(500);
  ClearMatrix();
  delay(500);
}


/////////   Wrappers for LedControl functions . . . //////////
void SetLed(byte Color, byte Row,byte Col, byte State){
  MsTimer2::stop();                   // stop toggling shutdown when updating MAX
  lc.setLed(Color,Row,Col,State);
  MsTimer2::start();                  // turn interupt back on
}

void SetRow(byte Color, byte Row, byte State){
  MsTimer2::stop();                   // stop toggling shutdown when updating MAX
  lc.setRow(Color,Row,State);
  MsTimer2::start();                  // turn interupt back on
}

void SetColumn(byte Color, byte Col, byte State){
  MsTimer2::stop();                   // stop toggling shutdown when updating MAX
  lc.setColumn(Color,Col,State);
  MsTimer2::start();                  // turn interupt back on
}

void ClearMatrix(){
  MsTimer2::stop();                   // stop toggling shutdown when updating MAX
  lc.clearDisplay(RED);
  lc.clearDisplay(GREEN);
  lc.clearDisplay(BLUE);
  MsTimer2::start();                  // turn interupt back on
}

Good for you :slight_smile: Happy to hear it.

I wish MsTimer2 could be set to finer times - like 0.5, 1.5, etc. Ms. But I guess that why it's called what it is. At some point I might take another shot at writing or finding another low level timer that is easily disabled.

So I imagine 2Ms is a little flickery? I notice you are only setting the intensity to 8 - about 50%. Would it improve is you went brighter?

Post back with your final results. I am curious to see how it works out.

I wouldnt mind finer timesettings myself, as this is a little bit flickery yes. But at least its one step further. :slight_smile:
I am mainly using intensity at 8 because i dont want to hurt my eyes while looking at the LED, ill try setting it higher to see any changes in the flicker.

Thanks for the support!

hello Steffensen & BroHogan,

I add the same result for 2 colors without ISR, for only 3x2 matrix.

int sizeX = 3;
int sizeY = 2;
 
int bitTable[8]={ 128, 64, 32, 16, 8, 4, 2, 1 };
 
int dataIn = 5;
int load = 6;
int clock = 7;
 
int maxInUse = 3;    //change this variable to set how many MAX7219's you'll use
 
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, LOW);       // and load da nuts
  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, LOW);
  digitalWrite(load,HIGH);
}
 
void maxOne(byte maxNr, byte reg, byte col) {    
//maxOne is for adressing different MAX7219's,
//whilele 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, LOW); // and load da nuts
  digitalWrite(load,HIGH);
}
 
 
void setup () {
  pinMode(dataIn, OUTPUT);
  pinMode(clock,  OUTPUT);
  pinMode(load,   OUTPUT);
 
//initiation of the max 7219
  maxAll(max7219_reg_scanLimit, 0x07);      
  maxAll(max7219_reg_decodeMode, 0x00);  // using an led matrix (not digits)
  maxAll(max7219_reg_shutdown, 0x00);    // not in shutdown mode
  maxAll(max7219_reg_displayTest, 0x00); // no display test
   for (e=1; e<=8; e++) {    // empty registers, turn all LEDs off
    maxAll(e,0);
  }
  maxAll(max7219_reg_intensity, 0x0f & 0x0f);    // the first 0x0f is the value you can set
                                               // range: 0x00 to 0x0f
 //Reset();
}  
 
void loop () {

// a little pattern very ugly
// it will be replace by a big function to update the matrix from serial messages sent from Max/msp to the board!
maxOne(1,1,128);
maxOne(1,2,64);
maxOne(2,1,32);
maxOne(2,2,190);

 
WakeUpR();
ShutdownR();
WakeUpB();
ShutdownB();
 
}
 
void ShutdownR()
{
  maxOne(1,max7219_reg_shutdown, 0x00);
}
 
void ShutdownB()
{
  maxOne(2,max7219_reg_shutdown, 0x00);
}
 
 
void WakeUpR()
{
  maxOne(1,max7219_reg_shutdown, 0x01);
}
 
void WakeUpB()
{
  maxOne(2,max7219_reg_shutdown, 0x01);
}

I'm sure ISR would be cleaner and more efficient.
But I DON'T have any flicker or very bad effects
It works fine

But the target is 8x8.
Do you think the fact the matrix is greater could create problems?

I tested this code with 3 colors... doesn't work :o :o probably my messsssy breadboard ;D