The
monome is a gorgeous, minimalist, open-source light-and-button pad used primarily by musicians as a controller. The folks over at
SparkFun Electronics, inspired by the monome, released their own
button pads and
circuit boards, only they designed theirs to be able to hold RGB LEDs. They made this nifty
Tetris game with their parts. Looking at it, though, I noticed something: they only seemed to use a limited palette, in particular, they only appeared to have red, green, blue, cyan, magenta, yellow, and white, corresponding to channels being fully on or fully off. I wanted to see if I could get colour mixing, wherein channels were on partially in order to blend colours smoothly.
Read on for more details, videos, and instructions on how to build one.
The Design
A common way to control many LEDs is
multiplexing, wherein only some of the LEDs are on at any given time. They are cycled through at a rate fast enough that the human eye can't detect it, and hence all appear to be on at the same time. In this case, having one row on at a time is the natural way to go. A similar method can be used to determine which keys are pressed; diodes are necessary to prevent "ghosting" and "masking" of buttons, as explained in
this article.
Analog output, used to control LED brightness, is usually achieved via
pulse-width modulation (PWM). While it may be possible to combine PWM with a multiplexed display, it would require very fast refresh rates in order to not appear to flicker. Furthermore, that would require 12 pins on the microcontroller be dedicated to controlling the brightness of the LEDs (3 colour channels x 4 LEDs on at a time). That eats up an unacceptable number of microcontroller outputs. Another solution had to be found.
Another way to adjust the brightness of an LED is using a resistor; in particular, if you want the brightness to be adjustable, a variable resistor. Fortunately, there exist digital potentiometers whose resistance can be set. I was introduced to one such digital pot in
this tutorial on the Arduino website, written by Heather Dewey-Hagborg. The chip in the tutorial, the AD5206, has six independent potentiometers on board. As I mentioned above, this project needs to control 12 channels at once, so two AD5206s should do the trick nicely.
The Parts
4x4 Button pad ($10, Sparkfun)
Button pad breakout board ($15, Sparkfun)
Arduino ($33, Adafruit)
16 common cathode RGB LEDs (I used RL5-RGB-D) (~$1.50ea, Superbrightleds.com)
2 AD5206 digital potentiometers ($3.66, Digikey)
16 1N4148 diodes (Pennies, any electronics parts store)
4 2N2222 transistors (Pennies, any electronics parts store)
Various resistors (LED current limiting and pull-down) (Pennies, any electronics parts store)
The Build
I'm too inexperienced with Eagle (and, let's face it, too lazy) to draw up a proper schematic. If enough people want it, I suppose I'll put one together. Still, the build itself is pretty easy. The button pad assembly is

