Subscribe via RSS

Controlling lots of LEDs with your Arduino

There's a great article on the MAX7219/MAX7221 LED Drivers on that details how to utilise these chips to control a large amount of LEDs (MAX7219/7221 Datasheet.) The layout I've been working on was always going to have a lot of scenery lighting and I'd decided this time to use LEDs over traditional 12v DC Bulbs as they draw less current and can often be a lot brighter. Also, Japan does use a lot more 'white light' when lighting streets and train/traffic signals, so it fits in close enough to the prototype.

LED Drivers are specific intergrated circuits that are designed to control a large amount of LEDs wired up in a matrix. This means that, in the case of the MAX7219/7221, the LEDs will be in rows and columns of 8 for a total of 64 LEDs per chip. The exact wiring dictates that each column contains 8 cathodes and each row 8 anodes. This therefore means that if you apply power to one row, and then ground a column, you will light the associated LED. Of course, this means that if you power two rows and two columns you will in fact have 4 LEDs lit. This is because the matrix is limited in only being able to light specific LEDs on a row-by-row basis.

Fortunately, the Drivers are fast enough to light row after row (selecting the exact LEDs to light by grounding certain columns) making it look like all LEDs are on at the same time. Therefore, you can specify the exact LEDs to light and, in the case of an 8x8 matrix, you can draw pictures, scroll text, etc...

Of course, you are not limited to controlling a matrix. These chips fundamentally just light up 64 LEDs and, for my layout, this should be enough for my scenery requirements. The main issue is actually building a 'distribution point' for getting the 64 pairs of wires out to the LEDs from the chip.

Note: PLEASE make sure you have a 'clean' power supply and it's connected cleanly and solidly. I just spent a day diagnosing why my LEDs stopped working... it was because my 12v power distribution had a dry solder joint... totally frustrating!

How to wire up a MAX7219 LED Driver

As the chip only has 16 pins (8 rows, 8 columns), one has to split these out into inidividual wires to LEDs.

If you happen to have your LEDs in groups/clusters of 8 then you will have a lot less trouble wiring everything up... otherwise you'll need to tediously create a 'distribution board' like I've done here:

Plugs to connect LEDs to

So, once this was together I put some plugs on the end of the ribbon wire and then added header pins to my LED wiring. This then meant I could simply plug the LEDs in as no resistors are required. Trying to work out which way around to put them was quite easy, as they seem to get full voltage if you put them the wrong way! So, be careful, if this happens then quickly reverse the LED.

I then wrote some code to turn my well-lit footpath into a flashing mess...

//pins for the MAX7219 
#define CLK_PIN 31
#define LOD_PIN 33
#define DIN_PIN 35
//pins for my L298N throttle 
#define PWM1_PIN 3
#define PWM2_PIN 4
//library required from:
#include "LedControl.h"
//LED CONTROL... 3 pins and then the number of devices
LedControl lcl=LedControl(DIN_PIN,CLK_PIN,LOD_PIN, 1);
//currently connected lights:
//ROW 0:   NONE. 
//ROW 1: Building, Building, Building, Building,
//       Streetlight, Streetlight, Streetlight, Streetlight
//ROW 2-3: NONE.
//ROW 4: Streetlight, Streetlight, Streetlight, Streetlight,
//       Streetlight, Streetlight, Building
//ROW 4-7: NONE.
void setup() {
  //initialise the led driver...
  lcl.shutdown(0, false);   //turn off shutdown..
  lcl.setIntensity(0, 8);   //set the intensity, you can also use the potentiometer.
  //set initial throttle, direction and speed 
  digitalWrite(PWM2_PIN, HIGH);
  digitalWrite(PWM1_PIN, LOW);
  analogWrite(THROTTLE_ENABLE, 200);
  //turn on the building lights.
  for (int i = 0; i < 4; i++) lcl.setLed(0,1,i,true);
int MS_DELAY = 300; //timing, close enough to train speed.
void loop() { 
  //the streetlights are in a bit of a jumbled order:
  //ROW 4: 5,4,3,2,1 and then ROW 1: 4,5,6,7.
  //turn them all on
  for (int x = 5; x >= 0; x--){ 
    lcl.setLed(0, 4, x, true);
  for (int x = 4; x < 8; x++){ 
    lcl.setLed(0, 1, x, true);
  //now turn them back off
  for (int x = 5; x >= 0; x--){
  for (int x = 4; x < 8; x++){

And here was the result, with my homemade street lights:

The best thing about these chips is that they can be daisy-chained together to control a total of 512 LEDs off 3 pins. If you think you'll need more than that for your project, then you're crazy... but it can be done. Simply utilise another 3 digital pins of your Arduino to control another 512 LEDs... I shudder to think of something lit that brightly.

Comments (4) Trackbacks (2)
  1. This is an interesting chip you’ve found! I’ll have to get some and play around. The TLC5941/TLC59401/TLC5940 that I’ve been playing with sink 16 channels directly. Matrix-multiplexing requires and additional current-sourcing shift-register for each TLC594*.

    If it makes you feel better, I’m now at a loss to guess what new and interesting use you’ll be putting your Arduino to next.

    • Don,

      Those chips are much nicer if you want better control over the LEDs. PWM dimming would be a neat feature indeed. The chip here only sets one standard intensity and it’s really expected to only control 64 of the same type of LEDs (i.e. for signs/displays.)

      Fortunately I’m not that much of a perfectionist, so… as long as the LEDs come on, I’m happy :)

      Meanwhile, the next project is a while off as I’m still fighting with IR Detection. I can’t get consistent results and so have forked out for the Sharp units, but am attempting another method as well.

      • I was thinking about your problems the other day, and while thumbing through one of Forrest Mims’s excellent handbooks, wondered if you might could do something with Hall-effect sensors? You could set up an array—maybe just two—along side each track in the barn. I don’t know how sensitive they would be to the locos’ motors though.

Leave a comment