Introduction: Lampduino - an 8x8 RGB Floor Lamp

About: For more information on my projects as they develop, visit my blog: http://blog.lincomatic.com
Lampduino is a computer-controlled free-standing floor lamp, comprised of an 8x8 RGB LED matrix. The lamp stands 45" high and 18" wide.  Light emanates from both sides.  It has various display modes, as well as an included editor for creating animations.  The lamp is controlled via an application running on a PC host.  The display modes include realtime drawing, playback of previously created animations, snow, meteor, plasma, and synchronization with music.  With its endless available colors, Lampduino can also be used for color therapy, or as a mood light.  When running standalone, without a computer, it plays a soothing plasma simulation..

NOTE:  Any flickering in the videos below is caused by video camera aliasing.  Persistence of vision makes it look flicker-free by the naked eye.



Step 1: Bill of Materials

Parts List

(64) 5mm common anode RGB LED's. I bought mine on eBay
(1) ITead Studio Colorduino or an Arduino with Itead Studio Colors Shield
(
1) large piece of foamcore board.  This kind of board can be found in most office or artist supply shops.  It is a foam core sandwiched between two sheets of thick paper.  I recycled a 45x30" piece that had a previous life as an advertising poster.
(2) 18x18" pieces of matte drafting film.  I cut them out of a single 24x36" sheet of .003" thick Grafix 2-sided matte drafting film.
lots of 30AWG kynar-insulated wrapping wire. I bought 3 50 feet rolls at Radio Shack, one each of red/white/blue. 150 feet is overkill, but it's a lot easier to work with different colors of wire.
(2) 16-pin male headers
(1) 5V 1A power supply.  I repurposed a wall wart from a broken gadget.

For music synchronization, a few additional parts are needed.  See the Music Synchronization step.


Tools

x-acto knife
hot glue gun
wire stripping/wrapping tool
straight edge
ruler

Step 2: Lay Out the Grid Pieces

Each of the 64 LED's in the matrix is enclosed in a 2x2x2" cell.  First, draw out your cutting lines in pencil on your foam board. You will need 14 grid pieces to form the core of the matrix. I found that it's convenient to lay out the cuts in pairs that are facing each other.  This way, you can cut two slots at once.

Cutting foam board requires a very sharp knife.  I used a #11 X-acto blade.  If your knife is dull, instead of cleanly cutting through the foam, it will just catch on it, ripping out little chunks of foam.  It's not very pretty.  I went through 3 blades while making the matrix.  Change the blade when the cuts start to get degraded.  I found it hard to make a single clean cut through the 3 layers of the foam board; this method often left me with little chunks of ripped out foam.  It's easier to make clean cuts if you first make a deep score with the knife against the straight edge.  Make sure the score goes through the whole top layer of paper, and into the foam.  Then you can remove the straight edge, and just run the knife repeatedly into the score until you get through the layers.  

First, cut the slots.  You can pop them out at this stage, or wait until the next step.

Step 3: Cut Out the Grid Pieces

Next, cut the grid pieces apart with your x-acto knife and straightedge.

Step 4: Cut Slits in the Grid Pieces

Cut horizontal slits into the grid pieces, one in the center of each cell.  Make sure the slits go through all the layers.  You needn't be super precise, but they should be about 1/2" long.  The LED's will be held in place in a later step by pressing the wires into the slits.

Step 5: Assemble the Grid Pieces

Assemble the 14 grid pieces to form the core of your matrix.  Don't glue it yet.  You might have to take it apart several times while wiring it up. I painted over the printed bits with white spray paint before proceeding.

Step 6: Wire Up the 8 LED Strands

I chose wire wrap as the wiring method for this project because:
  1. it’s cheap
  2. there are no toxic fumes
  3. there is no risk of overheating and destroying LED’s
  4. it’s easy to undo, so repairs are easier
  5. it’s relatively quick to do
  6. it’s as reliable as soldering – perhaps more reliable, since there’s no risk of cold-soldered joints
  7. the wire is so thin that it can be threaded into the gaps between the foam matrix pieces
