About Me

My photo
They never fall who never climb.

018 HOME MADE LED DOT MATRIX DISPLAY - 3x3 MATRIX



018 HOME MADE LED DOT MATRIX 3x3

March 16, 2011    (See also Companion Blog )

[Go BACK to Table of Contents] [ Next Experiment ] [ Last Experiment ]

           To build and program a 3 x 3 LED dot matrix display using only LEDs, resistors and the Arduino brainboard. This project is completely original and is not based on any kit or plans that I could find, in fact, I had to build it because I could not find any proper instructions or tutorial material.

           Be advised: this is a complicated project that took a lot of time. You should read through this description before you start to see what to expect and learn what you are in for. This project requires both complicated wiring and complicated Arduino code, at least if you ask me.

           You will need to plan out your tools and materials. I can’t do that for you, but you also will need the basics and some way to connect all the wiring. This project took me five hours to complete, around four hours for the wiring, and another hour for the programming. But keep in mind I have a degree in programming and was able to plan the code in my head.

           I apologize now and probably again later that I do not have the cash or equipment to take acceptable photos of what I’m doing. I’ve tried to record the events using what I’ve got and I am aware of the shortcomings. However, this is an experiment, not something for sale. Follow along and give it a try if you feel motivated.

           There is nothing difficult about the individual steps and components that make up such a circuit. But what is difficult is finding a source that explains everything in a simple fashion. I wasted much time watching on-line videos that didn’t show the code, or didn’t reveal the wiring schematics. Guys, you may be proud of your project, but without the technical details, your video is just some flashing lights and boring commentary.
