Monday, November 07, 2011

Turning GE Color Effects G-35 Christmas Lights into a 7x7 display with Arduino

Some time ago I saw some GE Color Effects G-35 Christmas lights and was fascinated by the combination of color patterns that they were capable of and the fact that they only had three wires. That meant that something digital was going on.

Happily, a chap called Robert Quattlebaum did the hard work last year of hacking these lights to reveal that they are linked by a simple self-clocked serial protocol that can easily be driven by a microcontroller. That blog post gives the full details of the protocol.

Each lamp can be set to a specific brightness and an RGB color (4 bits per color). And the protocol is clocked at 30µs per bit so it's possible to refresh the entire 50 LED string at a rate of 24Hz. Perfect for hacking fun.

So I got a set and plugged them in just once (still in their packaging) to check that they worked. Here's a video of the lights getting their one real work out before the soldering iron got to them.



The first thing I did was remove the lovely plastic blub covers (these are being saved to brighten up a simple set of Christmas lights) to reveal the LED inside. This picture shows all three states: one has the original plastic cover on, the one in my hand has it removed but the plastic base intact, the bottom one is the naked LED and controller.

Once you've ripped off the protective plastic you are down to a simple LED with three wires going in (+5V, Data and GND) and three coming out. With 50 of these on a string I decided to make a 7x7 display (with one LED 'spare' should I break one).

Here's the finished display. The entire chain of lights has been cut up, mounted, resoldered and is now controlled by an Arduino Pro. All that's needed is a 5V power supply to plug into the power socket.

It's controlled by a small piece of Arduino software that contains a simple frame buffer implementation, code to implement the LED protocol via bit banging, code for scrolling text and for making faces. You can get the source code here. The key file is protocol.cpp which initializes the display and allows simple setting of the color and brightness of each LED. The most interesting part of that code (at least to me) is the initialization of the LED addresses. On power up the LEDs wait to learn their 6 bit address. They wait in turn and have to be programmed for use. I exploit this to make addressing them easy:

To build this I first cut up the entire string of lights to get just the LEDs with a small amount of cable attached to each. Then I prepared a piece of plywood, marked it up, drilled guide holes and then drilled the 49 mounting holes for the lights.

Then I glued in place each of the lights taking care to orient them for easy soldering into the chain. Then just 144 solder joints and little bits of heat shrink later I had the chain reattached and capable of being driven by the GE supplied controller.

The next step was some sort of opaque diffuser to put in front of the display. For this I used a cutting board that I cut to the right size. With the board in various positions it's possible to get different diffusion effects.

The final step in the hardware was to get a picture frame made to measure (I got a cheap, but deep, one in simple white wood from these folks) and then stuck the cutting board inside, used some old nylon nuts as spacers, mounted the LED board and finally used a piece of MDF that was supplied with the frame as a backing. The back is fixed on using some parts from an old servo.

Electronically this modification to the original lights was pretty simple. Having eliminated the original power supply and controller all that was needed was a new controller in the form of an Arduino Pro and a 5V power supply. The supply provided with the lights gave 5V at 3A (which seemed at lot). I measured the actual power usage and the highest current seen was 1.68A with all LEDs on white at maximum brightness. Thus I used an off-the-shelf power supply for the lights (plus Arduino Pro) capable of providing 2.25A.

The Arduino Pro is screwed to the back of the picture frame and there's only one component added: a 10K pull down resistor between GND and pin 7. Pin 7 is driving the serial data through the LEDs and it is low when not being driven with data. You can see that here:

If you're eagle-eyed you might have spotted a capacitor as well. I got this Arduino Pro free because it had a manufacturing fault and I repaired it using an old capacitor that I'd desoldered from the control board of a dead toaster. In that photo the Arduino Pro is connected via an FTDI cable for programming.

The other slightly tricky thing with this project was getting the timing of the serial protocol right. The simple serial protocol uses alternating high/low pulses of 20µs and 10µs (or low/high). In protocol.cpp I've made use of C #define statements to inline code for speed and also third-party code for fast changes to the I/O ports and accurate delays.

When working on this I used the Salae Logic analyzer to view the actual serial protocol in action. Here are two screen shots. The upper one shows the standard GE controller sending the initialization packets to the each of the LEDs in turn (with a gap of 40ms between them), the lower one shows a zoom into a specific packet being sent.

Finally, here's a video of the complete unit running through a simple "Hello World", followed by a few facial expressions and finishing with a "Thanks GE" for such a nice hackable string of Christmas lights.



