How to drive dozens of LEDs from an UNO R3 for a Christmas project

I'd like to replicate in miniature a big Christmas light display my dad did in front of out house when I was a kid. He's in his 70s now and I think it'd be cool to show him his work had impact. Anyway, that means I have to build a miniature 1-2' tall replica of the display (a tree with a star on top) using dozens of LEDs. My dad used an ancient microcontroller computer back in the day (about half the size of a cinder block if memory serves!) to turn the tree, "lights" on the tree, and star on and off in sequence. I even remember the sequence and I'm all ready to go....with just one problem.

Each output from an Arduino only powers 1-2 LEDs each. I need to drive dozens, and I need to do it as simply and inexpensively as possible. The local arduino retailler sold me a SparkFun TLC5940 on his recomendation, but it only seems to drive up to 15 extra outputs; when I got home I checked the specs and it also seems more suitable to things like servo motors?

Where would you go from here if you were me?

With muliplexing, or charlieplexing you can control many leds with just a few pins. You can really reduce the number of pins by incorporating an LED driver, or shift register, basically converting parallel data into serial data.

The 5940 chip is a very popular choice, and you could use it, but you could also control many leds without adding chips to your design.

I have a LED cube that runs 64 LEDs running on 20 pins, If it were setup in an 8x8 matrix, it would only require 16 pins to control those 64 LEDs.

Depending on how many LEDs you have to light up at a time, or how bright you need them, you may need to use a driver chip, but you may also be able to just multiplex.

I understand the theory of multiplexing and how it can communicate one source of data rather than the other, but how will this somehow introduce more power into my circuit? I simply can't attach a bunch of LEDs to a bus run by an arduino output--there won't be enough power to light them all up. Are you saying I should instead control a higher source of power (like a 9v battery?), turning it on and off using the 5v data signal from my arduino?

When you multiplex the LEDs, they are not on, like they are in a simple circuit. They turn on and off very rapidly, in patterns that appear to be on. Any matrix, or cube uses Persistence Of Vision to make the illusion of what you see.

An 8x8 LED matrix will light up to 8 leds at one time, so its max draw is actually 160ma from 8 20ma LEDs, not 64 x 20 1280ma!

Ohhhhhhh...that's really cool. So the way it must work is that you have the ability to power x LEDs at a time from your output, and as such set up an array Y elements long with x LEDs each, then you provide current to each element in the array in turn for...how long?

I guess the code for that wouldn't be too bad at all. One output of the MUX is always on and the other alternates between...well...HIGH and LOW I guess...? Is there an example circuit out there you can link me too?

Heres a cube, its similar to the cube I made. It use 64 leds controlled with 20 arduino pins.

Here is some code from a cube that uses 20 pins to control 64 leds

#include "xyz.h"

#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define REFRESH 100

