LED Control Library

Can anyone tell if the LED Control Library only works for/with the Max72XX chips or can you use the library if your LED matrix is wired directly to your Arduino?

I currently have an 8x8 matrix wired directly to the the arduino and have a sketch that scans through the columns and rows. What I would like to do is set patterns within the matrix and then have those patterns triggered by MIDI input.

Just getting started and have never used an led matrix so any suggestions or advice welcome.

Should I multiplex or just just keep it wired directly to the Arduino?

Thanks-
ru

Can anyone tell if the LED Control Library only works for/with the Max72XX chips or can you use the library if your LED matrix is wired directly to your Arduino?

It is written specifically for the MAX72xx chips and will not work with Leds driven directly from the Arduino-pins
Eberhard

Thanks!

Are you using a Arduino Mega?

No I am using the Diecimila atmeg 168.

How are you getting 16 outputs then?

My setup is this:
Arduino atmega 168
Sparkfun MIDI breakout board
8x8 led matrix (currently I am only running single color with dual color matrix)

I have the outputs wired to pins:
digital pins 2-13 and then analog pins 0-4.

Here is the test code for the col/row scan that seems to work fine:
int row[] = {
17,16,15,14,5,4,3,2};

int col[] = {
13,12,11,10,9,8,7,6};

void setup() {
for (int thisPin = 0; thisPin < 8; thisPin++) {
// initialize the output pins for matrix 1:
pinMode(col[thisPin], OUTPUT);
pinMode(row[thisPin], OUTPUT);
// take the col pins (i.e. the cathodes) high to ensure that
// the LEDS are off:
digitalWrite(col[thisPin], HIGH);
}
}

void loop() {
// light up the matrix:
// iterate over the rows (anodes):
for (int thisrow = 0; thisrow < 8; thisrow++) {
// take the row pin (anode) high:
digitalWrite(row[thisrow], HIGH);
// iterate over the cols (cathodes):
for (int thiscol = 0; thiscol < 8; thiscol++) {
// when the row is high and the col is low,
// the LED where they meet turns on:
digitalWrite(col[thiscol], LOW);
delay(1000);
// take the col pin (cathode) high to turn the LED off:
digitalWrite(col[thiscol], HIGH);
}
// take the row pin low to turn off the whole row:
digitalWrite(row[thisrow], LOW);
}

// do the same to go backwards, counting backwards:

// matrix in reverse:
for (int thisrow = 7; thisrow > 0; thisrow--) {
digitalWrite(row[thisrow], HIGH);
for (int thiscol = 7; thiscol >0; thiscol--) {
digitalWrite(col[thiscol], LOW);
delay(1000);
digitalWrite(col[thiscol], HIGH);
}
digitalWrite(row[thisrow], LOW);
}
}

The issue I am having is running a set pattern,i.e., "HELLO". My end goal is to trigger the patterns via a MIDI input signal. For now I am just trying to get the patterns working.
I am happy to send the code I have been using for that as well if you think you mind be able to help me trouble shoot it.

Thanks-

The reason I asked is because I built a 5x5 matrix as a prototype to a 8x8. Then I went to build the 8x8 and thought I ran out of OUTPUT pins. I didn't realize (until I just looked it up) that I can use Analog In as GPIO, as long as they are all GPIO.

For my rows, I go through a ULN2803. I didn't like the idea of my ATMega Sourcing and Sinking the current. My fear was if I messed up my code, I might take out a pin. And 8 LEDs at 20mA each starts getting close to the max current the chip can handle.

On my 5x5, I have an animation working.

I have an integer (matrixState) that represents the current display. In my state machine I have a loop that goes through the matrix and updates each LED based on matrixState. This loop has been designed to make the LEDs appear as bright as possible, but spend as little time as possible there.

Arrays are used to keep track of the characters. I generated a 3 character string based on my Matrix's output. In the main loop, I load one column at a time from my characters[] array into the matrixState.

