8x8 led grid

I got this 8x8 LED cheap, I thought I would play with it, but there are only 16 pins on the back??

Can I control this with arduino, if so how do I do it? Also how can I tell which ones are ground?

Can you guys offer some leads? Do I need to user a shift register?

Here is the device I'm looking at

You can either do it manually (hard) or use a chip like the MAX7219. :slight_smile:

Basically they are arranged in eight rows and eight columns.
You need to trigger them quickly and persistence of vision does the rest.
The MAX7219 does this easily.

Hi,
Cheater is right, I would suggest using the MAX7219 or MAX7221.
There is an article about how to build the hardware
http://www.arduino.cc/playground/Main/MAX72XXHardware
and a few arduino-software solutions
http://www.arduino.cc/playground/Main/LEDMatrix

Eberhard

I did it the "hard" way with a similar component (which to me was the easy way, no extra chips just the Arduino and the matrix).

http://www.arduino.cc/playground/Main/DirectDriveLEDMatrix

Andrew

Andrew you code sample is great. Is there any way you could put up an explanation of what is going on there? How you decided on the pinouts? or even just comment the code?

This is an example of multiplexing right? I just don't know it and I'm trying to get a good explanation of of it.... and I really don't understand how POV works with this.

Your you tube video shows what appears to be random led cycling, I want to get something non-random going here so I really need to understand, ince I do I 'll get a bunch working with chips... but now I need basics.

I'm trying to understand here, how do I light up the led at x,y...

Here's a perhaps more useful example: Scrolling lights - YouTube with code here: http://arduino.pastebin.com/f35fdf323

The gist of it is that the FrequencyTimer2 library lets you setup a routine ("display" in my case) to be called on a regular basis via interrupts. In that routine it deals with each column in turn, looking at the state of the "leds" array for that particular column and lighting up each LED as appropriate. Because this is done 500 times a second your eyes don't see just one column lit up but the whole matrix. My main loop just worries about setting each element of the "leds" matrix to 1 or 0 (using a few helper routines like slidePattern) which is how you set an LED at (x, y). The interrupt routine takes care of refreshing the display.

Hope this helps.

[Update] I've just added this sample code (for scrolling messages) to the wiki page at Arduino Playground - DirectDriveLEDMatrix. Be sure to check the diagram of the matrix wiring on that page to see if yours is wired the same way - the pinout information should be in your component's datasheet.

[Update 2] I've just checked the diagram on the page you gave for your LED matrix and I think you're in luck - it looks like it has exactly the same pin connections as mine. So you should in theory be able to wire it up the same and get it to work with my code without changing anything. Please bear in mind the warning I put on the wiki page - I think I should have used 8 current limiting resistors to make sure I don't burn out the matrix LEDs, but I'm too lazy...

Andrew

awesome andrew thank you

Great job on this 8x8 matrix.

I'm just wondering if it would be possible to use the PWM pins on either the anodes or cathodes to control the brightness of the LED's?

The way I've done it (direct drive of the matrix from the Arduino) you'd need 8 pins capable of PWM which I don't think we've got.

Andrew

Where is a good place to buy a MAX72XX? The usual sources like sparkfun don't seem to have it and Digikey is prohibitively expensive at $15 each unless I buy 5000 of them.

I have them at http://www.phanderson.com/ordering_1.html for $7.00 US.

Peter Anderson

Andrew I hope you are still checking this thread, because I have some questions about your code.

I have it all working, but I want to understand multiplexing so I'm using this as an example.

First you set everything to OUTPUT, and LOW, but then clearLeds(); which sets them all to 0... is clearLeds() redundant here?

pattern = ++pattern % numPatterns; // ok whats going on here, I think I understand the pattern setup, pins, etc, but whats this bitwise math doing to the pattern??

it looks to me like the interrupt is 2000 microseconds, then slidePattern has a delay(of 60) and display has a delayMicroseconds of 900, and you elaborate on whats going on here... and how you determined the proper delays/interrupts?

ok I've been monkeying with the code, I've added to the scrolling text, and I tried moving the "delay(del)" from the slidePattern function.

