Introduction: 90x60cm Discrete Led Scrolling Text Matrix

About: http://itdomain.org

This is my first instructable and I wasn't planning on doing it when I first started this project, so bear with me and any kind of flaws it may have. I first decided to do this project when I discovered how easy and cheap it is to display some scrolling text these days with just an arduino board and some led matrix. However, i felt that these cheap matrix ( like this one) are somewhat small. I wanted something big that could light all of my city. I then decided to get real and do it in a 90X60cm cork Bulletin Board.

Step 1: ​Things You Will Need

  • 1x - Cork Bulletin Board (or any other material like a sheet of plywood or something)
  • 1x - Arduino Board
  • 128x - 5mm Leds (you can do it with more or less and also other sizes)
  • 2x - Resistors (I used 25KΩ aprox.)
  • 2x - IC Max 7219 (one for each 8x8 matrix)
  • Solder
  • Soldering Iron
  • Perfboard
  • 2x - 24 pin Dil socket (optional)
  • Arduino Breakaway Pin headers (optional)
  • WireCutting and long nose Pliers
  • Ruler or measuring Tape
  • Pencil
  • Patience
  • Something i Forgot

Step 2: Measuring and Sticking

Because i wasn't planning on doing an instructable i only have a picture of the matrix already half done, but this isn't rocket science (although i managed to choose a very poor method of doing it which almost made give up).

I did some math and calculeted the distance between leds so that they would be evenly spaced ( 256 at first, but in the middle of the process i got tired and made it with only 128, ie. 2 8x8 matrixs). Do your math but don't forget that you must divide by 2 the value that you get to eg(256 cm/128=2cm - if you start sticking the first led at the 2 cm mark, then your last led will be right on the edge of the board, so you must start at 1cm in, ending up with a 1cm margin on both sides. Note this is just an example not my real values).

I didn't wanted to leave marks on the front of the board so i made all my measurement marks on the back...Clever ehh??! Well this made the led sticking process a real pain. I would stick a pin, that came with the board, from the back of the board, see where it came out on the from and then stick the led. To see the tip of the pin i had to keep moving the pin until i could spot the tiny part of the tip the was visible. Real dumb,boring and time consuming. Today i would have done it completely different. I think a nice way to do it would be to stick 16 pins in each horizontal side of the board and 8 across each vertical side and then connect them with wire (fishing, nylon wool, whatever...) and then just stick a led in the vertical and horizontal crossing points. This way one would not need to keep the board in a vertical position in order to be able to look to the front and back of it while moving the pin and sticking the led (what a nightmare).

Make sure you always stick the led with the anodes and cathodes facing same side, this will make it easier for the soldering process.

Step 3: Soldering Leds

Check that all leds have the same orientation and that the legs of each led were not bent during sticking process and are not touching each other. Now, just bend for instance all the anodes down and all the cathodes to the right and solder all anodes on the same row and all cathodes on the same column as you can see in the image. The image was taken from the best electronics tutorial website tronixstuff.com (link) (no relation whatsoever with them) which has the most complete tutorial on the max7219 IC i've ever seen and also the arduino code i used (would take a really long time to write such code, so... many tanks for sharing!!!).

I used some bare/naked copper wire to make the rows and columns so i had to place some tape to prevent contact where they crossed. Shrinking tube would have been better but i didn't have any.

Step 4: Connections

Connect the rows and columns to the Max7219 IC as showed in the image.

I made a board holding the 2 max2719 ICs, the resistors and capacitors but i don't have any pcb files. The circuit is very simple, just put the 2 ICs close to each other side by side, so that its easier to send the DataOut pin(pin 24) of the 1st IC to the DataIn of the second one(pin 1) leaving enough space between them to put he capacitors though. I used two 24pin dil socket to hold the max7219 ICs because if one of them happens to frie i can just replace it, i don't need to desolder it and solder back a new one in the same place (would be messy) but it is not required. I looked at the table in the max7219 data sheet to find a reference value for the resistors, i didn't have any resistors near those values so i used two 50 and somethingKΩ in parallel to get a value of about 25KΩ which luckily worked fine (until now :] ).

Make sure to respect the electrolityc capacitors polarity and put them as near to the power supply as you can. Also keep the wires as short possible so they don't behave like antennas.

Solder the breakaway headers in each side of the ICs, making sure they are well seated. The only problem i had in this project was related to this. When soldering them, some solder slipped through the hole to the other side of the pcb because there was some free space in-between the pcb surface and the header due to the header not being well seated. I didn't notice this when i was soldering and it shunted 3 pins. After finishing i still couldn't see nothing wrong because the shunting solder was under the plastic part of the header, it was not visible. When i first tested the project with text something looked wrong, i then slowed the text scrolling trying to get what it was. There was one column that would never lite. I first thought it could be some cold joint but it wasn't . I then loaded the debug code from tronixstuff.com that lights led by led, column by column and i could see that 3 columns would light at the same time. I used my multimeter in continuity mode and could see that 3 pins were shunted, i looked everywhere for the shunt and was a pain to find it because i couldn't see anything connecting those 3 pins.