Theory:
           Let’s get some terminology out of the way. The correct name for the apparatus is “LED Dot Matrix”. I spent considerable time on Google trying to find a beginner’s level document and got led down many a wrong path. Some people referred to the object as an array, but an array is a mathematical concept, part of the Arduino code you may eventually use. I don’t use it here.

           Other authors called it an LED flashing sign, but these were the usual gangs of commercial outfits looking to sell you the finished product. You don’t learn much buying a kit, either. It is too bad Google has no way of blocking these bait and switch operators. There are also slang terms like LED grid, but from here on, when I say the matrix, I mean the LED Dot Matrix display.

           Do not confuse an LED dot matrix display with and LCD (liquid crystal display). These are two different animals. The LCD is a manufactured component you cannot build at home, and it is controlled with a matching IC (integrated circuit), a chip that is much more advanced than what we are doing here.

           Before you begin, there are many things to know that are not covered elsewhere, so I take the liberty of bringing them together here. The smallest practical LED Dot Matrix is a 3 x 3, anything smaller won’t give you the feel for the correct wiring—and you WILL need that knowledge learned here when you scale up to larger matrices (the correct plural of matrix) later.

           Words to the wise. Be advised there is no way an ordinary breadboard with banks of 5 parallel slots can be used to produce a 3 x 3 matrix, it is physically impossible. Don’t waste your time trying like I did.

           The term dot matrix has been around, some of us are old enough to remember dot matrix printers. You should make an attempt to understand the theories behind dot matrix printing, and how the minimum number of dots needed to display all the alphanumeric characters was derived. For practical purposes, most matrix displays are 8 x 8, which allows some “space” around each displayed character. It is worthwhile to read up a few paragraphs on dot matrix before you commence building anything here.
           Here are some patterns I made around six months ago, long before I had contemplated actually building a matrix. I found limitations of what could be displayed on 3 x 5 matrix and gives you some direction about how to think concerning how to present characters in dot matrix format.

           Next, try to use red or yellow LEDs, the 5mm brand. They have the brightness required to be seen in ambient room light and you don’t want to be continually turning off the overhead to see if you are making progress. Also, these colors tend to switch on and off instantly where other colors seem to have a noticeable delay time turning off, although I have not measured or confirmed this delay.

           The Arduino will supply barely enough power to experiment with small LED matrices. Beyond that, you will have to use transistors. If you are not familiar with transistors, they serve a dual function in a matrix circuit: they act as switches and they act as amplifiers. The amplifier part allows you to connect a power supply independent of the Arduino. I recommend that you plan to use transistors as early in your matrix projects as you can.

           When you see a pattern displayed on a dot matrix, what you are really seeing is all of the LEDs flashing on and off so rapidly that your POV (persistence of vision, about 1/20th of a second) makes your eye perceive that they are all on at once. Sometimes this flashing is controlled by multiplexing, but this is not what I used here. The concept of multiplexing comes into play when you have more LEDS to control that the Arduino has outputs. This project is planned to use only six of the available pins on the Arduino.

           For clarity, only one LED is on at a time. The computer code flashes each LED in sequence. Your eye and brain perceive the character or pattern, but this is an illusion. The one-at-a-time flashing has a theoretical upper limit in that more LEDS mean more of a delay before each one gets its turn. But the Arduino can flash so many thousands of times per second it is not likely you will ever reach this limit or even notice that more LEDs are slightly dimmer than a few LEDs.

           In an LED matrix, all your positive (anode) LED pins are connected in each row, your negative (cathode) LED pins are connected by columns. Thus, to turn on an individual LED, you will need to set the corresponding positive to HIGH (5Volts) and the corresponding negative to LOW (0 Volts). To turn the LED off, remove the HIGH and LOW.            This may seem obvious, but it is not. Think for a moment about the situations where the LED would be off. It the negative lead was also set to HIGH, no current would flow. But there is potential for damage to your LED in such a configuration. Later, you will see how using transistors as switches helps in this situation.

           No matter how you approach the wiring, it is a tiresome task that demands full concentration. The connections are tiny and look alike for the most part. The real lesson you learn is that matrices are best constructed by automated means. You will probably never build a matrix beyond what you require to learn how it is done. Practice:

           My layout was wire-wrapped. I avoided soldering because I am not that good at it, while I am very experienced with wire wraps. In the event of an error, I find a wire wrap easier to undo than a solder joint. Also, I’m cheap when it comes to wiring a circuit I intend to tear apart if it works. Whichever you choose, your patience will be tried to the ultimate.
           Here’s another factoid difficult to discover from the Arduino manual—all the pins default to INPUT. You can see in the code how I specifically instruct the pins to be set to OUTPUT. If you don’t spell it out, the Arduino isn’t going to help. This is not a trivial step, and the default setting can be totally confusing to newcomers.

           I had to start somewhere, so here is my first attempt. I used yellow LEDs because I have lots of cheap ones not destined for any other usage. I have a store-bought perfboard and I will not be using any transistors on this grid. I only want to test the logic of turning on the LED targeted by my Arduino code.

           As a precaution against short circuits, I staggered the rows and columns of my LED leads on the perfboard. That is, I did not line the leads up in the same colums. I placed them diagonally. See nearby diagram. This made the leads easier to distinguish and work with.
           I wired my matrix on a perfboard, with a layer of stiff paper between the anode and cathode leads to prevent any short circuits. The mass of wires and leads are too close for my soldering skills at this time. The wire wraps have no structural strength so the paper was necessary for me to complete the matrix in reasonable time. I got the idea for the paper after watching a youTube video on layered printed circuit boards. My wire was 30 AWG jumper wire from the Shack, where I also purchased a wrapping tool. It takes about 5 minutes to learn to wrap like a pro, I can’t say that about soldering.

           The paper was cut in strips, first one direction, shown partially completed here, then the perpendicular direction as this gave the solderless joints more stability. I’ll let you figure out how I used an old sponge and a paperclip to line the holes up exactly. For some reason, component leads do not exactly match the drill holes on either breadboards or perfboards.


           Since the so-called authorities on this subject don’t mention it, be sure to use insulated wires for your matrix connections. I saw several jpegs where bare wire was used and it just doesn’t make sense to take that kind of chance because shorts on a matrix are very hard to detect. Take an extra look at my progress photos, for if this type of intricate wiring isn’t your strong point, now is the time to have second thoughts about this project. You can buy ready made matrix components.

           You may be able to spot where I ran out of 1,000 Ω resistors and used some 330 Ω in series. Several sources said to use 1,000 Ω resistors in all LED matrix circuits, although all of them failed to give a good reason why that is so. I’m merely following orders on this one.

           At this point, you have built the matrix, complete with resistors. I could not find a good schematic or description, so I took a large and complicated schematic of a multicolor matrix, zoomed in and very slowly erased all the parts I did not need. The result is the 9 LED diagram shown nearby. The wires that cross are not nodes, they are not connections.
           Before you do any Arduino work, you may want to take a battery supply and test the circuit for shorts and other problems. You can see me testing the middle LED. I spent twenty minutes looking for a short in the LEDs for what turned out to be a short on one of the resistors. Beyond that, this 3 x 3 matrix tested fine the first time. Here is a diagram of my logic. In the end, it was so tricky to keep track of the rows and columns that I named the columns X, Y, and Z.
           Let me say that most of the videos and on-line material is not helpful in this department. The ones that show the matrix don’t show the matching code and vice versa. Some code included libraries I could not find. So I set down to programming the LEDs one by one using a loop. My goal is to have the LEDs light up alternatively in an “x” and then a “+” with a pause between the patterns.

           Another important point not adequately explained in the material I read is the exact logic of how to turn on the correct LED. It is not enough to simply rely on your prior knowledge that a current will flow from source to ground, since you have more than one LED in series on each row or column. Try to follow my logic on how I solved this issue below.

           When you connect the cathodes to ground, they will always be grounded. Thus, any voltage to an LED will light up that entire row, not just the single LED. Thus, I have to leave the voltage HIGH for the cathodes connected to the LEDS I want turned off. No voltage will flow from HIGH to HIGH. This seems to fly against logic--that I have to turn a pin on HIGH to get an LED to remain unlit. You will run up against this quirk many times when working with a matrix.

           All the pins are output. All are controlled by commands from the Arduino, there is no interface with the outside in this circuit. Applying Boolean AND logic, a given LED should light only when its anode (positive) pin is HIGH and its cathode (negative) pin is LOW. There may be other ways to approach this situation, but if so, whoever knows them is keeping it a big secret. The LOW state must be as carefully controlled as the HIGH state.

           I arbitrarily chose pins 3, 5, and 6 for the anode pins, and 9, 10, and 11 for the cathodes because they are the PWM-enabled pins farthest apart on the brainboard, making my wiring just a little easier. Follow the code very carefully when you decide to read it, there are many pitfalls. (Question: why do I have to declare a pin as an integer? There is no pin 3.7 or 9.4, right?)

           Later, I figured out I did not need any pins with PWM for the working of this circuit, but it’s not like anybody was kind enough to say so before I got started. Maybe they were born knowing all the tiny details and don’t see any need to explain anything to their audience. Fact is, any set of pins will work, since they will exist only in HIGH and LOW state for the purposes of this experiment, no PWM needed. Ah, but what if I want to dim the LED instead of turning it off? Sure, if I live long enough. Let’s keep focused with simple ON and OFF.

           In the first pass through the code, I programmed the two patterns in one long chunk, thinking the void loop would keep calling them and causing things to look right. Nope, and although that loop could probably be made to work, it would be cumbersome. Although I’ve got the patterns to display, they ripple through each pattern so fast it can barely be seen until the last LED (in the code sequence). Again, it could be made to work, but at the expense of complicated and inflexible code.

           So, back to the drawing board. When I ran the code, all nine LEDS lit up. Something else must control the LEDs that I missed. The LEDS were flashing in sequence too fast for my slow eye. Let me slow things down (note the delay command strategically place to do just that). Wait, I got something to work on the second pass. Okay partial success. I can get the lights to flash in sequence, first the “x” pattern, then the “y” pattern by placing a 200 millisecond delay between each flash so I can see the results. And you were wondering why I had that delay command repeated so many times in the code . . . .

           But when I speed it up to see the POV effect, it does not happen. But the concept is good enough in that I have found a way to control specific LEDs that I figured out on my own, pat on the back here. Yet something is still wrong but nobody is going to quit now. The circuit loops once, very rapidly, then stalls. There is a logic error and those can be nasty. The tendency of programmers with a C+ mindset would be to keep adding more code until it worked.

           When I suspect my logic, I don’t blame my code. I think I need to code the patterns in subroutines, and call the subroutines in rapid sequence. This would also make the code more adaptable. That didn’t work either, since each subroutine ran once really fast, again moving rapidly to the last LED called, then leaving that LED lit until the next subroutine was called. It isn’t working.

           Thinking it through, I’m going to introduce a “for” loop in the code, first in the void loop, and if that doesn’t work, then in the subroutines. The idea is to have the code call the subroutine repeatedly for long enough to see the patterns. This is a crude brute force approach made necessary by primitive programming languages like C+. Examine the void loop code.

           Ha, note the syntax “examine the void loop”, only a C+ programmer would see nothing wrong with that sentence. They call it C+ programming because that is the average mark of the people who use it. All the C+ programmers are busy from last week’s change to daylight savings. They are still pouring sand out of their sundials.

           Son-of-a-gun, it works! I don’t have the photography equipment to get you working videos and clear photos of what I’m doing, but if you follow the code, I believe you may be able to see how I got this to work “on the fly”. There are probably far better or more efficient ways to accomplish the same thing, but this is the version I understand. For now. I took out the center LED in the cross pattern because it looked like it was on all the time. So instead of a cross, I have a diamond pattern.
           Without saying this is the right way to do things, I can say it worked for me. If you can do what I just did, the next step is to move to transistors to do the switching. They are supposed to be better at controlling a matrix, but danged if I can find anybody on line who will tell me why in plain terms. Warning, a project like this can cause you to have to re-wire your brain along. It is unlike anything in real life. I’ve never done anything like this before.

           I’ve attempted to upload a video of the successful operation here. Blogspot claims that their system is compatible with AVI, but despite following the directions to the letter, I cannot get a video to embed. Any assistance would be helpful.
