Go Down

Topic: 32x32 led ghetto matrix :) (Read 6321 times) previous topic - next topic


I am working on a led matrix project, and I have had no luck finding code that works for the setup that you have (595's without specialized led driver chips). I am trying to get this project done in 2 days for an event coming up, and I would appreciate it if you posted the code you used or sent it to me directly. I found sample code from Earthshine Design's tutorials, but it does not seem to work and I have quadruple checked the wiring!!!

Please post the code! Thanks.  ;D

BTW I already have 20 8x8 matrices and quite a few 595's, but I just dont have the money for 20 Max 7219's!


how many led's, this screen is big enough where I had to do some voodoo to get it to refresh quick enough, where as a 8x8 or a 16x16 you can just use shift out

I will post in a bit, I have to go to the other room and fire that pc up, but its really just slapped together and I doubt it would do much except confuse you (which is fine cause then we can move onto theory lol)


Mar 30, 2010, 06:01 am Last Edit: Mar 30, 2010, 06:04 am by Osgeld Reason: 1
I mashed it all into 1 file and added some comments

Code: [Select]
// 2k10 OSGELD

// i am scanning by row (instead of normal pixel by pixel), which overloads the 595's
// there are 2 595 per row / col piggy backed on eachother in a kludge to bring
// it more in spec, your results may vary

// this array of bytes is used to keep track of where
// we are, X is the first 4 bytes these are columns
// combination of those 32 bits repersent what pixels
// are lit for every row.

// Y is the last 4 bytes in the array,
// each of the 32 bits is toggled on one at a time in order

// !be careful on your wiring!

// its still backwards on mine so i start with lsb and shift left
// instead of to the right which would have made more since
byte screenBuffer[8] =
 B00000000, B00000000,
 B00000000, B00000000,
 B00000000, B00000000,
 B00000000, B00000000};
void setup()
 // setup pins for screen (595's)
 // enable the atmega 328s hardware spi port
 screenInit(); // delay 10

void loop()
 // update the screen as fast as it can
// enable the atmega 328s hardware spi port
// this can be found on the fourm
void screenInit()
 DDRB = DDRB | B00001101;
 // screen must be on pins
 // 10 latch
 // 11 data
 // 13 clock
 // setup hardware spi
 byte clr;
 SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
 SPCR &= ~( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
 clr = SPSR; // clear SPI status reg
 clr = SPDR; // clear SPI data reg
 SPSR |= (1<<SPI2X); // set prescaler bits

// what you use to send data to the screen
void screenFlip()
 screenOn(false); // turn off latch
 screenOn(true); // tun on latch, showing screen

void screenOn(boolean ON) // toggle the latch
 if(ON) bitSet(PORTB, 2); // HIGH
 else bitClear(PORTB, 2); // LOW

// hardware send data to screen
// stripped down version of what you would
// find on the hardware spi fourm topics
void screenOut(byte data)
 SPDR = data;                    
 while (!(SPSR & (1<<SPIF))){}  
// bitmap data, original file pbm image format saved in ascii
// as text 1's and 0's from the gimp, arduino formatted with
// a little hand magic in notepad ++
byte mac[32][4]  =
 {B00000000, B00000000, B00000000, B00000000},
 {B00111111, B11111111, B11111111, B10000000},
 {B01100000, B00000000, B00000000, B11000000},
 {B01000000, B00000000, B00000000, B01000000},
 {B01000111, B11111111, B11111100, B01000000},
 {B01001000, B00000000, B00000010, B01000000},
 {B01001000, B00000000, B00000010, B01000100},
 {B01001000, B00000000, B00000010, B01000010},
 {B01001000, B01000100, B01000010, B01001000},
 {B01001000, B01000100, B01000010, B01001010},
 {B01001000, B00000100, B00000010, B01010010},
 {B01001000, B00000100, B00000010, B01001001},
 {B01001000, B00001100, B00000010, B01010110},
 {B01001000, B00000000, B00000010, B01001010},
 {B01001000, B00100001, B00000010, B01010101},
 {B01001000, B00011110, B00000010, B01011011},
 {B01001000, B00000000, B00000010, B01001101},
 {B01001000, B00000000, B00000010, B01010110},
 {B01000111, B11111111, B11111100, B01011011},
 {B01000000, B00000000, B00000000, B01011101},
 {B01000000, B00000000, B00000000, B01010111},
 {B01000000, B00000000, B00000000, B01011011},
 {B01000000, B00000000, B00000000, B01011101},
 {B01000110, B00000000, B01111110, B01011111},
 {B01000000, B00000000, B00000000, B01010111},
 {B01000000, B00000000, B00000000, B01011101},
 {B01000000, B00000000, B00000000, B01011111},
 {B01111111, B11111111, B11111111, B11011111},
 {B00100000, B00000000, B00000000, B10011011},
 {B00100000, B00000000, B00000000, B10011111},
 {B00111111, B11111111, B11111111, B10011111},
 {B00000000, B00000000, B00000000, B00011111}};

