LED Fireworks. Or, parent helpers go overboard

My friend, Mike Ward, and I help out at our kids school by teaching
5th and 6th graders programming in conjunction with a Lego class. For
several years, I was teaching Logo on ancient Apple II machines. The
teacher had a great curriculum and the kids learned a lot, but
this year we decided to switch things around and try them out on
Arduinos.

This spring, the kids are building a Lego display centered around
a birthday party theme for the star elephant at the Oregon Zoo
(Packy), who turned 50 last weekend. In a moment of fun, I suggested
that perhaps we should have some fireworks, along with the presents
and birthday cake. How hard could it be to wire up a couple of LEDs to
an Arduino to make something that looked like fireworks?

Selecting parts.

Mike and I sat down to order some parts from Digikey. We found these
nice, cheap,
LED drivers from Sharp.
Then we found a selection of LEDs from Cree
along with current-programming resistors (12.7kΩ) to drive the LEDs at
20mA, and some bypass caps (0.1μF) to keep the parts happy.

The LED drivers are simple shift registers, with separate clock and
data. They have both input and output pins, so you can daisy chain
them and drive as many as you like from a single pair of CPU pins. We
figured 160 LEDs would be plenty, so we ordered 10 chips.

The LED drivers came in a through-hole, DIP package; it seemed like
we'd be able to just stuff them into a breadboard and quickly wire
things up.

Prototyping the design

The LED driver chips turn out to use a much finer pitch package than
the usual 0.1" spacing. There's no way we could stuff them into a
breadboard and quickly wire things up. Obviously, a bit more care
while ordering would have uncovered this, but my experience with
through-hole parts is limited to parts from the mid 1970s…

I soldered extension wires onto one chip to test the circuit, and
managed to get one chip talking to an Arduino. Here's a short movie of
that in action:

You can see the LED driver chip sitting on a set of extension leads
plugged into the breadboard. It's hooked to the SPI port on the
Arduino board, with the clock set as fast as it will go. If you
watch the video, you can see that the LEDs actually vary in
brightness. They're actually being pulse-width modulated. Clocked at
2MHz, there's enough bandwidth in the SPI bus to drive 160 LEDs with
127 discrete pulse widths at nearly 100Hz (100 * 127 * 160 = 2032000).

Is bread boarding practical?

With the chip propped up on its extension wires, and the LEDs plugged
in, the whole setup was not surprisingly fragile. Getting five
of these chips wired up and running for the length of the Lego show
(one day at school and two days at the zoo) seemed unlikely. So, we
decided to build some custom circuit boards.

Using the GEDA tools to make circuit boards

My business partner, Bdale Garbee, and I build rocketry electronics
through Altus Metrum. He's the hardware guy
and I spend my weekends writing firmware for various
micro-controllers. Of course, I use free software tools for the
firmware, and Bdale uses the free gEDA tools
for the hardware. I've gotten vaguely familiar with those by helping
Bdale review circuit diagrams and PC board layout over the years. So I
figured I'd be able to learn a bit more about them and come up with
some designs.

I decided to stick two LED drivers on each board. As the chips can
drive each LED with up to 50mA of current, each board could
potentially consume 1.6A at 5V. Sticking a linear regulator on each
board capable of supplying that much current would have required a
hefty heat sink. Instead, I decided to stick a mini USB connector on
the board and use some cheap USB power supplies.

Of course, there wasn't a pre-packaged schematic symbol or footprint
for the LED driver, so I first had to construct those. But, with
symbols for all of the parts I used available, I drew this circuit:

Wiring up 32 LEDs

It's really easy to draw wires showing 32 LEDs hooked up to each
board. Actually selecting connectors that can be easily hooked up took
a bit more time. The idea of crimping individual two-pin connectors
for 160 LEDs didn't seem like fun, plus individual connectors were
going to cost a small fortune (the best option I found would have cost
about $0.40 per LED). Bdale suggested using ribbon cable with a
crimp-on connector -- crimp a connector across the whole cable and
then split out two-wire sets for each LED. I'd still have to
individually solder each LED to the wire, but on the board end, all
I'd have to do is crimp the connector on to the cable.

Designing the circuit boards