There have to be better ways to do this. My goal was to get a 8x8 PCB done (my protoboards aren't big enough) so I could do an 8x8. I need to optimize the hardware and software more.

My code is badly commented and I switch between the concept of Rows/Cols and Source/Sink all over the place. To be honest, I put the project aside because I thought I'd have to add a multiplexer to make it work.

One of the major keys I will tell you is that you won't be able to use the delay() function. You really need to write your own. The matrix needs to keep updating, even while you wait for LEDs to stay on long enough. See myDelay() at the very end.

/*  LED Matrix, starting to play with matrixes for the first time.  */

#define numOfSources 5
#define numOfSinks 5
#define matrixSize 25
#define bigWait 500 // milliseconds
#define povWait 750  // microseconds
#define animationWait 50 // milliseconds
#define frames 10

int sourcePins[numOfSources] = {2,3,4,5, 6};
int sinkPins[numOfSinks]     = {7,8,9,10,11};

unsigned long characters[3] = {0x118FE31, 0x1F2109F, 0x0421004};
unsigned long checkeredPattern[10] = {0x0000000,0x0100401,0x0208822,0x0511445,0x0A2A8AA,0x1555555,0x0AA2A4A,0x1445114,0x0882208,0x1004010};

unsigned long matrixState = 0;

int characterPointer = 24;
int characterOffset = 4;
int whichCharacter = 0;
    
    
void setup()   {                
  Serial.begin(9600); 
  blankLEDs();
}
  
void loop()                     
{  
// 24 23 22 21 20
// 19 18 17 16 15
// 14 13 12 11 10
// 09 08 07 06 05
// 04 03 02 01 00

// Start at far left row, moving right.
    for (int charRow = 24; charRow >= 21; charRow--) {   
      for (int charColumn = charRow; charColumn >= 0; charColumn = charColumn - 5) {  
        if bitRead(matrixState, (charColumn-1)) {  // load each bit from the right column into this column
          bitSet(matrixState, charColumn); 
        } else {
          bitClear(matrixState, charColumn);
        }
      }
      myDelay(animationWait);  // myDelay waits for whatever amount of time I say, like delay.  Except I keep updating the matrix.
    }

 // load the farthest right row from character buffer
    for (int charColumn = characterPointer; charColumn >= 0; charColumn = charColumn - 5) { 
      if bitRead(characters[whichCharacter], (charColumn)) {
          bitSet(matrixState, (charColumn-characterOffset)); 
        } else {
          bitClear(matrixState, (charColumn-characterOffset));
        }  
    }

    
  characterPointer--;  // within the characters[] buffer, which row am I loading?
  characterOffset--;  // which column is getting loaded in matrixState
  if (characterPointer <= 19) {  // reached the end of the character, time to advance to the next element in character[]
    characterPointer = 24;
    characterOffset = 4;    
    whichCharacter++;
    insertKern(1);
    if (whichCharacter > 2)
      whichCharacter = 0;   
     // myDelay(1000);
  }
}

void insertKern(int kern) {   // Kludgy way of adding a space between the characters.
    for (int i = 0; i < kern; i++) {
     for (int charRow = 24; charRow >= 21; charRow--) {
      for (int charColumn = charRow; charColumn >= 0; charColumn = charColumn - 5) {
        if bitRead(matrixState, (charColumn-1)) {
          bitSet(matrixState, charColumn); 
        } else {
          bitClear(matrixState, charColumn);
        }
      }
      myDelay(animationWait);
    }
    
     for (int charColumn = 20; charColumn >= 0; charColumn = charColumn - 5) {
          bitClear(matrixState, charColumn);
     }     
  }
}

void lightMatrix() {
  int LEDCount = -1;       // which bit of matrixState are we checking
  int thisRowState = 0;    // state of each of the bits in this row 
  
  for (int sinkCount = 0; sinkCount < numOfSinks; sinkCount++) {   // the DP sinks an entire row
    digitalWrite(sinkPins[sinkCount], HIGH); // HIGH turns off the DP's output, turning on the LED row.
 
    thisRowState = 0;   // clear on each interation
    
    for (int i=0; i < numOfSources; i++) {  // fill thisRowState with which LEDs need to be on.
      LEDCount++;
      if (bitRead(matrixState, LEDCount)) {
        bitSet(thisRowState, i);
      } else {
        bitClear(thisRowState, i);  // Really not necessary, but want to keep timing consistant.
      } 
    }
    
    lightRow(thisRowState);
    delayMicroseconds(povWait);                // Constant delay to ensure higher on duty cycle 
    digitalWrite(sinkPins[sinkCount], LOW);   // All done with the row, turn everything off before moving on
    blankSources();
    
  }  // sink  for 
 
}  // end of lightMatrix

void lightRow(int j) {
  for (int source=0; source < numOfSources; source++) {
   if (bitRead(j,source)==1) {
      digitalWrite(sourcePins[source], HIGH); // HIGH sources 5V to the LED
   } else {
      digitalWrite(sourcePins[source], LOW); // Really not needed, but keep for consistant timing
   }
 }
}

void blankSources() {
  for (int i=0; i < numOfSources; i++) {
    pinMode(sourcePins[i], OUTPUT);
    digitalWrite(sourcePins[i], LOW);
  }  
}

void blankLEDs() {

  for (int i=0; i < numOfSinks; i++) {
    pinMode(sinkPins[i], OUTPUT);
    digitalWrite(sinkPins[i], LOW); // low turns on the DP's output, providing path to gnd, turning off the LED.
  }  
  blankSources();
}

unsigned long pow2(unsigned long j) {
  unsigned long result=1;
  for(int i=0; i < j; i++) {
    result = result * 2;
  }
  return result;
}

void myDelay(int waitTime) {
  long incomingMills = millis();
  long waitUntilMills = incomingMills + waitTime;
  
  while(millis() < waitUntilMills) {
    lightMatrix();
  }
 
}

I can use Analog In as GPIO, as long as they are all GPIO

No you can pick and mix and use as many or as few of the analogue pins as digital ones. Each pin can be an analogue input, a digital input or a digital output.

You just use pin 14 for A0, pin 15 for A1 and so on.