Conclusion:
Two new things I learned from this experiment are:
           1. Now I know why so many people drop out of engineering school.
           2. Now I know why those who make it seem to lose their ability to relate to regular humans in terms everybody can understand.

           With this experiment, I’ve outdone myself and gone past my ability to work with other components. I can’t even solder worth a darn yet. I have a head start with matrix algebra and the brand of thinking needed to visualize the code so do not dismay if you don’t get it so easily. The remainder I am learning from scratch. But I’ve gone beyond my own aptitude with this crazy experiment which I did on a whim. I got lucky this time.

           In real life, this matrix would not be very rugged. For example, I used the fact that the LEDs only conduct in one direction. If an overvoltage hit the circuit beyond the threshold of the LED, it would probably be destroyed. I had also read in advance that the Arduino could power LEDs, but that larger loads require an independent supply.

           Here is the code. I’m the first to admit it is lengthy and repetitious. But if I cleaned it up and used arrays for the patterns, it would be harder to understand. (I intend to build a bigger matrix with discount LEDs from Hacktronics at which time I will attempt to streamline the code.) It would be nice if my critics allow that this is the first time I have ever done anything like this am just a few months into this hobby. Here it is, warts and all:

/* This is an LED dot matrix experiment
* It matches Experiment 018 in the Minutes
* Please refer to the notes to construct the matrix needed for
* this code. Your LEDs must be perfect and tested before
* proceeding with the code, as the matrix is hard wired.
* Today is March 22, 2011
*/