I thought it was responsible for the scroll speed, and when I change the arg, it appears so, but when I remove the delay(del), and put one in the main loop, I get crazyness... it runs very fast... not what I expected.

Do the interrupts only interrupt the main loop?...

kudos on the code, I still don't fully understand it, but they way you mapped pins, to rows, and cols is great it makes the rest very compact, it makes the defines for letters very easy, and the looping easy to understand....

First you set everything to OUTPUT, and LOW, but then clearLeds(); which
sets them all to 0... is clearLeds() redundant here?

Writing out the LOWs sets all the actual physical LEDs off electrically, but you want to make sure that the led array contains all zeros to match - that's what clearLeds() does. I think the byte array might start out containing zeros anyway but I'm a bit paranoid about memory allocation and usage in C - it's very easy to use uninitialized memory and cause a crash or weird behaviour.

pattern = ++pattern % numPatterns; // ok whats going on here, I think I
understand the pattern setup, pins, etc, but whats this bitwise math doing
to the pattern??

That was me being a smartarse with some terse C syntax - there's no bitwise arithmetic. You could write it out more clearly (roughly) as this:

temp = pattern + 1;
if (temp == numPatterns) {
temp = 0;
}
pattern = temp;

so first of all increase the contents of the pattern variable by one (that's the pre-increment ++ operator) and if that makes it equal to numPatterns wrap it around to zero (% is the modulo operator in C).

it looks to me like the interrupt is 2000 microseconds, then slidePattern has
a delay(of 60) and display has a delayMicroseconds of 900, and you elaborate
on whats going on here... and how you determined the proper
delays/interrupts?

I think 2000 microseconds was the interrupt period used in the sample code for FrequencyTimer2 and it seemed to work out alright for me. That's equivalent to 500 times a second, but as each display() call only shows one column out of eight on the matrix the whole display gets refreshed 500/8 times a second or 62.5 times a second. That's plenty fast enough for a stable looking display (unless you try filming it with a digital camera...)

The slidePattern() function is responsible for putting a whole new character on the display before returning to the main loop. In its loop it adds one new column of the character at a time to the right side of the matrix and pushes all the existing columns to the left, and the delay is how long to wait in between each loop. I just used 60 'cause it seemed to give a nice speed for the characters sliding onto the display.

Looking at it now I'm wondering if the delayMicroseconds(900) at the end of display() is actually doing anything. When I wrote it I had in mind pulse width modulation of the LEDs and making the on times much longer than the off times makes them appear brighter. However my current code leaves each column on until just before displaying the next column so they're on nearly 100% of the time and no delay is needed. You might like to try taking that out of display() and seeing if it makes any difference.

Andrew

ok I've been monkeying with the code, I've added to the scrolling text, and I
tried moving the "delay(del)" from the slidePattern function.

I thought it was responsible for the scroll speed, and when I change the arg,
it appears so, but when I remove the delay(del), and put one in the main
loop, I get crazyness... it runs very fast... not what I expected.

Dealt with above I hope.

Do the interrupts only interrupt the main loop?...

No they interrupt slidePattern as well. The main loop and slidePattern just manipulate the contents of the leds array variable; the interrupt routine (display) takes whatever's in the leds array when it fires and puts it out on the actual LEDs.

I suppose the interrupt could fire while slidePattern is halfway through changing a column in the array and you'd get a weird pattern on the matrix, but it's there so briefly you'd never notice it. To do it "properly" you might want to disable the interrupt routine before updating the array but then that would stop the matrix being refreshed in the meantime and you might get flicker. Perhaps you could use a double buffer - one array that's currently being shown and another you update, then you swap them over. Since it works visually at the moment though I'm certainly not going to bother.

kudos on the code, I still don't fully understand it, but they way you mapped
pins, to rows, and cols is great it makes the rest very compact, it makes the
defines for letters very easy, and the looping easy to understand....

Thanks! The way the letters are stored is actually very inefficient memory-wise. You'll find you can't add more than a few more letters to the message without running out of memory. What needs to be done is store each row of a letter as a byte so a definition would look something like this:

define L { \

B10000000,
B10000000,
B10000000,
B10000000,
B10000000,
B10000000,
B10000000,
B11111111
}
...
byte patterns[numPatterns][8] = {
H,E,L,L,O,SPACE
};

Then you've got 8 times the pattern space, but it makes the display() function more complicated (now you'll need bitwise operators). I'll leave that as an exercise for the reader...