If you are not familiar with wire wrapping, Wikipedia has a detailed introduction to the technique.  I was a bit worried that the 30AWG wire would be too thin to handle the current running through the matrix.  I consulted some tables on the Internet, I found that 30AWG solid wire has a resistance of 105.2 Ω/1000 ft. I estimated an upper bound of 4 ft of wire, so that’s ~.4Ω – probably insignificant for this application. Next, I found that the current carrying ability (Ampacity) is estimated at .144A by most tables, but one actually had it listed at .86A. The LED’s I used run at a maximum of 20mA per color. In a column, a maximum of 1 LED at a time is lit, so it’s definitely in spec. On the other hand, if a whole row is driven w/ the with all 3 colors lit, we can end up with 8 x 3 x 20mA = 480mA. This is way over the .144A spec, but below the .86A spec. I decided to just try it, and if I encountered problems, I would put multiple wires in parallel for the rows.  After testing, I found that using single wires for the rows worked fine ... they did not heat up at all.

The schematic diagram for a common anode 8x8 RGB matrix is depicted above. We are going to wire our matrix, composed of 5mm LED's, in the same fashion.

We need a total of 8 strands of 8 LED's.  Each pair of LED's is connected with three 4" pieces of wire. The anode is the lead which is slightly longer.  In my photo above, the pins, from left to right, are Blue/Green/Anode/Red.

The red wires connect the red channel,  the white wires the green channel, and the blue wires the blue channel.  4" may sound a bit long, since the cells are only 2" wide, but I when you account for stripping the wire on both ends, and leaving enough slack to manipulate the LED's in while assembling the grid, 4" is a good length.  You will need 49 4" pieces of wire for each color - 147 pieces total.  While working on this step, I discovered a few things which make for a quicker and cleaner job:
  1. orient the pins of your LED's the same way while wiring them (e.g. blue pin on the left, red pin on the right)
  2. connect the R/G/B wires between each pair of LED's before moving to the next LED.  At first, I was connecting all the reds, then all the blues, then all the greens.  This method was a bit messier.
  3. spread the pins apart a bit before wrapping.  Otherwise, the wrapping tool will get caught on the adjacent wraps as you try to insert it 
  4. start the first wrap about halfway into each lead
  5. when connecting the second wire on each lead, just stack the wrap against the previous wrap.
Note that the anode pin is left unconnected at this stage.  This is because the anodes form the rows, which are perpendicular to the R/G/B cathode wires, which form the columns.

Step 7: 8 LED Strands

When you are done with this stage, you will have 8 strands of 8 LED's each.

Step 8: Thread the LED Strands Into the Matrix

Thread the LED strands into the gaps between the grid pieces.

Step 9: Wire Up the Rows

Next, flip the matrix over so that the slots running perpendicular to the strands are on top.  Wiring up the rows is a bit trickier, because we're working in close quarters.  However, unlike the columns, the rows need only 1 wire per LED, a total of 49 wires.  Here's where the slack we created by using 4" long wires comes in handy.  It lets us manipulate the LED's more easily.  Connect the anodes with 6" lengths of wire.  The yellow wires in my photo are the anode connections.  I had an old spool of yellow wire, but it ran out before I was done with the rows. It's easier to wire up all the anodes before you insert the LED's into the slits, as pictured.

Step 10: Route the Wires

I ran all of my column wires through a single slot in the matrix ,to the bottom.  I cut slots in the bottom for running the row wires.  This was a mistake, because now my columns are horizontal, and the rows are vertical.  The correct orientation is the reverse:  the column wires should out the bottom, and the row wires down the side.

Step 11: Connect the Matrix to the Colorduino

Wrap the 32 wires coming out of the matrix into the two 18-pin male headers.  Note that you have to wrap on the short end of each pin, because we need to long end to plug into the Colorduino.  The headers on the Colorduino are clearly labeled.  The red and blue pins go on one header, while the anodes and the green go on the other.  Note that the anodes are labeled VCC on the Colorduino, and that there are 4 anode pins on each side of the 8 green pins.  The origin of our matrix, (0,0), is located at the bottom left.  Therefore, pin 1 of red/green/blue should connect to the leftmost column.  Similarly, pin 1 of the VCC (anode) pins should connect to the bottom row.

Before plugging the matrix into the Colorduino, it is a good idea to test it, and check for shorts, as well as correctness of the header wiring.  I used a 5V power source, hooked up to a 100Ω resistor, to test each individual LED.  I was pleasantly surprised to find that I didn't have a single short circuit in the matrix.  

Step 12: Finish Constructing the Matrix

