A friend of mine had a great idea for an awesome project. He wanted to create a pair of servo rigs that would mimic the movement of his hands using a leap motion. On top of the servos would sit some lasers so he could create some kind of laser-light show.
I talked him down from lasers to LEDs, and we eventually settled on using RGB LED matrices. He initially tried to use Rainbowduino to drive a single LED matrix, but it wasn’t working out so well. I offered to design and build a custom driver board that could not only drive one matrix, but two, using a single ATmega328p – the same chip used on the Rainbowduino board.
Check out this Instructable where I teach you how to build the entire parent project!
So grab your soldering irons and order some parts. It’s to do some real embedded systems design.
Step 1: Parts and Tools
As always, we need to gather a few materials before we dive into the project. There is a lot going on here, so be sure to double check the parts!
Parts and Components
- ATmega328p – 8 bit MCU
- 2 x RGB Matrices (These cheap ones on Amazon are what I used)
- 4 x 16 pin female header – standard spacing
- 1 x 3 pin female header – standard spacing
- 2 x 3 pin male header – standard spacing
- 6 x TLC5916 – 8 x Constant Current LED Sink
- HEF4094 – 8 bit SIPO latching register
- 8 x NTD2955 – P Channel MOSFET
- 8 x BS270 – N Channel MOSFET
- 9 x 0.1uF Ceramic Capacitor
- 2 x 22pF Ceramic Capacitor
- 16MHz Crystal
- 17 x 10k Resistor
- 4 x 4.7k Resistor
- 2 x 2.67k Resistor – You can use a 2.2k in series with 470 ohms
- 2 x 680 ohm Resistor
- Small normall-open momentary push button
- Perf Board(s) – To house soldered components
- 2 x 10uF Aluminum Capacitor – (Optional) Spaced out on boards to help with power line performance
- Computer – for programming and such
- AVR Programmer – This one from Sparkfun is fantastic.
- Soldering Iron and Solder
- Wire – some small gauge and some larger gauge to handle higher current levels
Step 2: Understanding Matrix Multiplexing
Multiplexing LEDs can be tricky, but we’re working with RGB LEDs, so think of each RGB as three individual LEDs. For an 8 x 8 matrix, that is 192 total LEDs on a single matrix. Even though there are only 32 connection pins, it is still possible to individually control the color and brightness of every single LED.
Take a look at this diagram from the datasheet for the RGB Matrix I am using.
You should see that each “row” shares a common anode. Similarly, each column (of each color LED) shares a common cathode. To drive just a single LED, we will drive its shared anode HI and its cathode LO. To control the color of each individual LED, we will have to do some low level multiplexing.
There are eight rows of common anodes, so each row will only be on (powered) for 1/8th of the time. The trick is to switch between which row is on so fast that a human eye cannot detect it. In this way, the pins driving the LED cathodes will only control one row of LEDs at a time. As the active row is switched, new values for the cathode lines will have to be loaded.
Step 3: Determining Matrix Pin 1
It was impossible to tell what pin was what just by looking on the matrices that I got. It is also unknown if the pin numbering wraps around the matrix in the same way that pins are numbered on an IC. The only real way to know is by applying voltages to a few pins until you see a pattern.
Using the schematic in the previous step, we can try to illuminate a single LED. If a positive voltage is applied to pin 17 with a negative applied to pin 1, the blue LED of row 1, column 1, should turn on.
DO NOT APPLY DIRECT BATTERY VOLTAGES TO THE PINS. Always use an inline current limiting resistor. A 10k resistor and 9V battery will work fine.
If the pin numbering is similar to that of an IC, pins 1 and 17 will be in opposite corners, if not, they will be directly across from each other.
Once you think you have found this single blue LED, test your findings by trying to turn on a few other random LEDs. Once you have the pin numbering down, be sure to mark pin 1!
I preferred to plug the matrix across two vertical breadboards for development; however, this meant my rows were actually columns. Because of this, I refer to the “rows” of the datasheet as “columns.” I also start counting from 0 instead of 1, as in common in low-level control.
Step 4: Circuit Design
With a basic understanding of how to multiplex the LEDs, we can build a circuit to drive them. A single ATmega328p will be used with an external 16MHz crystal. This chip will rapidly switch control between the eight common anode columns (remember, these are “rows” on the datasheet). Since the current through all LEDs in a single row is far too much to be sourced by an MCU pin, I am using a HI-side MOSFET pair to source the LED current.
Remember a current source is on the positive side of a component. A current sink is on the negative side. You can think of it like this (in terms of common circuit design orientation, at least): a source pushes current, while a sink pulls it.
Originally, I was driving the transistors directly from the MCU, but I added an external 8bit shift register to do this in order to free IO lines for future capability expansion.
The current sinking is handled by a few 8 channel constant current sinks. For 2 matrices, 6 chips are required – one for each column of R, G, and B LEDs.
You should also notice that I have included an I2C connection. This will be used for external control of the LED colors and/or strobe patterns. In addition, the ISP lines are not shown on this schematic, but it is a good idea to include them in your circuit so you can actually program the chip! Lastly, there is a line called “servo control”
The only values that might change for you are the external resistors on the TLC5916 current sinks. These resistors set the current for the LEDs, and I will go over how to set these values in the next few steps.
I have included the circuit as a Cadsoft Eagle file as well. The servo control line is not necessary for this project.
Step 5: RGB White Balancing Overview
On each LED current sink, there is an external LED connection R-EXT. This resistance sets the LED current; however, it will not be sharing that current, so we don’t need to worry about power ratings.
According to the datasheet (which I attached for your viewing pleasure), the equation to determine the LED current is as follows: (1.25V / R-Ext) *15
The gain can actually be adjusted by a special control line sequence, but it’s easiest just to find a resistance using the default gain and step size.
Now, there is a definitely science to properly white balancing LEDs; however, I was able to do it rather quickly just by simple tests and observations. In case you don’t know, the individual colors created by an RGB LED are formed by combining various levels of red, green, and blue. If all three are fully on, a pure white light should be seen. Here are the basic combinations, with each LED being fully on or off.
- RED + GREEN + BLUE = WHITE
- RED + GREEN = YELLOW
- RED + BLUE = MAGENTA
- GREEN + BLUE = CYAN
If all three LEDs are drawing the same current, the colors will not look right. This is a result of the various intensities that different colored LEDs produce at different currents.
In the next step, we will determine the resistance values for each LED current sink.
Source: AVR Dual RGB Matrix Driver