Andrew

PS You've got the movie "Sweeney Todd" to thank for me being up and typing this. Just got back from the cinema and was too wired to go to bed. It's an excellent film! Stephen Sondheim musical crossed with a Tim Burton razor slasher flick - how could it fail?

awesome andrew thanks again.

I was thinking the same thing about using bytes for the arrays, but you are right... about it complicating things later.... still I like the way you wrote, it is self documenting, except for the slow ones like myself.

I think I understand now, I'll keep monkeying with it, and hopefully get it working with 2 shift registers....

Funny you mention Sweeney Todd, my wife was watching it on TV the other day, and remarked how weird it was that a remake was out already....

Hey Andrew,

I've had a lot of fun playing with your code. I had a led matrix with common anodes on rows, so it took me some finagling to get the code to work with it. The only thing I haven't been able to figure out is how to make the message scroll the opposite direction (it is scrolling left to right for me). Can you explain the slidePattern function a bit to give me a clue?

I'm not sure I agree with the comment about the letter storage being inefficient. By defining them as constants, they stored in program memory, not variable memory, right? I've got a bit more of that to spare.

Many thanks.

Hey Andrew,

I've had a lot of fun playing with your code. I had a led matrix with common anodes on rows, so it took me some finagling to get the code to work with it. The only thing I haven't been able to figure out is how to make the message scroll the opposite direction (it is scrolling left to right for me). Can you explain the slidePattern function a bit to give me a clue?

As I said in a previous post:

"The slidePattern() function is responsible for putting a whole new character on the display before returning to the main loop. In its loop it adds one new column of the character at a time to the right side of the matrix and pushes all the existing columns to the left, and the delay is how long to wait in between each loop. I just used 60 'cause it seemed to give a nice speed for the characters sliding onto the display."

If the scrolling is going in the wrong direction for you, try changing the code to this:

void slidePattern(int pattern, int del) {
  // Loop 8 times, once for each column of new character to scroll in
  for (int loop = 0; loop < 8; loop++) {
    // First shuffle existing columns 0 to 6 into cols 1 to 7
    for (int i = 0; i < 7; i++) {
      // Do each row of each column
      for (int j = 0; j < 8; j++) {
        leds[j][i + 1] = leds[j][i];
      }
    }
    // Now copy new column from pattern onto end column of display
    for (int j = 0; j < 8; j++) {
      leds[j][0] = patterns[pattern][j][7 - loop];
    }
    // Wait for a bit
    delay(del);
  } // end loop for each column of new pattern
} // end function

and if that makes your letters come out backwards try changing

      leds[j][0] = patterns[pattern][j][7 - loop];

to

      leds[j][0] = patterns[pattern][j][loop];

I'm not sure I agree with the comment about the letter storage being inefficient. By defining them as constants, they stored in program memory, not variable memory, right? I've got a bit more of that to spare.

Many thanks.

They're not actually constants - my memory (no pun intended!) about C memory allocation is a bit hazy but I think arrays declared like this have memory dynamically allocated at runtime on the heap, so it comes out of our measly 1k of RAM. Someone who knows more about it should feel free to chip in at this point...

Andrew

PS I hope I've got the code right - it's untested and I'm tired...

Thanks for the help.

Here is how I got it to work: I changed:
leds[j][i + 1] = leds[j][i]; to
leds[j][i] = leds[j][i + 1];
and changed

leds[j][0] = patterns[pattern][j][7 - loop];to

leds[j][7] = patterns[pattern][j][loop];

I'm still not sure why it works, but it does. Thanks for annotating the code!

On the memory issue, defining the letters isn't costing us, it is the three-dimensional patterns array which eats up 64 bytes per letter displayed. "HELLO" would be the same memory usage as "LLLLL". I figure I'd max out at about ten letters.

Still pretty dang cool. Maybe someone will tackle it bit-wise.