Finally connect the arduino to the Max7219 Datain, Clock and Load pins. I also used the 5V Pin from arduino to power The 7219 IC. Keep in mind that your power supply must be able to provide enough current to the arduino and 7219 IC (in worst case scenario 8 leds will be on at the same time because no more than one row is shown at each time, they are just shown one after the other at an high frequency (around 800 times in 1 second i think).

Step 5: Programm

I got this code from the tronixstuff.com site and you can get other code examples like the debug code available there, that was very useful to understand what was going on when things weren't working as supposed due to the 3 shorted columns i mentioned above.

// based on an orginal sketch by Arduino forum member "danigom"
// http://forum.arduino.cc/index.php?action=profile;...

#include #include

const int numDevices = 2; // number of MAX7219s used const long scrollDelay = 75; // adjust scrolling speed

unsigned long bufferLong [14] = {0};

LedControl lc=LedControl(12,11,10,numDevices);

prog_uchar scrollText[] PROGMEM ={ " THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG 1234567890 the quick brown fox jumped over the lazy dog \0"};

void setup(){ for (int x=0; x

void loop(){ scrollMessage(scrollText); scrollFont(); }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

prog_uchar font5x7 [] PROGMEM = { //Numeric Font Matrix (Arranged as 7x font data + 1x kerning data) B00000000, //Space (Char 0x20) B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, 6,

B10000000, //! B10000000, B10000000, B10000000, B00000000, B00000000, B10000000, 2,

B10100000, //" B10100000, B10100000, B00000000, B00000000, B00000000, B00000000, 4,

B01010000, //# B01010000, B11111000, B01010000, B11111000, B01010000, B01010000, 6,

B00100000, //$ B01111000, B10100000, B01110000, B00101000, B11110000, B00100000, 6,

B11000000, //% B11001000, B00010000, B00100000, B01000000, B10011000, B00011000, 6,

B01100000, //& B10010000, B10100000, B01000000, B10101000, B10010000, B01101000, 6,

B11000000, //' B01000000, B10000000, B00000000, B00000000, B00000000, B00000000, 3,

B00100000, //( B01000000, B10000000, B10000000, B10000000, B01000000, B00100000, 4,

B10000000, //) B01000000, B00100000, B00100000, B00100000, B01000000, B10000000, 4,

B00000000, //* B00100000, B10101000, B01110000, B10101000, B00100000, B00000000, 6,

B00000000, //+ B00100000, B00100000, B11111000, B00100000, B00100000, B00000000, 6,

B00000000, //, B00000000, B00000000, B00000000, B11000000, B01000000, B10000000, 3,

B00000000, //- B00000000, B11111000, B00000000, B00000000, B00000000, B00000000, 6,

B00000000, //. B00000000, B00000000, B00000000, B00000000, B11000000, B11000000, 3,

B00000000, /// B00001000, B00010000, B00100000, B01000000, B10000000, B00000000, 6,

B01110000, //0 B10001000, B10011000, B10101000, B11001000, B10001000, B01110000, 6,

B01000000, //1 B11000000, B01000000, B01000000, B01000000, B01000000, B11100000, 4,

B01110000, //2 B10001000, B00001000, B00010000, B00100000, B01000000, B11111000, 6,

B11111000, //3 B00010000, B00100000, B00010000, B00001000, B10001000, B01110000, 6,

B00010000, //4 B00110000, B01010000, B10010000, B11111000, B00010000, B00010000, 6,

B11111000, //5 B10000000, B11110000, B00001000, B00001000, B10001000, B01110000, 6,

B00110000, //6 B01000000, B10000000, B11110000, B10001000, B10001000, B01110000, 6,

B11111000, //7 B10001000, B00001000, B00010000, B00100000, B00100000, B00100000, 6,

B01110000, //8 B10001000, B10001000, B01110000, B10001000, B10001000, B01110000, 6,

B01110000, //9 B10001000, B10001000, B01111000, B00001000, B00010000, B01100000, 6,

B00000000, //: B11000000, B11000000, B00000000, B11000000, B11000000, B00000000, 3,

B00000000, //; B11000000, B11000000, B00000000, B11000000, B01000000, B10000000, 3,

B00010000, //< B00100000, B01000000, B10000000, B01000000, B00100000, B00010000, 5,

B00000000, //= B00000000, B11111000, B00000000, B11111000, B00000000, B00000000, 6,

B10000000, //> B01000000, B00100000, B00010000, B00100000, B01000000, B10000000, 5,

B01110000, //? B10001000, B00001000, B00010000, B00100000, B00000000, B00100000, 6,

B01110000, //@ B10001000, B00001000, B01101000, B10101000, B10101000, B01110000, 6,

B01110000, //A B10001000, B10001000, B10001000, B11111000, B10001000, B10001000, 6,

B11110000, //B B10001000, B10001000, B11110000, B10001000, B10001000, B11110000, 6,

B01110000, //C B10001000, B10000000, B10000000, B10000000, B10001000, B01110000, 6,

B11100000, //D B10010000, B10001000, B10001000, B10001000, B10010000, B11100000, 6,

B11111000, //E B10000000, B10000000, B11110000, B10000000, B10000000, B11111000, 6,

B11111000, //F B10000000, B10000000, B11110000, B10000000, B10000000, B10000000, 6,

B01110000, //G B10001000, B10000000, B10111000, B10001000, B10001000, B01111000, 6,

B10001000, //H B10001000, B10001000, B11111000, B10001000, B10001000, B10001000, 6,

B11100000, //I B01000000, B01000000, B01000000, B01000000, B01000000, B11100000, 4,

B00111000, //J B00010000, B00010000, B00010000, B00010000, B10010000, B01100000, 6,

B10001000, //K B10010000, B10100000, B11000000, B10100000, B10010000, B10001000, 6,

B10000000, //L B10000000, B10000000, B10000000, B10000000, B10000000, B11111000, 6,

B10001000, //M B11011000, B10101000, B10101000, B10001000, B10001000, B10001000, 6,

B10001000, //N B10001000, B11001000, B10101000, B10011000, B10001000, B10001000, 6,

B01110000, //O B10001000, B10001000, B10001000, B10001000, B10001000, B01110000, 6,

B11110000, //P B10001000, B10001000, B11110000, B10000000, B10000000, B10000000, 6,

B01110000, //Q B10001000, B10001000, B10001000, B10101000, B10010000, B01101000, 6,

B11110000, //R B10001000, B10001000, B11110000, B10100000, B10010000, B10001000, 6,

B01111000, //S B10000000, B10000000, B01110000, B00001000, B00001000, B11110000, 6,

B11111000, //T B00100000, B00100000, B00100000, B00100000, B00100000, B00100000, 6,

B10001000, //U B10001000, B10001000, B10001000, B10001000, B10001000, B01110000, 6,

B10001000,//V B10001000, B10001000, B10001000, B10001000, B01010000, B00100000, 6,

B10001000,//W B10001000, B10001000, B10101000, B10101000, B10101000, B01010000, 6,

B10001000,//X B10001000, B01010000, B00100000, B01010000, B10001000, B10001000, 6,

B10001000,//Y B10001000, B10001000, B01010000, B00100000, B00100000, B00100000, 6,

B11111000,//Z B00001000, B00010000, B00100000, B01000000, B10000000, B11111000, 6,

B11100000,//[ B10000000, B10000000, B10000000, B10000000, B10000000, B11100000, 4,

B00000000,//(Backward Slash) B10000000, B01000000, B00100000, B00010000, B00001000, B00000000, 6,

B11100000,//] B00100000, B00100000, B00100000, B00100000, B00100000, B11100000, 4,

B00100000,//^ B01010000, B10001000, B00000000, B00000000, B00000000, B00000000, 6,

B00000000,//_ B00000000, B00000000, B00000000, B00000000, B00000000, B11111000, 6,

B10000000,//` B01000000, B00100000, B00000000, B00000000, B00000000, B00000000, 4,

B00000000,//a B00000000, B01110000, B00001000, B01111000, B10001000, B01111000, 6,

B10000000,//b B10000000, B10110000, B11001000, B10001000, B10001000, B11110000, 6,

B00000000,//c B00000000, B01110000, B10001000, B10000000, B10001000, B01110000, 6,

B00001000,//d B00001000, B01101000, B10011000, B10001000, B10001000, B01111000, 6,

B00000000,//e B00000000, B01110000, B10001000, B11111000, B10000000, B01110000, 6,

B00110000,//f B01001000, B01000000, B11100000, B01000000, B01000000, B01000000, 6,

B00000000,//g B01111000, B10001000, B10001000, B01111000, B00001000, B01110000, 6,

B10000000,//h B10000000, B10110000, B11001000, B10001000, B10001000, B10001000, 6,

B01000000,//i B00000000, B11000000, B01000000, B01000000, B01000000, B11100000, 4,

B00010000,//j B00000000, B00110000, B00010000, B00010000, B10010000, B01100000, 5,

B10000000,//k B10000000, B10010000, B10100000, B11000000, B10100000, B10010000, 5,

B11000000,//l B01000000, B01000000, B01000000, B01000000, B01000000, B11100000, 4,

B00000000,//m B00000000, B11010000, B10101000, B10101000, B10001000, B10001000, 6,

B00000000,//n B00000000, B10110000, B11001000, B10001000, B10001000, B10001000, 6,

B00000000,//o B00000000, B01110000, B10001000, B10001000, B10001000, B01110000, 6,

B00000000,//p B00000000, B11110000, B10001000, B11110000, B10000000, B10000000, 6,

B00000000,//q B00000000, B01101000, B10011000, B01111000, B00001000, B00001000, 6,

B00000000,//r B00000000, B10110000, B11001000, B10000000, B10000000, B10000000, 6,

B00000000,//s B00000000, B01110000, B10000000, B01110000, B00001000, B11110000, 6,

B01000000,//t B01000000, B11100000, B01000000, B01000000, B01001000, B00110000, 6,

B00000000,//u B00000000, B10001000, B10001000, B10001000, B10011000, B01101000, 6,

B00000000,//v B00000000, B10001000, B10001000, B10001000, B01010000, B00100000, 6,

B00000000,//w B00000000, B10001000, B10101000, B10101000, B10101000, B01010000, 6,

B00000000,//x B00000000, B10001000, B01010000, B00100000, B01010000, B10001000, 6,

B00000000,//y B00000000, B10001000, B10001000, B01111000, B00001000, B01110000, 6,

B00000000,//z B00000000, B11111000, B00010000, B00100000, B01000000, B11111000, 6,

B00100000,//{ B01000000, B01000000, B10000000, B01000000, B01000000, B00100000, 4,

B10000000,//| B10000000, B10000000, B10000000, B10000000, B10000000, B10000000, 2,

B10000000,//} B01000000, B01000000, B00100000, B01000000, B01000000, B10000000, 4,

B00000000,//~ B00000000, B00000000, B01101000, B10010000, B00000000, B00000000, 6,

B01100000,// (Char 0x7F) B10010000, B10010000, B01100000, B00000000, B00000000, B00000000, 5 };

void scrollFont() { for (int counter=0x20;counter<0x80;counter++){ loadBufferLong(counter); delay(500); } }

// Scroll Message void scrollMessage(prog_uchar * messageString) { int counter = 0; int myChar=0; do { // read back a char myChar = pgm_read_byte_near(messageString + counter); if (myChar != 0){ loadBufferLong(myChar); } counter++; } while (myChar != 0); } // Load character into scroll buffer void loadBufferLong(int ascii){ if (ascii >= 0x20 && ascii <=0x7f){ for (int a=0;a<7;a++){ // Loop 7 times for a 5x7 font unsigned long c = pgm_read_byte_near(font5x7 + ((ascii - 0x20) * 8) + a); // Index into character table to get row data unsigned long x = bufferLong [a*2]; // Load current scroll buffer x = x | c; // OR the new character onto end of current bufferLong [a*2] = x; // Store in buffer } byte count = pgm_read_byte_near(font5x7 +((ascii - 0x20) * 8) + 7); // Index into character table for kerning data for (byte x=0; x>24); // Mask off second character lc.setRow(2,a,y); // Send row to relevent MAX7219 chip y = (x>>16); // Mask off third character lc.setRow(1,a,y); // Send row to relevent MAX7219 chip y = (x>>8); // Mask off forth character lc.setRow(0,a,y); // Send row to relevent MAX7219 chip } }

Step 6: Some Thoughts

I realize that some things could be improved in order to take this project to another level:

1- Because it has only 128 leds, the resolution is low

It would benefit from having more leds in the same area.

Defusing led light like seen on other DIY projects with ping pong balls or other translucent material could also improve the end result. I tried this myself but these were some cheap leds i had laying around for years for another project and the leds were not suitable for this solution, the light comes out in a very low angle (30º?), leaving a strong spot of light in the ping pong ball center but the rest of the ball does not get that much of a light. Some may find it cool, but i didn't like it too much. If you sand the led the light will diffuse but if you are aiming for this kind of result, save your self some time and just buy some leds with a suitable viewing angle.

2- It could be wider

It would look a lot cooler if it was wider but that would require one to use more max7219 ICs and one must keep in mind that there are implications regarding performance when more of them are used and problems may arise (or not have not tested myself but read the Datasheet).

3- The Breakaway pin Headers were a VERY BAD idea!

Well, this seemed a great idea at first but it just makes the connecting wires go up and above the IC which makes a lot of volume in the back (I don't know if i can make myself clear). I think better and cleaner results would have been achieved if i had just soldered the wire directly to the board.

4- Last line is not used

The font in the used code is 7x8 and for that, the last line is not used.

5- Some other uses for it

I'm thinking about making it display time or code some python or java application that could send info to the arduino serial port, triggered by some event (maybe new mail or something...don't know if theres an api for that). More on that in the near(or not so near) future.

And thats it. Go build It and Have some Fun. Also, keep me posted if you happen do something like this or have some useful information or correction you would like to share.