////////////////////////////////////////////////////////////////////////////
//Begin Initialization & Variables

int PinColX = 11; //Assigns the pins for the
int PinColY = 10; //columns. I used letters to
int PinColZ = 9; //minimize confusion.

int PinRow01 = 3; //Assigns the pins for the rows
int PinRow02 = 5; //I arbitrarily started counting
int PinRow03 = 6; //from the top left and across.

int vDelay = 1; //used only for debugging, set to 1 otherwise
int vTimer = 50; //sets the speed for the display loop


//End Initialization & Variables
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// Begin Main Program
////////////////////////////////////////////////////////////////////////////

void setup()
{
pinMode(PinColX, OUTPUT); //all pins used in this sketch are outputs
pinMode(PinColY, OUTPUT);
pinMode(PinColZ, OUTPUT);

pinMode(PinRow01, OUTPUT);
pinMode(PinRow02, OUTPUT);
pinMode(PinRow03, OUTPUT);

}
//-----------------------------------------------------------------------
void loop()
//this loop calls the subroutines repeatedly to keep the LEDS lit.
//make sure you follow this logic completely before continuing.
{
for (int i = 0; i <= vTimer; i = i + 1)
{
subPatternEX(); //calls the pattern that displays an "x"
}
//-----------------------------------------------------------------------
for (int i = 0; i <= vTimer; i = i + 1)
{
subPatternCR(); //calls the pattern that displays a "diamond"
}
}
//----------------------------------------------------------------------
void subPatternEX() //this is the pattern that displays an "x"
{
digitalWrite(PinColX, HIGH); // X O O Sets column 1 high
digitalWrite(PinColY, LOW); // X 0 0
digitalWrite(PinColZ, LOW); // X 0 0

digitalWrite(PinRow01, LOW); // 0 0 0 Sets row 1 low
digitalWrite(PinRow02, HIGH); // X X X
digitalWrite(PinRow03, HIGH); // X X X
delay(vDelay); //debugging delay
//----------------------------------------------------------------------
digitalWrite(PinColX, LOW);
digitalWrite(PinColY, LOW);
digitalWrite(PinColZ, HIGH);

digitalWrite(PinRow01, LOW);
digitalWrite(PinRow02, HIGH);
digitalWrite(PinRow03, HIGH);
delay(vDelay);
//----------------------------------------------------------------------
digitalWrite(PinColX, LOW);
digitalWrite(PinColY, HIGH);
digitalWrite(PinColZ, LOW);

digitalWrite(PinRow01, HIGH);
digitalWrite(PinRow02, LOW);
digitalWrite(PinRow03, HIGH);
delay(vDelay);
//----------------------------------------------------------------------
digitalWrite(PinColX, HIGH);
digitalWrite(PinColY, LOW);
digitalWrite(PinColZ, LOW);

digitalWrite(PinRow01, HIGH);
digitalWrite(PinRow02, HIGH);
digitalWrite(PinRow03, LOW);
delay(vDelay);
//----------------------------------------------------------------------
digitalWrite(PinColX, LOW);
digitalWrite(PinColY, LOW);
digitalWrite(PinColZ, HIGH);

digitalWrite(PinRow01, HIGH);
digitalWrite(PinRow02, HIGH);
digitalWrite(PinRow03, LOW);
delay(vDelay);
//----------------------------------------------------------------------
}