PS If anyone from GE is reading this... how about making a 220V version of these? All you need to change is the wall wart to one that does 110-220V and you'd have all us Europeans interested in these lights.

PPS Other Arduino-based projects you might enjoy: GAGA-1: High Altitude Balloon Project and Cansole: Video games console in a can. Other non-Arduino projects: Revealing the secrets of the Ikea Lillabo wooden train set and Building a 'Ponyo' boat.

Labels: ,

If you enjoyed this blog post, you might enjoy my travel book for people interested in science and technology: The Geek Atlas. Signed copies of The Geek Atlas are available.

11 Comments:

Blogger Mike said...

Incredibly frustrating that it's so hard to get these lights in Canada.

5:12 PM  
Blogger Ron Proctor said...

Congratulations on a fun build! Now all you have to do is make 42,624 more and link 'em together for a giant HDTV! :)

3:11 AM  
Blogger kamakazi said...

Wonderful idea. I love it. Incredibly frustrated though. I can't get your code to compile. I have a fresh install of the 1.0 environment and the MEGA ADK. Your code uses includes for WProgram.h and unfortunately I don't have what it is looking for. I believe as a result of the missing file, I'm getting compile errors stating that 'byte' has not been declared in face.h; 'byte' was not declared in this scope in protocol.h; 'byte' does not name a type in frame.h. I would love to make your code work on this controller so I can pass it off to my colleague. Any thoughts to what I am missing?

5:25 PM  
Blogger kamakazi said...

Wonderful idea. I love it. Incredibly frustrated though. I can't get your code to compile. I have a fresh install of the 1.0 environment and the MEGA ADK. Your code uses includes for WProgram.h and unfortunately I don't have what it is looking for. I believe as a result of the missing file, I'm getting compile errors stating that 'byte' has not been declared in face.h; 'byte' was not declared in this scope in protocol.h; 'byte' does not name a type in frame.h. I would love to make your code work on this controller so I can pass it off to my colleague. Any thoughts to what I am missing?

5:26 PM  
Blogger kamakazi said...

Wonderful idea. I love it. Incredibly frustrated though. I can't get your code to compile. I have a fresh install of the 1.0 environment and the MEGA ADK. Your code uses includes for WProgram.h and unfortunately I don't have what it is looking for. I believe as a result of the missing file, I'm getting compile errors stating that 'byte' has not been declared in face.h; 'byte' was not declared in this scope in protocol.h; 'byte' does not name a type in frame.h. I would love to make your code work on this controller so I can pass it off to my colleague. Any thoughts to what I am missing?

5:26 PM  
Blogger John Graham-Cumming said...

WProgram.h is part of the standard Arduino environment. I am using version 0022.

http://www.arduino.cc/playground/Code/Library#WProgram

6:06 PM  
Blogger kamakazi said...

JGC, thanks for the version tip... Version 1.0 has library compat issues. WProgram.h is now Arduino.h and the library has undergone many changes. I'm using 022 now and now I'm having different compile errors about multiple definitions across files. I'm googling to find the solution, but if you have any thoughts I'd love to hear them.

4:56 AM  
Blogger The World Is Not Enough said...

Fuck kamakzi, patients is a virtue!

7:58 PM  
Blogger Matt Smith said...

Trying to recreate this, but unknowingly put my 50th LED at the front of the bus instead of the end. I'm no programming expert, but am having a hard time trying to find out how to make fix the code to support it. I also wired them in rows vs diagonals, but I got them to initialize properly (aside from the one extra at the wrong end). Any ideas?

3:58 AM  
Blogger John Graham-Cumming said...

@Matt Smith: The order in which the lights are strung together doesn't matter because they are assigned their addresses when the power is turned on. In fact when I made mine I cut them all up and had a bag of them and took them out in some random order. All that really matters is that you get the electrical connection correct: i.e. +ve, GND and the data line.

10:44 AM  
Blogger Vinnie Vu said...

Since the Arduino Software has been updated to version 1.0, there has been a lot of compatibility issues with a lot of codes written in 022 or 023 simply because of library name changes and other changes.

If you would simply change your #include "WProgram.h" to:
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

It'll automatically detect the version and compile with the correct library.

Thanks for the inspiration!! I picked up twenty one boxes of lights!! You should see some ridiculous display up soon.
We referenced your code and added MSQEG7 to add audio and 7 segment equalizer.

Also, if ou use a cardboard and cut into a grid, you can get the lights to display more evenly.

5:17 PM  

Post a Comment

Links to this post:

Create a Link

<< Home