After the wiring and testing is done, you can attach the top, bottom, and sides.  Note that there is an 3" long extension of the side pieces on the bottom.  This is to accomodate the Colorduino.

Step 13: Add the Legs and Stand

My intention is to wrap the matrix in wood, and attach it to a wooden stand.  However, due to time constraints, I decided to first prototype it using foam board.  I cut two 45x2" pieces to form the legs.  For greater stability, the lower section is two layers thick.  The base is 22x6". The box directly beneath the matrix, which houses the Colorduino, uses two 18x3" sheets for its sides.

Step 14: Cut and Attach the Drafting Film

Cut two 18x18" squares of drafting film.  Attach one to each side of the matrix.  I made a mistake, and used hot glue.  Hot glue is hard to deal with when gluing large objects, because it cools down too fast.  I forgot that when I built my 5x5 matrix, I used Elmer's glue instead. Elmer's works a lot better, because it gives you time to pull the film tight, and get all the wrinkles out.  Also, unlike hot glue, it doesn't mar the look of the matrix with little shadows of glue blobs.

Step 15: Colorduino Description

An Arduino doesn't have enough I/O pins, nor enough current output to drive an 8x8 RGB LED matrix. Therefore, one needs to interface it with external LED driver circuitry.  The Colorduino is an Arduino variant, which is specialized for driving up to 192 LED's (64 RGB LED's).  For a detailed description of the Colorduino, see my article, Itead Studio Colorduino - A Preview.  Note that my Colorduino is a beta board.  The production version, V1.3, has been released to manufacturing.  It contains some minor tweaks, such a repositioning the ICSP header to a location that actually has enough space for you to plug in your programmer!

The Colorduino can be powered by 5V via the 8-pin header, or with 6.2-7.5V via the 4-pin green screw terminals.  When switching between the two power sources, it is important to put the slider switch in the correct position.  The Header position is for power through the VDD pin on the 8-pin header, and the Terminal position is for power via the VCC pins on the 4-pin green screw terminals.

The LED's draw a lot of current.  When I powered the Colorduino with either my Arduino or my USBtinyISP, I was not able to program it, because the LED's draw too much current.  Switching to a separate 5V 1A supply fixed the problem.

On drawback of using a dedicated board such as the Colorduino is that it doesn't expose any I/O pins for external inputs.  Therefore, many users connect them to another Arduino via I2C.  Since I'm using it standalone, I connected my input to one of the I2C pins. There are actually a couple of other free I/O pins, such as INT0 and INT1, but they are not connected to any accessible headers, so you have to solder wires directly to the ATmega MCU to use them.

Step 16: Programming the Colorduino

The Colorduino comes with the Arduino bootloader pre-loaded, so it can be programmed via the Arduino IDE.  It doesn't have a built-in USB to serial converter, however, so you must use either an external USB to serial cable, or an ICSP-compatible programmer. If you have an FTDI cable or similar, you can use that.

To use an FTDI cable, connect it as follows:

 FTDI RX -> Colorduino TX
 FTDI TX -> Colorduino RX
 FTDI RTS -> Colorduino DTR
 FTDI GND -> Colorduino GND

Another way is to use the embedded FTDI chip in an Arduino Duemilanove.  Simply pop out the ATmega MCU from the Duemilanove board, and make the following connections between the two boards:

  Arduino RX  ->  Colorduino RX
  Arduino TX  ->  Colorduino TX
  Arduino Reset -> Colorduino DTR
  Arduino 5V -> Colorduino VDD
  Arduino GND -> Colorduino GND

Then, you can connect your Arduino to your PC via USB, and select Arduino Duemilanove or Nano with ATmega328 from the Tools->Board menu of the Arduino IDE.

Since I was developing a PC host app to communicate with the Colorduino, I found it more convenient to use my USBtinyISP.  When using a USBtinyISP, the serial port doesn't need to be shared between the Arduino IDE and your host application, so you don't have to keep starting/stopping your host app every time you need to reprogram the Colorduino.  For more information on how to use a hardware AVR programmer with the Arduino IDE, see my article:  How to Use the Arduino IDE with an External Programmer.  Another benefit of using an ICSP programmer is that we can save program memory, since we no longer need the Arduino bootloader. Also, the Colorduino boots up instantly as soon as power is applied to it (with the bootloader installed, it takes a couple of seconds).

Pictured above is my development setup.  I used a 60x60mm RGB matrix plugged directly into the Colorduino.  On the right is my USBtinyISP for downloading sketches, and on the left is my Arduino Duemilanove, supplying a serial connection to my host app, a Processing sketch.


Step 17: ColorduinoSlave Firmware

In my design, the Colorduino acts as a slave to a PC host application.  Since a 24-bit per pixel RGB frame takes up 192 bytes, the Colorduino can't store many frames onboard, even if you use program memory.  Therefore, the host program sends the frame data down to the Colorduino via a USB->serial connection.  I have written the sketch so that the Colorduino boots up with a plasma demo when not connected to the PC host.

The Arduino sketch for this project, ColorduinoSlave.pde, makes use of the Colorduino Interface Library, which I also developed.  I've included the current version in ColorduinoSlaveV1.zip, but in case of future updates, you can always download the latest version from: Colorduino Library for Arduino.  The library takes care of all the dirty work of talking to the LED control hardware on the Colorduino, such as basic initialization of the hardware, refreshing the screen, and providing basic primitives for double-buffered updates to the screen.  This way, you don't have to clutter up your sketch with all this extra code.  To install the Colorduino Library, simply download the zip file, and copy Colorduino.cpp/Colorduino.h into your <Arduino sketch folder>/libraries/Colorduino.  If you are already running the Arduino IDE, you need to restart it so that it can find the newly installed library.

Load ColorduinoSlave.pde into your Arduino IDE, and upload it to the Colorduino.  It simply waits for data packets from the host.  The receive buffer in Arduino's Serial library has a receive buffer size of 128 bytes.  Since one of the functions of this project is real-time music synchronization, it is important to reduce the latency of sending frames from the host to the Colorduino.  Therefore, I took the liberty of quantizing the data down to 12-bits per pixel.  This way, screenful of data uses only 96 bytes (with packet protocol overhead, 100 bytes), and an entire packet fits into the receive buffer.

ColorduinoSlave Packet Protocol

The ColorduinoSlave packet protocol is simple, and designed to be as compact as possible.  The basic format is:

<SYNC BYTE> = 0xAA
<OP CODE> (BYTE)
<DATALEN>
[DATA PAYLOAD]
<CHECKSUM>

DATALEN is the size in bytes of the optional data payload.  CHECKSUM is simply the 8-bit sum of all of the bytes in the packet after SYNC BYTE.  When ColorduinoSlave receives a packet, it immediately returns a status code to the host.  A status code of zero means no error.  A non-zero status code means an error was encountered, such as a corrupted packet.

The following opcodes are supported:

#define OPC_PING 0x01 // used to test if ColorduinoSlave is there, and responding to commands

#define OPC_PLAY_FRAME 0x02 // imediately play a 12-bit frame

#define OPC_QUEUE_FRAME 0x03 // place a 12-bit frame in the frame queue.  The size of the frame queue is controlled via PACKED_FRAME_QUEUE_LEN.  My beta Colorduino came with an ATmega168V, so the RAM was so puny that my frame queue can only handle 2 frames.  If you have an ATmega368, you can go higher.

#define OPC_SET_MODE 0x04 // set the current operating mode.

#define OPC_FILL 0x05 // fill with a 24-bit solid color.  The data payload is 3 bytes, R, G, then B.  Each value is from 0-255.

The operating modes selectable with OPC_SET_MODE are:

#define CMODE_PLASMA 1 // go into automatic plasma display mode
#define CMODE_PLAY_FRAME 2 // accept OPC_PLAY_FRAME packets
#define CMODE_MUSIC_SYNC 3 // sample music inputs via SENSOR_PIN
#define CMODE_FILL 4 // accept 24-bit RGB values
In CMODE_MUSIC_SYNC, the host sends 12-bit frames via OPC_QUEUE_FRAME whenever until the frame queue is full.  Once the frame queue fills up, ColorduinoSlave will not send a response back to the host until it dequeues at least one packet.  When not in CMODE_MUSIC_SYNC, OPC_QUEUE_FRAME does not exhibit this blocking behavior, and always immediately returns the status to the host.


Step 18: RGBmtx Host Software

The host software, RGBmtx, is a Processing sketch. It is a heavily hacked up version of mtxControl (thanks, Tobi!), and excellent visual animation editor for RGB matrices. Processing is a simplified version of Java, much as Arduino is a simplfied version of C++.
I have included pre-compiled executables for Windows, OSX, and Linux, which you can directly run without installing Processing on your computer. You can find them in RGBmtxAppsV1.1.zip. They still require Java, so if you don't have Java installed on your computer, download it from java.com. If you don't want to play with the source code within the Processing IDE, skip to Using RGBmtx below.

WARNING FOR THOSE USING ARDUINO 1.x

The serial buffer has been decreased to 64 bytes, which is too small for RGBmtx to properly communicate with my ColorduinoSlave sketch. RGBmtx will just freeze up your Colorduino, and not work correctly.
To fix it, you must exit the Arduino 1.x IDE and edit modify hardware\arduino\cores\arduino\HardwareSerial.cpp.
Look for the line


#define SERIAL_BUFFER_SIZE 64

and change it to


#define SERIAL_BUFFER_SIZE 128

Then restart Arduino 1.x and re-upload the ColorduinoSlave.pde sketch to your Colorduino.

If you have trouble with communication between RGBmtx and the Colorduino, try disconnecting the connection between DTR and Reset.

Working with the Source Code in the Processing IDE

The full source code to RGBmtx is contained in RGBmtxsrcV1.1.zip.

RGBmtx relies on a Java Colorpicker. Before you can run the sketch, you must copy colorpicker.jar /libraries/colorpicker/library/colorpicker.jar. Restart the Processing IDE if it's already running, so it can find the newly installed library.

Copy the contents of the RGBmtx folder to /RGBmtx, and load RGBmtx.pde into Processing.
You should be able to launch it by clicking the Run button in the Processing IDE.

Using RGBmtx

If your Colorduino is connected to your host PC via a serial port, RGBmtx will automatically find it. The scanning for the device occurs only on startup, so make sure to connect it to your computer before launching RGBmtx. If the Colorduino is not connected, then Device:Slave will be grayed out, and you will only be able to run it in Record mode.

To create animations for your matrix, simply use the built in editor in Record mode. When editing frames while the Colorduino is connected, the matrix will instantly update in realtime. Click on the color patches to select the current drawing color. To select a color which is not in the default palette, hold down the CTRL key while clicking a color patch to pull up an RGB color picker (Note: for some reason that I can't figure out, pulling up a color picker sometimes freezes up RGBmtx. Therefore, make sure you save your work first). The little buttons on the right, bottom, and bottom right corner allow you to fill a whole row, column, or the entire matrix with the currently selected color. You can use the matrix as a mood light by filling it with a single color.

To save a set of frames to your PC, click Save to: File. RGBmtx can save in two different formats: BMP and MTX. If you specify a filename without an extension, it will save to Windows BMP format, and the filename will automatically be appended with .bmp. If you specify a filename ending in .mtx, the data will be saved in a text file format instead. You can also create or edit animations with any BMP-compatible graphics editor (.bmp), or, if you prefer a text editor (.mtx).

To load a previously created frame set, click Load from: File. If you specify a filename without an extension, it will automatically append .bmp. If you want to load a .mtx file, you must explicitly type the whole filename. I have included some sample framesets in framesets.zip, which you can download below.

You can cycle through RGBmtx's various modes by repeatedly clicking the Mode button. The modes are:

Record - create or load a frame set

Play - play the currently loaded frames. I have attached some sample frame sets below.

Plasma - run plasma mode

Snow - display a snowflake-like effect

Meteor - similar to Snow mode, but with trails

Music - music synchronization mode. Optional. You must add the music synchronization circuit described in the next step.

In the Play, Snow, and Meteor modes, you can control the playback speed with the up and down arrow keys on your keyboard.

framesets.zip contains the following sample framesets:

spaceinvaders.bmp - Space Invaders
tetris.bmp - Tetris simulation
music.bmp - suitable for synchronizing with music

mal_animations.zip contains some cool animations that were created by Mal3D

If you make any framesets that you think are really cool, please send them to me, and I'll make them available for everyone to download. For that matter, please send me any good upgrades you make to RGBmtx or my Colorduino library.

UPDATE 2016-10-10:White-Tea has written MagicMatrix, an alternative host controller software in Java. I have not tested it myself, as my Lampduino is currently inoperable. Github repo for MagicMatrix:

https://github.com/wietsebuseyne/MagicMatrix

his announcement comment:

https://www.instructables.com/id/Lampduino-an-8x8-R...

Step 19: Set the White Balance

In order to allow the lamp to display the widest gamut of colors, it is important to set the white balance as best as you can.  Using RGBmtx in record mode, send a screen of solid white R=255,G=255,B=255 to the matrix.  You will probably see a distinct color cast.

The DM163 LED driver IC in the Colorduino has inputs for adjusting the relative current running through the 3 color channels.  These are controlled by resistors.  Rather than using potentiometers, ITead Studio installed fixed 10Ω resistors in all 3 channels.  This is because the DM163 also has an extra set of three 6-bit registers set aside for adjusting the relative brightness of the 3 color channels via PWM control.

In the setup() function of ColorduinoSlave.pde, there is the following code:

// compensate for relative intensity differences in R/G/B brightness
// array of 6-bit base values for RGB (0~63)
// whiteBalVal[0]=red
// whiteBalVal[1]=green
// whiteBalVal[2]=blue
// unsigned char whiteBalVal[3] = {36,63,63}; // for LEDSEE 6x6cm round matrix
unsigned char whiteBalVal[3] = {22,63,63}; // for 5cm CA LED
Colorduino.SetWhiteBal(whiteBalVal);

The values range from 0 to 63, with 0 being off, and 63 being maximum brightness.  Try playing with these values until you achieve the closest approximation to white on the matrix.

An Alternate Method

Another way to set the white balance is to first send a sketch to your Colorduino with all channels set to maximum brightness:

unsigned char whiteBalVal[3] = {63,63,63}; // all channels maximum output

Next, using RGBmtx in record mode, iteratively send solid color screens to the matrix, adjusting the relative R/G/B values until the display as closely approximates white as you can achieve. Then multiply each value by 63/255, and enter it into whiteBalVal.

I was able to get a pretty decent approximation of white when using my LEDSEE 60x60mm matrix.  Unfortunately, I was not nearly as successful with the hand-built 5mm LED matrix in Lampduino.  As you can see from the photo above, there is a wide variation of relative R/G/B levels among the 64 LED's.  This makes it impossible to tweak more than a few LED's at a time to display white.

Step 20: Reducing FTDI Serial Latency

If you use a FTDI-based serial port, including an Arduino Duemilanove, there is a 16ms latency introduced by the driver.  This short latency normally does not cause problems.  However, if you decide to implement the music synchronization feature described in a later step, any extra delay between the host and Colorduino communication will cause a lag between the music beats and the response on the display.  If you are running Microsoft Windows, you can tune down the latency via the FTDI driver's advanced settings.

Start the Windows Device Manager while your FTDI USB->Serial cable or Arduino Duemilanove is attached.

Look for its corresponding USB Serial Port under Ports (COM and LPT).

Right click on it, and select Properties from the popup menu.  Next, click the Port Settings tab, and click the Advanced... button.

In the dialog which pops up, change the Latency Timer (msec) value to 1, and click OK.

After you disconnect/reconnect your device, the new Latency Timer value will take effect.

I am not sure if there are similar settings in OSX or Linux.  Hopefully, someone can dig up a similar IOCTL to achieve the same effect.

Step 21: Music Synchronization (Optional)

In order to synchronize our matrix with music, we need to connect it to an audio source.  I want it to sync to the bass beats. Building upon the music synchronization capabilities of my 5x5 matrix, we are going to reuse the previously designed circuit. The circuit we will use is a simple op-amp mixer, connected to a first order low pass RC filter, tuned to a cutoff frequency of 133Hz.


Parts List

(1) 10uF electrolytic capacitor
(1) 120 ohm resistor
(3) 10K ohm resistor
(1) 100K ohm resistor
(1) 1/8" stereo TRS jack
(1) TLC272CP op amp IC


Circuit


UPDATE: Sorry, the schematic diagram above is wrong.  There should be a third 10K resistor, R5, which connects between pin 2 (- input of opamp) and GND.  The gain of the amp is R4 / R5.

The op-amp stage mixes the left and right music channels, and amplfies the audio signal with a gain of 10.  This signal is then fed into our passive low pass filter.  Instead of connecting to the filter output to ANALOG PIN 0, connect it to SDA on the Colorduino.  Make sure that the GND from the music circuit is also connected to the GND on the Colorduino.

Connect the input to an audio source, such as the headphone jack of a stereo, or an MP3 player. DO NOT CONNECT IT TO SPEAKER LEVEL OUTPUTS FROM AN AMPLIFIER UNLESS YOU'RE SURE IT OUTPUTS <= 5V. Any audio source designed to drive headphones should be safe. Since I use the headphone jack on a stereo, I can still hear the music even when the circuit is plugged in. If you're using something with only one output, such as an MP3 player, you can hook up two TRS jacks in parallel, and then feed the audio from the 2nd jack to a set of powered speakers or headphones.

It might seem logical to use a microphone instead of direct audio input.  There are plenty of microphone circuits on the web, which you can use, if you prefer this approach.  Just add the RC filter between the mic preamp and the SDA pin.  I decided against this approach, because I wanted it to key off the bass beats, and in order to hear enough bass, one has to turn the volume quite high when using a microphone.

To use music sync mode, after hooking up the circuit as described above, repeatedly click on the Mode button in RGBmtx until it reads Mode: Music.  Then start playing your music, and adjust the volume until the matrix responds to the music to your tastes.


ColorduinoSlave.pde Sketch Tweaking

You may need to manually tune the threshold variable:

   // trigger next frame when music amplitude > threshold
   // increase threshold to decrease sensitivity
   // decrease threshold to increase sensitivity
   int threshold = 31;

The next frame will be played when the input read from SDA exceeds threshold. Notice that the threshold is set to 31 in this sketch, much higher than the threshold I used in the 5x5 matrix.  This is because when the Colorduino is driving LED's, the circuit switching causes noise on the SDA pin.  Even if SDA is grounded, on my beta Colorduino board, random values up to 31 are read.  I know that the noise is related to the LED circuit switching, because if I disable the screen refreshing function in the Colorduino library, then SDA reads a solid zero when grounded.  You may need to use a different value if you use a production quality Colorduino, or instead use a real Arduino with the ITead Studio Colors Shield.

Next, you may want to experiment a bit with minBeatInterval:

  // debouncing - filter out consecutive triggers that are too close
  // together to slow down the animation. decrease this value
  // to make it more sensitive to shorter beat intervals
  int minBeatInterval = 750;

Note that this variable is unit-less. It simply defines how many consecutive loops after the input exceeds our threshold before the sketch is allowed to trigger the next frame. I found that in many songs, bass beats are actually composed of several very closely spaced peaks. If we don't filter them out, then the display will advance several frames for each beat. You might actually like this effect, because it makes the display more lively. Play around with it, and see what setting you prefer.

Step 22: Summary and Future Enhancements

The matrix took about 8 hours total to construct. The wiring took another 20 or so hours.  A lot of the construction/assembly work was extremely tedious.  I thought I was going blind and batty.  My fingers and back were aching.  I learned a lot about perseverence while building it.  (On the other hand, I have nothing complain about compared to the builder of this monster:  http://www.youtube.com/watch?v=jlJ9fSPPUEc) 

The software and firmware took many more hours to develop. I finally got my feet wet on Processing, which I had wanted to learn about for a while.  Since Processing is essentially Java, I also gained some experience with Java, a ubiquitous programming language that I had never had the time to learn.  All in all, it was an interesting and educational experience for me, designing and building this lamp.

The first enhancement will be to replace my rather rickety foam board frame, legs and stand with wood (the matrix itself is ok to stay w/ the foam).  This will be a lot more aesthetically pleasing, as well as durable.  Next in line is wireless control via Bluetooth.  Another idea is to use an SD card to store frame data for standalone playback.  The music synchronization is currently implemented using a polling loop.  It would be more efficient, and perhaps latency could be reduced if hardware interrupts were used instead, via the INT0 pin.  This would require soldering a wire directly onto the ATmega MCU, as well as an additional circuit comprised of a Schmitt trigger.

I have seen various comments on the Internet questioning the long term reliability of the wire wrap connections.  Wire wrap is at least as reliable as soldering (if not more), and can easily hold up for years.  In fact, early computers were often constructed using wire wrap techniques.

3rd Epilog Challenge

Second Prize in the
3rd Epilog Challenge

MakerBot Challenge

Participated in the
MakerBot Challenge