void bitmapUpdate()
 int x; // col counter
 int y; // row counter
 for(y = 0; y < 32; y++) // for 32 rows do...
 { // 32 rows + each row is comprised of 4 bytes of X on off data so...
   for(x = 0; x < 4; x++)
     screenBuffer[x] = mac[y][x];
     // read the current row X data into into the screen buffers 0-3

   // after the X data for the row is in the buffer
   // we need to format the row position data for the 595's,
   // only 1 line at a time means we have to shuffle a
   // single bit though 32 bits(over the last 4 bytes of the buffer array)
   switch(y / 8)
     case 0: // ie 3 / 8 = integer 0
       if(screenBuffer[4] == 0) // see if the first 8 rows is turned off
       { // if so
         screenBuffer[7] = B00000000; // turn off the last 8 rows
         screenBuffer[4] = B00000001; // set the first bit to one, mines backwards
       else // if not
         screenBuffer[4] = screenBuffer[4] << 1; // shift the bit one space, or to the next row
     // repeat 7 more times
     case 1:
       if(screenBuffer[5] == 0)
         screenBuffer[4] = B00000000;
         screenBuffer[5] = B00000001;
         screenBuffer[5] = screenBuffer[5] << 1;
     case 2:
       if(screenBuffer[6] == 0)
         screenBuffer[5] = B00000000;
         screenBuffer[6] = B00000001;
         screenBuffer[6] = screenBuffer[6] << 1;
     case 3:
       if(screenBuffer[7] == 0)
         screenBuffer[6] = B00000000;
         screenBuffer[7] = B00000001;
         screenBuffer[7] = screenBuffer[7] << 1;
   } // end switch  
   screenFlip(); // show screen
 } // end y for loop  
} // end function

// wait for next call


Thanks so much! I'm trying to make a Daft Punk helmet replica (the gold one) and I am planning on having 5 8x8s tall by 4 8x8s wide for a total of 20 8x8xs with 40 pixels tall by 32 wide. I'm gonna go look through that code (Im horrible at code but decent with circuits) and figure out how to manipulate to the size I need. Im thinking Im gonna have to a a transistor for each row, but we'll see.  ;D I know this is really complicated for a first foray into Arduino, but I bought all the parts so Im kinda committed....  :P


Actually, I think im gonna shrink it to the same size as yours so I dont have to modify anything!!!!! (4 8x8s by 4 8x8s)


my rows are wired backwards, its commented in the code

and yes using a transistor on each end would be advisable if you want decent brightness, but also resistors for each anode

mine has neither, and its dimmer than i would like, + i had to kludge the shift registers by piggy backing them + its totally uneven! (which you can make out in the images)

or in other words ghetto, but the code is pretty solid, tho I have not tried animations yet, that just displays a static image (in ram, so your going to have to figure storage out)



Yeah, I have some resistors that I was planning to use for the positive terminals (lotsa wiring!) but I think I will add the transistors in a second build for times sake (trying to finish for school on thursday). Just bought PCB to solder the 595's/ resistors, and Im sticking the matrices together with some super heavy duty double sided adhesive strips (They work awesome!).

One question: When you say the rows are wired backwards, that means the 1st SR receiving data is the last set of rows, then SR2 the second set of rows, SR3 = 3rd row, SR4 = 4th row, then SR5 is the last set of couloms, SR6 = 3rd coloum, SR7 = 2nd coloum, and the end of the SR daisy chain is the 1st set of coloums? I think that is what you mean, but I'm not 1005 sure.....

Thanks soooo much for your help!!!! ;D


Mar 30, 2010, 11:28 pm Last Edit: Mar 30, 2010, 11:32 pm by Osgeld Reason: 1
its all messed up, look at the screen screenFlip() function to see the order of the shift registers, it should be pretty much like you would expect

BUT what happened is row 1 is turned on using 00000001 and row 8 is 10000000, that is the backwards part, row 1 should really be the MSB and shifted right, instead its the LSB shifted left

if I did it MSB shifting to the right (with the way its wired now) it would go 8,7,6,5,4,3,2,1,16,15 etc instead of 1,2,3,4,5,6,7,8,9 etc


Is this how you numbered/wired the Shift Registers to the matrices?

Hopefully so. If not, please explain your numbering system!!! Thanks! Im soldering this tommorrow afternoon, and I dont wanna mess it up! It'd be garbage to solder 150+ connections then have to resolder half of them... :o


Sorry bout bad link. Here it is. Please respond (About to solder in an hour or 2.

Thanks! ;D


Apr 01, 2010, 12:47 am Last Edit: Apr 01, 2010, 12:48 am by Osgeld Reason: 1
if you wire it like that you will need to change << to >> (in the bitmapUpdate function) and it should work fine

when you see something like

         screenBuffer[7] = B00000000;
         screenBuffer[4] = B00000001;

make it

         screenBuffer[7] = B00000000;
         screenBuffer[4] = B10000000;


Jul 09, 2010, 09:47 am Last Edit: Jul 09, 2010, 09:47 am by mrmeval Reason: 1
I used HEF4794 it can drive higher current per pin around 40ma though there are package limitations to running all outputs at max. You can pwm the output enable pin to control brightness.



Or you can use transistors or something like

Have fun.
If it was designed by man it can be repaired by man.

Go Up

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131