Step 1: Electronics
* we wanted it to be brighter than a multiplexed display would allow (since any subset of LEDs can be turned on at once)
* we wanted to reduce software complexity that is inherent to multiplexing
* we didn't want there to be any flickering artifacts on video footage of the display
The display is driven by an Arduino-compatible development board called Nanode interfaced to chain of custom made circuit boards hosing Texas Instruments TLC5926 16-bit Constant Current Source Sink Driver. Sixteen of these boards provide the 256 current sinks needed to drive the display. These chips have a similar interface to the familiar 74HC595 shift registers, except that:
* using a single resistor per chip you can set the current that each channel will sink when it's enabled
* they can handle sinking up to 120 mA per channel (!) (we only set the current to about 20 mA on our boards)
* when you set a channel to one it sinks the preset constant current on that channel, whereas a zero pulls no current on that channel
The boards also each have a 74HC125 quad-buffer on board to ensure good signal quality all the way to the end of the chain of boards.
In summary, for our 16 x 16 display, we used one of these boards per row of LEDs and chained them all together to drive all 256 displays.
Step 2: Firmware
The display is represented in memory as an array of sixteen 16-bit words. Each element of the array represents one row of LEDs (because that's how we wired it!). To change the image being displayed the words in the array are shifted out one bit at a time in the statement "sr.loadValues(game_board[CURRENT_GAMEBOARD], 16);" which uses the ShiftRegister library to bit-bang the 74HC595-compatible interface to the TI TLC5926. This routine clocks in all the bits then toggles the latch pin to enable the desired outputs across all the chips at once to keep things stable.
Two things to note that we want to play with. Rendering animations including shading should be possible by interfacing to a computer or by generating frames algorithmically. Arduino's digitalWrite function is painfully slow, though, so to get higher frame rates and/or more shades of gray we would make some adjustments to the ShiftRegister library to make it more specific to our display and use lower-level port manipulation functions rather than digitalWrite. We figure 4-bit gray scale at 30 Hz refresh is plausible back-of-the-envelope.
Step 3: Construction
A flat sheet plywood was cut to 3 feet square to provide the structural support for the display. Holes were drilled with a forstner bit at regular intervals for the LEDs to be mounted. We chose to recess the ping pong balls slightly to avoid light leakage around the edges and disguise any irregularity to the cut edge. The forstner bit drills a hole for the LED to poke through the plywood while also carving out a round recession. Hundreds of ping pong balls were painstakingly cut in half to be used as translucent diffusion covers for the LEDs. We found that making an initial slice with a utility knife and finishing the cut around the ping pong ball with scissors was the fastest and safest method. We selected wide angle LEDs to reduce hot-spotting on the ping-pong balls, and used a double layer (one ping pong ball inside another) to further diffuse the light. Hot glue was used to attach the ping pong balls. Note that although we are referring to these as ping pong balls, they are actually beer pong balls. Ping pong balls are made of highly flammable celluloid, and beer pong balls are much less expensive and are non-flammable.
We used copper tape to run all the power rails along each row and down both sides The chain of TLC5926 boards was insulated from the copper tape where they would overlap using velcro and double-sided tape. The Nanode was likewise mounted to the to the plywood in some free space and wires were run to the source of the shift-chain interface. An ATX computer power supply was repurposed to provide the juice for the project. As an aside, consider that 256 LEDs consuming 20mA each adds up to over 5 amps if they are all on!
We used CAT5 ethernet cable wires to solder a length of wire from each dedicated TLC5926 breakout board pin to each individual LED cathode (i.e. short pin) being careful to get the order right and consistent. We then soldered the anode of each LED down to the copper tape power bus. So when the dedicated current sink pin is turned on, the requisite amount of current flows from the power bus through the LED (causing it to illuminate!), into the sink, back down the chain of boards and into ground on the power supply.
All said and 768 solder joints were made (512 to the LEDs and 256 to the TLC5926 breakout boards). Really makes you appreciate the upside of multiplexing! :-) Because the TLC5926 are chainable, it should be possible to make more panels just like and hook them together to compose a bigger display.