void subPatternCR() //this is the pattern that displays the diamond pattern
{
digitalWrite(PinColX, LOW);
digitalWrite(PinColY, HIGH);
digitalWrite(PinColZ, LOW);

digitalWrite(PinRow01, LOW);
digitalWrite(PinRow02, HIGH);
digitalWrite(PinRow03, HIGH);
delay(vDelay);
//-----------------------------------------------------------------------
digitalWrite(PinColX, HIGH);
digitalWrite(PinColY, LOW);
digitalWrite(PinColZ, LOW);

digitalWrite(PinRow01, HIGH);
digitalWrite(PinRow02, LOW);
digitalWrite(PinRow03, HIGH);
delay(vDelay);
//-----------------------------------------------------------------------
digitalWrite(PinColX, LOW);
digitalWrite(PinColY, LOW);
digitalWrite(PinColZ, HIGH);

digitalWrite(PinRow01, HIGH);
digitalWrite(PinRow02, LOW);
digitalWrite(PinRow03, HIGH);
delay(vDelay);
//-----------------------------------------------------------------------
digitalWrite(PinColX, LOW);
digitalWrite(PinColY, HIGH);
digitalWrite(PinColZ, LOW);

digitalWrite(PinRow01, HIGH);
digitalWrite(PinRow02, HIGH);
digitalWrite(PinRow03, LOW);
delay(vDelay);
}
//-----------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////
// END MAIN PROGRAM
////////////////////////////////////////////////////////////////////////////

// Key entered by Anton da Bassguy 2011
// Tested and compiled 2011-03-22
// There is no easy way to describe the logic of the digitalWrite statements
// above, it is best to just step through the code until it makes sense.
// Tested again 2011-03-23

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