straightforward: solder in the LEDs and the diodes according to the silkscreen on the board. Actually, the LEDs held in tightly even without soldering, and since I'm a bit paranoid, I did all of my testing with the LEDs held in place by tension alone. I soldered in wires for each of the input and ground lines, 24 wires in all, making it all quite a mess to work with. If I continue with this, I'll replace them with proper connections of some sort, but I didn't have anything handy, so wires it was.
The AD5206 gets wired up just like in the datasheet, or in this
tutorial from the Arduino site. To add the second digital pot, you wire it up exactly the same, and share the same Serial In and Clock lines with the first chip, with a separate Chip Select line. Each of the twelve outputs gets wired to one channel of one column of LEDs, with a series resistor in between to protect the LED from too much current and to set the colour balance. (You might be able to get away without this resistor, but it will

probably shorten the lifespan of your LEDs.) The zero setting of the AD5206 has a resistance of about 40 Ohms. In all the RGB LEDs that I've seen the red channel has a much lower forward voltage than the blue and green, something to consider when picking your resistor values.
The input and output lines from the buttons go into Arduino pins, with the output having
pull-down resistors. The ground lines from the common cathodes of the LEDs go to the collectors of the transistors, with the emitters going to ground, and the base pins attached to the Arduino (through appropriate resistors). Using the transistors ensures the Arduino pins don't sink too much current.
One final word about the build: make sure that, when soldered, your LEDs don't stick up too high, otherwise you might not be able to get the buttons to make a good contact. I found this out the hard way.
The Code
The basic outline of the code is:
Looping through the rows, bring each row of buttons high in turn, in order to scan that row for button presses.
Looping through the columns, check if each button-press state has changed. If it has, run the appropriate on_press or on_release routines. If it hasn't, run the appropriate while_pressed or while_released routine.
Still inside both loops, write the potentiometer value for that button entry.
End the column loop.
Bring the row of buttons low.
Bring the LEDs for the row high, wait a little bit so it's visible, and then bring it low.
End the row loop.I wanted to include real code here, but I have yet to figure out how to properly format it in the Blogger tags. If people really want to see it, I'll figure out how to add it in here.
(Update: I've posted some code in the Arduino forum for now.)
The Catch
Or, rather, the catches. Basically, this is a lousy a pretty lousy method to accomplish the colour blending. First of all, the digital potentiometers are voltage dividers; they limit current (and therefore brightness) by limiting voltage. That means that, once the supply voltage drops below the LED's forward voltage, the LED turns off. For the blue and green channels, this happens less than halfway through the pot's 8-bit range, severely limiting the range of colours you can get. I could use the digital potentiometers as rheostats, limiting only current, but then the 10kOhms maximum isn't enough to get them anywhere close to off, so I'd either need a high-resistance pot (with correspondingly low resolution), or additional circuitry to turn the LEDs off. Both bad choices. Furthermore, because of the LEDs' nonlinear current-brightness curve, the number of visible changes within that limited range is further cut. So, the resolution in colour space is much less than I'd like.
The other catch is brightness. Though the videos look really bright, it doesn't look anywhere near that good in person. Don't get me wrong, it looks alright, but not as good as it could look. Because of the multiplexing, the LEDs are on at a maximum a quarter of the time. In reality, it's probably more like a fifth or less because of overhead. Comparing a full-on LED to one at the duty cycle on the board really makes me want to come up with a non-multiplexed solution.
The FutureThe good news is, I think I have come up with a solution that will work for non-multiplexing the LEDs. The bad news is, it will eat a lot of current (so I'm looking in to power supply options), and it will require me to make my own circuit board (which I've never done before, but I'm going to have to learn sometime, so why not now?). The
really bad news is that the free version of
Eagle CAD has a size limit per board that is smaller than the 4x4 buttons. I'm not sure I'm ready yet to invest $125 in the non-profit license, so we'll have to see what happens. I'll get a breadboard prototype working first.
As for this version, I think it should easily expand to a 4x8 pad by adding two more AD5206s. It might require some fancy work, or even a demultiplexer IC, to read all 8 buttons in a row, but I think it should work. An 8x8 layout might also be attainable, but in order to keep the brightness up I would set it up as two 4x8's being driven off the same master controller. I think anything higher than 8x8, at least with this design, will require multiple microcontrollers for different segments with a master controller coordinating it.
One other possibility using this design, which is more in tune with the
minimalist philosophy of the original, would be to use single colour LEDs and fade them, ideas of which are shown in the following couple of videos:
Finally, if I were to continue pursuing this design, I would want to eventually put it on a board that could function as a "backpack" to the Sparkfun breakout board, similar to their
serial interface for their RGB pixel boards, or the idea behind the Arduino
shields. The idea would be a board with headers that lined up with those of the breakout board, which can be attached directly to it to extend it's functionality.
The ChallengeWow! If you've read this far you must be
really interested. I'm flattered!
Here's the deal: so far, all the demos I've written are running directly on the Arduino, so the whole setup is standalone. One of the coolest things about the monome, though, is that it's
interfacing with something (namely, the computer). Implementing a serial protocol on the button pad is pretty trivial. However, you need something to interface with. I haven't had time to write any software that would talk to the button pad via the serial port and do something cool; I'm too caught up in the microcontroller side of things. However, if someone were to write software to talk to the button pad, I would definitely set it up to work and post a video of it in action.
Here are the requirements: it needs to run on OS X, and I need to be able to see the source. A
Processing sketch would be ideal. You can set the communications protocol up any way you like, as long as you explain it; it should be easy, all you need to send are coordinates and RGB data, and received a 16-bit binary string indicating whether buttons are pressed or not. Post something in the comments, maybe a link to the code, and we'll see if we can get it working.
I'll be honest, I don't really expect anyone to respond to this, but man, it'd be cool if someone did!