int LEDPin[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int LEDPinCount = 16;
int PlanePin[4] = {16, 17, 18, 19};
int PlanePinCount  = 4;

boolean currentState[4][06] = {
{1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1}
}; // demo - initialized with this pattern

xyz neighbours[] = {{0,-1},{0,1},{4,0},{1,0},{-4,0},{-1,0}}; // use this to find possible neighbours

void setup()
{
  int pin; // loop counter
  // set up LED pins as output (active LOW)
  for (pin=0; pin<PLANESIZE; pin++) {
    pinMode( LEDPin[pin], OUTPUT );
  }
  // set up plane pins as outputs (active HIGH)
  for (pin=0; pin<CUBESIZE; pin++) {
    pinMode( PlanePin[pin], OUTPUT );
  }
  
  //Serial.begin(9600);
  setupState(); // randomize the state

}

void loop(){
  drawState();
  memcpy(previousState,currentState,64);
  progressGame();
}

/*this calucaltes the next Game of Life gamestate according the rules beHIGH
*1. Any live cell with fewer than two live neighbours dies, as if caused by under-population.
*2. Any live cell with two or three live neighbours lives on to the next generation.
*3. Any live cell with more than three live neighbours dies, as if by overcrowding.
*4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
*/
void progressGame(){
  for(int y=0;y<4;y++){
    for(int xz=0;xz<16;xz++){
      xyz thisLED = {xz,y};
      
      
      int numNeighbours = howManyNeighbours(thisLED);
      
     
      
      if(numNeighbours < 2 && currentState[y][xz]){ //underpopulation
        currentState[y][xz] = false;
     
      }
      else if(numNeighbours > 3 && currentState[y][xz]){ // overcrowding
        currentState[y][xz] = false;
        
      }
      else if(numNeighbours == 3 && !(currentState[y][xz])){ // reproduction
        currentState[y][xz] = true;
        
      }
      else if(currentState[y][xz]){
        
      }
      else{
      
      } 
    }
  }

}
// core to the Game Of Life, this works out exactly what it says using previously written valid function
int howManyNeighbours(xyz led){
  
  
  
  int numNeighbours = 0;
  for(int e = 0;e<6;e++){ //iterate each possible neighbour
    
    // is it out of bounds? and if not, is on?
    xyz neighbourDirection = neighbours[e];
    
    if(valid(led,neighbourDirection)){
      xyz neighbour = move(led,neighbourDirection);
      if(previousState[neighbour.y][neighbour.xz]){
        numNeighbours++;
      }
    }
  }
  return numNeighbours;
}

void setupState(){
  randomSeed(analogRead(20));
  for(int y=0;y<4;y++){
     for(int xz=0;xz<16;xz++){
       currentState[y][xz] = (int)random(2); //initiate every LED to random state
     }   
  }
}

void drawState(){
  long startTime = millis();
  boolean draw = true;
  while(draw){
    for(int y=0;y<4;y++){
      digitalWrite(PlanePin[y],HIGH); // turn on this plane
      for(int xz=0;xz<16;xz++){
        digitalWrite(LEDPin[xz],currentState[y][xz]); // set it to wahtever the state says it should be
      }
      delay(2);
      pinsOff();
      digitalWrite(PlanePin[y],LOW); //turn off this plane before moving to the next one   
    }
    if(millis() > startTime + REFRESH){
      draw = false;
    }
  }
}



void pinsOff(){
  for(int thisPin = 0; thisPin < PlanePinCount; thisPin++){
        digitalWrite(LEDPin[thisPin],HIGH);
    }
}

My dad used an ancient microcontroller computer back in the day (about half the size of a cinder block if memory serves!) to turn the tree, "lights" on the tree, and star on and off in sequence. I even remember the sequence and I'm all ready to go....with just one problem.

Do yo need to address dozens of LEDs? i.e. Turn them on & off individually? Or, do you only need to control several LED "strings". If you are turning on & off several LEDs together as a group, you may not need multiplexing or a shift register... You just need to boost the output voltage/current (with a MOSFET or something).

I just need to run 3 strings of LEDs.

You may want to make up some kind of schematic of what you want to do, be specific, include all the gory details.

If you are running 3 sets of 12 LEDs you may be able to do with just the arduino. 3 sets of 200 20ma LEDs or 3 sets of 4 1w LEDs will require more current, and that will require some parts (like DVDdoug mentioned.

I did a very quick and dirty layout on paper of what I'd need, and it's:

10 LEDs (yellow) - Star
13 LEDs (green) - Tree
9 LEDs (blue/red) - Lights on the tree
...and maybe a dozen more if I've got the resources to make a couple of presents under the tree.

32 LEDs off of, what? 13 or 14 outputs doesn't look good enough. If I used the breakout board, though, that would take care of the tree circuit, and the rest would have to be powered in 1's and 2's by individual outputs. Does that sound like a feasible plan? It seems a bit awkward but for now I'm willing to take something that's possible and work on making it efficient later.

If they are multiplexed, the would be individually controllable, and you should be able to run them right off the arduino without additonal hardware, but the LEDs may not be as bright. You could run the off some shift registers, that are powered by an external power supply, but it may turn out that its not much brighter.

If I were you, I would start with just multiplexing and see how it looks.

If the leds need to be either on or off, you could get a cheap shift register (or four). Something like this:

Then use the shift out to control it:

You can daisy chain 4 of them to control your 32 leds

If he is just turning on and off groups of led's then why not just use a few cheap BJT transistors?
32 led's x 20ma = 640 ma <that's cheap 12v wall-wart territory.
break that into a few groups and he does not need much in the way of size to run them.
there are tons of cheap and easy to use bjt's out there.

if he wants to get fancy then shift registers would work better.

cat6 here is a handy tool for figuring out parallel/series chains of led's
http://led.linear1.org/led.wiz