The gEDA tools separate schematic design and PCB layout into two
separate tools; the schematic program, gschem, exports a netlist and
set of components which the schematic program, PCB, can import. This
sounded a bit clunky to me, as you have to re-export and re-import the
schematic data into the PCB each time you make changes, but it seems
to work reasonably well in practice.

The first time the schematic data is imported to the PCB tool, all of
the component footprints are simply stacked on top of one
another. With those moved to sensible locations, the tool will show
'rats' for each netlist.

Having drawn the schematic with symbols that strongly resembled the
actual components, it was pretty easy to work through the rats one at
a time by painting copper on the board. I'd noticed that all of the
signals could easily be routed on one side of the board, so I flooded
the back side with a ground plane to keep things quiet.

The final circuit board design looks like this:

Circuit boards.

All Altus Metrum products are manufactured by Advanced Circuits, and
we've been quite happy with them. They offer a cheap and fast
prototyping service through their
barebonespcb.com site. These boards are two
layers with no silk screen or solder mask.

I uploaded my design and in a couple of days I got back some shiny
circuit boards:

The footprint I designed for the LED drivers turned out to have a very
small gap between the pads for each pin and the ground plane. This
lead to a couple of shorted pins in the five boards, which were pretty
easy to diagnose as the LED driven by that pin would be stuck on.

Here's another picture with the ribbon cable connected and an LED lit
up:

Mounting the LEDs

I started by writing a small nickle program to
simulate the trajectory of a ballistic fireworks shell followed by an
explosion at apogee and subsequent ballistic tracks for the resulting
pieces. I made the initial conditions of the launch somewhat random,
and Mike and I sat and watched that draw things until we saw a couple
that looked 'good'. The output from that was a series of X/Y locations
spaced uniformly in time. Mike used those to drill holes in a piece of
acrylic from TAP plastics. He glued the LEDs into that with some white
glue (so that we have a chance of getting them back out):

A custom maple box?

I spent last weekend visiting my father for his birthday. Meanwhile,
Mike was busy back home building a case for the project. I got home
and found that he had fabricated a solid maple case. It's beautiful,
and holds all of the LEDs, boards, wires and a couple of 4-outlet USB
power supplies.

Here's a picture of the joint he made in the box corners:

The finished product

Here's the inside of the box:

And here's a movie of the whole thing in action. It's missing 8 white
LEDs; I hadn't ordered enough from Digikey.

Things I'd do differently

One of the frustrating things about moving atoms around instead of
just bits is that once you've got a physical artifact, it's really
expensive to change it. There are a couple of minor things I would
change if I were going to build more of these:

Add mounting holes. Not having any way to mount the boards means
that they're flopping around inside the cabinet. We'll probably
find a way to tie them down somehow, but a couple of holes in the
boards would have made that really easy.

Increase the gap between the pin pads and the ground plane. The
narrow space provided ample opportunity for solder bridges. I've
increased that spacing in the git repository version of the
boards.

Used a variable resistor for LED current control. With a fixed
value, it's very difficult to adjust the relative brightness of the
LEDs. Even though we used LEDs from the same series, the different
colors have different apparent brightness.

Used surface mount passives. We had bought through-hole parts when
the plan was to build these on a breadboard, but soldering
through-hole parts onto the board is more work than using surface
mount parts. 0805 (or even 1206) parts are plenty large to solder
by hand and are faster to deal with than having to fold leads,
insert them into holes, flip the boards over, solder them down and
trim the leads.

Perhaps we went a bit overboard on this project...

Things that worked well

There were a couple of things that went better than I had expected:

The gEDA tools aren't that hard to use. Constructing the circuit
board really was a simple matter of painting with copper. If you
can drive inkscape, you can make circuit boards.

Advanced Circuits bare-bones PCB service. It was really cool to
upload the output files from gEDA and have actual boards arrive in
the mail a couple of days later.

Building the boards. I really didn't expect all of the components
to 'just fit' in the boards; I figured I'd mess up the footprints
or drill sizes and end up kludging something onto the
boards. Bdale did catch a small drill size on the LED driver pins,
which I bumped up a bit, but other than that, all of the parts
slipped in and soldered easily. Each board took about 10 minutes to
put together.