Several months ago I came across a piece called Flylight from Studio Drift. It's a gorgeous piece of work, a chandelier composed of several dozen or maybe several hundred separate lights. The idea is that it's a swarm of light. It's flying, it's fluid, and its light moves throughout the available space.
The lights appear to be miniature incandescent bulbs or very warm white LEDs, and can be lit individually. The discrete nature of the lights means you can take a hundred of them and build an arrangement that fits any space, vertically or horizontally. Nice idea. I decided I needed one.
I've been fascinated by 3D light displays since seeing Nine Inch Nails and their aptly named Lights In The Sky tour. Flylight runs in a similar vein, though at the extreme opposite end of the emotional spectrum. I really like the concept of a swarm of light. That's the part I wanted to replicate. The glass bulbs Drift made for each light are also cool, but they're not what caught my attention. In fact, that's something I immediately wanted to change. If you look at Flylight, it's big and it commands its space. I wanted something lighter and more flexible, something you could overlook if you're not careful. Step one, let's replace the cables with strings, something like ultra-thin dacron, so you get the impression the lights are almost floating in space. Second, let's do away with the glass bulbs. They work like flow lines, giving you an impression of the movement of the flock, or the swarm, but they're too heavy. Also, I don't know how to blow glass, and I don't think I currently could afford to make or have made several hundred of those. Third, instead of having the swarm defined by the location of the bulbs, let's make the swarm defined by the location of the light they produce. In other words, instead of arranging lights into a predetermined form, let's make a general purpose display, and draw a swarm on it.
My design concept ended up being a 3D field of lights, hanging in a grid like strings of Christmas lights.The first thing to do was figure out what performance I needed to make it look right. My goal is to show something like a predator/prey model. For static images you need high resolution, but to merely convey motion you don't. I wanted to show a flock of birds, a swarm of butterflies, flying around the room, and I was hoping I could get the effect I wanted without selling a kidney. I threw together some simulations in Matlab, predator/prey, prey only, raindrops falling, stars twinkling, and they looked promising. A 16x16x16 cube, updated at 30Hz or higher, can show a wide variety of images and motion very nicely.
Oh by the way, I decided the perfect location to install the prototype would be the stairwell at my mother's house. It's big, empty, and kind of boring. It needs something crazy like this. It's a fairly large room, and I decided 6-inch spacing between lights, resulting in an eight-foot cube, would be about right.
So I need 256 strings, each of which has 16 lights, spaced out at six-inch intervals. How should I build this? Incandescent bulbs look wonderful, but bulbs as small as I need would be expensive. I would need to go buy 4096 Maglite bulbs. Additionally, incandescents burn out. Replacing them would be an incredible pain. LEDs have their own problems though. Warm white LEDs typically have small viewing angles, and this chandelier is designed to be viewed from above and below. On top of that, warm white LEDs can get pretty hot. Finally, I need brightness control. On/off LEDs would look awful, but generating 4096 PWMs is not a small task.
The first idea I tried was to control each string of 16 with a single LED driver IC. You can get a wide variety of ICs that control 16 or more lights with anywhere from 3- to 16-bit brightness control and are controlled via I²C or SPI for about $1.00 each. This seemed promising. All I had to do was buy a hell of a lot of the thinnest wire I could find and strand 16 LEDs into a cable with the IC at the top. I also found some amber through-hole LEDs with a decent viewing angle and current that safely could be multiplied by 16^3.
Unfortunately, amber is not warm white. I tried several different options, but there's only so much you can do with a single-color LED. At least the power was fine. Each LED pulled about 20mA, so each string pulled about 0.3A at full duty. I built a test cable out of 40awg wire. This was incredibly time consuming (turning 17 strands of hair-thin wire into a cable , with each wire terminated at a different position, is incredibly tedious), but it worked, more or less.
Still, I wasn't all around happy with the results. I didn't want to spend the time and money required to build this thing if it was going to look like this. I decided to look for fundamentally different options. Just brainstorming, I thought the ideal solution would be an RGB or multiple-wavelength warm-white LED with its own control IC. I thought, if I were going to mass produce these things, that would be the route to take. I bet we could make a one-wire serial protocol that would allow me to string LEDs in series almost indefinitely and control them all using one GPIO pin. Luckily, it turns out this product already exists. Some company I'd never heard of called Worldsemi made a chip called the WS2812, a single RGB LED controller. It takes a signal from a one-wire serial interface and parrots the signal on to other LEDs, allowing you to string an arbitrary number of LEDs together with only three wires. Beautiful. They also make LEDs with this IC built in. Even better. You can also buy many different varieties of them from Adafruit and have them delivered in 48 hours for a high but manageable price. Praise the Lord. I ordered a few packs.
Adafruit's rainbow demos are nice, but I wanted an incandescent feel so I wrote a temp/color conversion function to light the LEDs with natural light colors. It's not perfect, but it's good enough for now. We'll optimize later. So these are great. They are more or less my ideal solution. However, Adafruit sells them for $1 a piece. I'm not spending $4100 on these things. Alibaba to the rescue! On Alibaba, I can buy 1000 of them for $70, about one fourteenth of Adafruit's price. I ordered 5000. Heck, if I only use 4100 of them, I can sell the remaining 900 on eBay for half of Adafruit's price and recoup most of the investment.
<pile of LEDs>
So I can put 16 of these WS2812 LEDs on each string and control each string with a single GPIO pin. That means I still need 256 GPIO pins. Hmmmm. My go-to microcontroller has long been the arduino pro mini. It has 20 GPIOs, so up to 20 strings, assuming the CPU is fast enough to talk to them all in sequence at 30-60Hz. For simplicity's sake, I decided to do 16 strings (one row of strings, one layer of the cube) per arduino. That makes nice sense. I bought several miles of 34awg magnet wire and started soldering. I assembled one string and ran some demos. Adafruit and Worldsemi recommend putting stiffening capacitors on the Vcc lines and decoupling capacitors on the data line, but that's difficult when you're working with just LEDs and magnet wire, so I decided to see if everything would work without that. Luckily, it appears to, so far. I soldered together a full 16 strings, bought a 100W power supply, and plugged it all in.
This is cool. I like this. It's raining light in the stairwell. As an added bonus, my mom is totally confused and weirded out and doesn't know what to say. With this level of development, I can display anything that doesn't require coordination between strings. That means rain, stars ... anything that's regular across horizontal space. My swarm visualization will require 16 arduinos with 16 strings with 16 LEDs to be linked, communicating in realtime. The idea for that is that I'll connect 16 arduinos to a USB hub, controlled by a master PC, probably something simple like a Raspberry Pi Zero. I don't need a lot of computational power, just something with low overhead and reliable timing.
This was the original plan, and it would work if I wanted to build it, but after some thought I decided I could do better. By that, I mean better quality, better flexibility for future upgrades, and also lower cost. Arduinos are not cheap, especially not those Sparkfun pro micros with the super convenient 32u4 chips. Additionally, I didn't like having a USB cable for data and a separate cable for power. Remember, I want the final product to be as thin, lightweight, ethereal as possible. Thick power cables going all over the place are bad. Each LED can pull up to 60mA at full brightness, which means each string can pull ~1A, and each arduino cluster can pull 16A. However, in practice, only a few lights will be lit on each string at a given time, and usually at a fraction of full brightness (at full power, these things will give you a headache in a few seconds). In normal use, each 16-string cluster was pulling ~4A startup current and 0.4A steady state during the above rain demo. I was pretty sure I could deliver the power I actually needed using only the USB cable. Time for an experiment.
USB cables deliver 5VDC, and the USB 2.0 standard says applications are limited to 1A. The physical cables themselves are typically 28awg multi-stranded copper and are officially rated for 1.4A continuous current. However, what's the safety factor? Let's find out what a standard, $2 USB cable can actually carry. I hooked up a 5-foot USB mini cable to a power supply and set it for a little over 5V and little over 3A. After a minute or two, the cable was noticeably warm. That's obvious cause for concern. However, the temperature leveled out after about five minutes, and was measured to be 29ºC, steady state, in a 22ºC room. That's totally acceptable. What next? I unplugged the 5-foot cable and connected it to a 15-foot USB extension cable. After another hour, the 5-foot cable was still at 29ºC, and the extension cable, which was all around a higher quality cable, was still at ~22ºC. So 3A across a standard USB cable is totally do-able. This means I can connect each cluster of 16 strings to the power supply and top-level controller using one cable. This is very good.
So one problem fixed, but we're still using arduinos, which are just barely powerful enough to run 256 LEDs, and are overpriced. I started looking for a better controller. I got a TI TM4C123 Launchpad board, which has an 80MHz ARM CPU, several times more features than any arduino, and a lower price than most arduinos. Of course, changing CPUs means I have to rewrite the LED control library. Adafruit wrote a very nice, very thorough, very robust control function set. I threw together a very sloppy, actually quite awful function set to control WS2812s from the Launchpad. I could actually control 256 LEDs using only that, but I can do much better. We'll work on it.
So, the next step is to fabricate custom PCBs that will control a single cluster of 16 strings. Each PCB needs a TI MCU, MOSFETs that allow me to turn on the strings a few at a time to limit startup current, and some stiffening capacitors for the case that I momentarily pull more than the ~3A I know the USB cables can handle. That'll take a while. Hopefully, I'll have news about that soon. I'm still incredibly far away from the end goal, the final product, a large-scale 3D light display that floats minimalistically in the center of the room, filling the room with flocks of birds, or rain, or other organic forms. What else should I show? I'm thinking I want something like a tree, rustling in the wind, but that might require higher resolution. A 16-cube can only effectively show motion. How about leaves blowing? How about waves of something, flowing through the room? Or dimly lit, slow moving fog ... lots of options. We'll be able to draw anything we think of, which is the whole point. I'm looking forward to that.