After seeing this post last year about hacking GE Color Effects LED lights, I knew I had to get my hands on these. Basically, they are the most awesome holiday lights ever. They are pretty cool right out of the box, but with the protocol reverse-engineered, the possibilities are pretty much endless. It didn’t take long for an Arduino port to surface and over the past year people have made good use of the fully addressable nature of these strings. I ran out and picked up some of the last strings available last season just in case GE decided to not make them again and was happy to see they are on sale again this year.
I’ve been playing with them on and off over the past few months and they are almost ready to make their debut for this holiday season. In the process of creating software to control these light strings, I decided to stick with the Arduino platform since I’m pretty familiar with it now and it was quick and easy to implement. The original code and the Arduino port worked well, but I needed a more modular implementation of the light driving code. I ultimately created an Arduino library that simplifies the use of these lights. It is based on those original code examples yet neatly wrapped into a library. I wanted to share it in case others were interested in playing with these awesome lights.
You can grab the library here: GE Color Effects Arduino Library (or if you are using the 1.0 version of the IDE: GEColorEffects Arduino 1.0) As with any other Arduino library, un-zip the file into your libraries folder in your Arduino installation directory. I have included a simple example sketch as well. See this page if you need additional help. As I mention in the library source comments, you may have to tweak the timing due to the imprecise nature of the DigitalWrite function, but the timing provided works well on my boards. Have fun!
This looks great, thank you so much for building this!
Alright, I got it working! First thing I noticed was that I was getting an error on line 1, I had to change “=#include ” to just “#include “.
Was that an issue you discovered with my library or the example? If you found a typo in my code, please let me know so I can correct it. Thanks!
It’s in the example sketch. I’ll start compiling notes and send you any errors/tweaks I find. Thanks!
Pingback: Arduino + GE Color Changing Lights + new Library + printing PCB, please! | TATYANA'S COOKBOOK
I published an article here which takes this to the next level with not only Arduino code which controls the lights but circuits for controlling several strings at once and a higher level programming language for controlling the lights along with an emulator on the PC for testing your light sequences. http://www.codeproject.com/KB/system/GELights.aspx
Also a point to note I found the timing needs to be tuned depending on the Arduino model you are using. The 6 microsecond pause is correct for the Arduino Pro but other models may need different timing. I explain this in my article.
Thanks so much for this library… it’s super easy to use. Having it available makes that step of cutting the wire on a perfectly good set of $70 xmas lights a little easier to justify to yourself…
I’m finding, though, that I’m losing contact with the end of my string of lights sometimes. If I hook back up the original data line (I always use the original +5 and ground) the end of the string will still remain dark unless I leave things unplugged for a few minutes. And it seems if I run my program for a longer amount of time that it’ll start to glitch more and more. Is this the timing problem I’ve read about here and elsewhere? I’m using an Uno if that makes any difference.
It probably is a timing issue. I used the standard DigitalWrite and delayMicroseconds to drive the data line. This is nice because it uses the built-in routines but, unfortunately, doesn’t create very accurately timed signals. I know I and others have seen that you have to play with the delays to reduce the glitches and it can vary from board to board. I have considered moving to a different method for the timing, like using other delay libraries or direct port writes. I’ll experiment with that and put up a new version of the library if it works better. For the accumulated glitches over time, I think the stock controller may set the color/brightness once and only send new commands when something needs to change. With the Arduino loop, it’s sending the same command over and over until the color/brightness changes. Again, this is all still a work-in-progress for me so I’ll play around with that as well. If you or others have any suggestions/improvements to this library or its use, please comment. Thanks!
Hey Paul, mind if I put the library up on GitHub with a friendly license (something like BSD)? Thanks for writing it!
Sure! Go right ahead – just send me a link or leave it in the comments. That’s a great idea – would the user community be able to collaborate on it then? That was really my whole motive – put things in motion and let other (smarter) people improve on it for everyone’s benefit. Thanks!
Check out https://github.com/sowbug/G35Arduino. Yes, anyone can fork it on GitHub and do whatever they want with it. If you’re interested in reviewing patches/pull requests, I’d be happy to make you a project owner (or fork it and maintain your own). I’ve verified that this version builds in the Arduino IDE, but I haven’t gotten it hooked up to real lights yet.
One more thing, Paul: I renamed the library G35Arduino, and the main class G35, to avoid any trademark hassles with “GE” and/or “Color Effects.” Not the most clever name, I admit; if you have something better, please suggest it.
While looking for a better way of timing out the pulses for the strings, I came across a library called DigitalWriteFast. It promises the speed of direct port manipulation with the familiar syntax of DigitalWrite. I’m going to experiment with calls to that in my library and see if it helps. The goal is to have perfectly timed 10, 20, and 30uS pulses. You can find it here: http://code.google.com/p/digitalwritefast/ If someone else tests it out, please leave a comment if it helped at all.
This afternoon I enhanced the stuff on GitHub to include a reasonably functional clone of the 14 programs included with the stock controller. It’s technically just a clone of the first program (the one that runs through the other 13 in sequence) because I don’t plan to hook up a wireless transceiver for the remote control. I did this code mostly as an exercise to make sure I understood the quirks of the hardware. For the ColorNode project, it’d be a nice proof of functional equivalence (not that anyone needed convincing). The project remains at https://github.com/sowbug/G35Arduino.
Paul, what an awesome beginning for an effects library! I had been looking for a good framework to settle into for the effects I create, and this does the trick very well. As others have mentioned, the timing of the pulses is crucial. I had lots of timing variability when first trying this library and couldn’t seem to tweak it out in the delay values. I would lengthen the value and some pulses would still be too short while some would be too long.
What I found is that the looping structure, << bit-rotates, and function calls appeared to be introducing enough code overhead to affect the timing from one pulse to another.
My solution was to adopt a piece of code Richard posted in Scott's blog…
http://scottrharris.blogspot.com/2010/12/controlling-ge-color-effects-lights.html?showComment=1317067297100#c2687789334371351574
It's not pretty from a code-size standpoint, but from a timing standpoint, it generates very consistent pulses because every pulse uses the same code structure with the same exact code overhead.
Once I replaced the set_color() function code with Richard's code and tweaked the millisecond values, the results were very consistent from pulse to pulse.
I hope this helps others out there. I'm looking forward to integrating DigitalWriteFast() into this code too, as it may further refine the pulse accuracy.
Thanks again for an awesome library Paul!
Here is my new set_color() member function if anyone wants to drop it in:
// these are the delays that worked for me (I followed Richard’s lead and used 40uS for the end instead of 30uS
// (I’m running a Teensy 2.0 sporting an Atmega32U4 running at 20MHz)
#define DELAYLONG 25 // should be ~ 20uS long
#define DELAYSHORT 11 // should be ~ 10uS long
#define DELAYEND 40 // should be ~ 30uS long
#define ZERO(pin) digitalWrite(pin,LOW); delayMicroseconds(DELAYSHORT); digitalWrite(pin,HIGH); delayMicroseconds(DELAYLONG);
#define ONE(pin) digitalWrite(pin,LOW); delayMicroseconds(DELAYLONG); digitalWrite(pin,HIGH); delayMicroseconds(DELAYSHORT);
void G35::set_color(uint8_t led, uint8_t intensity, color_t color) {
uint8_t R, G, B;
R = color & 0x0F;
G = (color >> 4) & 0x0F;
B = (color >> 8) & 0x0F;
digitalWrite(_pin,HIGH);
delayMicroseconds(DELAYSHORT);
//led
if (led & 0×20) { ONE(_pin) } else { ZERO(_pin) };
if (led & 0×10) { ONE(_pin) } else { ZERO(_pin) };
if (led & 0×08) { ONE(_pin) } else { ZERO(_pin) };
if (led & 0×04) { ONE(_pin) } else { ZERO(_pin) };
if (led & 0×02) { ONE(_pin) } else { ZERO(_pin) };
if (led & 0×01) { ONE(_pin) } else { ZERO(_pin) };
//Brightness
if (intensity & 0×80) { ONE(_pin) } else { ZERO(_pin) };
if (intensity & 0×40) { ONE(_pin) } else { ZERO(_pin) };
if (intensity & 0×20) { ONE(_pin) } else { ZERO(_pin) };
if (intensity & 0×10) { ONE(_pin) } else { ZERO(_pin) };
if (intensity & 0×08) { ONE(_pin) } else { ZERO(_pin) };
if (intensity & 0×04) { ONE(_pin) } else { ZERO(_pin) };
if (intensity & 0×02) { ONE(_pin) } else { ZERO(_pin) };
if (intensity & 0×01) { ONE(_pin) } else { ZERO(_pin) };
//Blue
if (B & 0×8) { ONE(_pin) } else { ZERO(_pin) };
if (B & 0×4) { ONE(_pin) } else { ZERO(_pin) };
if (B & 0×2) { ONE(_pin) } else { ZERO(_pin) };
if (B & 0×1) { ONE(_pin) } else { ZERO(_pin) };
//Green
if (G & 0×8) { ONE(_pin) } else { ZERO(_pin) };
if (G & 0×4) { ONE(_pin) } else { ZERO(_pin) };
if (G & 0×2) { ONE(_pin) } else { ZERO(_pin) };
if (G & 0×1) { ONE(_pin) } else { ZERO(_pin) };
//Red
if (R & 0×8) { ONE(_pin) } else { ZERO(_pin) };
if (R & 0×4) { ONE(_pin) } else { ZERO(_pin) };
if (R & 0×2) { ONE(_pin) } else { ZERO(_pin) };
if (R & 0×1) { ONE(_pin) } else { ZERO(_pin) };
digitalWrite(_pin,LOW);
delayMicroseconds(DELAYEND);
}
What’s the correct value for this line:
B = (color >> ??) & 0x0F;
My browser has a smiley face where the ‘??’ is! Assuming it is supposed to be an 8?
Thanks!
Hi – There’s nothing like being prepared! So with plenty of time until Xmas 2012 – I’ve shipped (at great expense) 2 sets of 50 over here to the United Kingdom.
The power socket won’t work, so I’ve used my own power supply (5V / 5A) which worked fine with the standard GE controller.
I’m running your 1.0 library and example on my Arduino Mega 2560 (IDE 1.0). It mostly works as expected, except after a random number of calls of lights.fill_color, random bulbs will be the wrong color. Sometimes it just seems like a bulb has missed an update (i.e. it’s stays the last color), but also they can be a random color.
It seems like it can affect any bulb (i.e. not necessarily ones near the end.)
Do you have any ideas on what the problem is?
Finally, it would be nice if people could post their sequences…
As I’ve only got myself up and running today, so don’t expect much from my first meager offering
void loop() {
//”Red White and Blue” – simple flash between red and white, then blue and white
lights.fill_color(0, lightCount, DEFAULT_INTENSITY, COLOR_RED);
delay(1000);
lights.fill_color(0, lightCount, DEFAULT_INTENSITY, COLOR_WHITE);
delay(1000);
lights.fill_color(0, lightCount, DEFAULT_INTENSITY, COLOR_BLUE);
delay(1000);
lights.fill_color(0, lightCount, DEFAULT_INTENSITY, COLOR_WHITE);
delay(1000);
}
I’ve found that if you call either set_color or fill_color very quickly in the loop addressing the same bulb(s) with the same color, they have a tendency to glitch and either go to some other unintended color or mysteriously light up some other random bulb. What I’ve been doing is setting the colors once and then keeping track of their state. The bulbs will hold the color even if you only send the command once. Now, for chase sequences or other light programs where the bulbs are changing color often, it doesn’t matter so much. It seems to have something to do with repeatedly setting the same color/brightness to the bulb(s). Have fun with your new lights!
Thanks Paul! Glad to know that it happens for other people, and is ‘normal’. Over the next few months I hope to get some decent sequences, which I’ll post.
/https://github.com/sowbug/G35Arduino g35.h and g35.cpp does not match your arguments. can you clearify the correct libraries to compile this correctly?
Thanks for the library…it’s awesome! My 12 y/o boy has been asking to learn Arduino because he decided he wanted a career making digital devices, but he tired of manipulating the blinking LED on the board pretty quick. I was looking for something easy and juicy to excite him deeper into code, and this light show has blown his mind
Thanks for the notes on communication timing. My recent UNO had a high % of light control errors until I sped things up some, now nearly flawless and definitely impressive. Thanks again…
Pingback: Arduino, Circular Linked Lists, and Christmas Lights | Gnewt's Blag
Thanks for publishing your library. I reworked the LED code to support fading and effects transitions. I also am starting to do audio effects dsp processing to make the lights react to music. i put my code on github for all to use as they see fit. https://github.com/pianoman19372/g35-color-effects-leds
Hi all, please see my new light programs for Sowbug’s Arduino library
https://github.com/MarkEMarkEMark/G35-MEO-Programs
The are based on other lighting technology, converted for G35 with my own tweaks, extra parameters etc.
I had trouble with intermittent errors using the library. Suspecting timing, I observed the pulse train on my trusty Tektronix 475A and saw that the timing was indeed rather glitchy.
The total fix came when I shut off the Arduino’s interrupts during generation of the pulses for each individual packet. For example…
noInterrupts();
lights.set_color(i, DEFAULT_INTENSITY, COLOR_WHITE);
interrupts();
…works perfectly 100% of the time.
Just thought I’d share this in case anyone else has encountered the problem.
Cheers,
Rob—
OK, a couple more breakthroughs!
1) Costco put out the GE Color Effects 50′s Sunday for ~$67.95. There are several sets liste on eBay right now at about $100, because people assumed they were discontinued, hence scarce commodities. Nope!
2) I have three strands hung and ready to wire… one of which will require a cable for power and data that’s over thirty feet from my controlling Arduino. That seemed it might be a challenge, given our 10 microsecond pulse times… and indeed it was. I decided to try Cat5 nework cable, using four strands for ground, three for the +5V, and one for data. At five feet with a standard GE controller, no problem. Toss on a twenty foot cable, FORGET IT! Four or five bulbs responded, that’s it. My scope showed the pulse risetime was like a bananna… about ten microseconds of lazy, curved pulse rise.
I solved it! Add a 75451 open-collector line driver at the controller end, and a 470 ohm pull-up resistor at the far end of the cable, and voila, perfect power and digital control at the end of a FORTY FOOT Cat5 cable! I will publish some pictures and a schematic later, but that’s my solution to running GE Color Effects 50′s at a distance.
Cheers all,
Rob—
Hi Rob,
Your line driver idea is excellent! I need to run eight strings, the longest of which is a 70′ run. Do you think that the line driver with the 75451 and pull-up resistor could run that distance? If you have a schematic, please post it.
Thanks!
Tom
Pingback: ToddFun.com » Blog Archive » G35 LED Christmas Light Review and Teardown
Tom,
Before I forget: I’m running four strings of varying lengths with four of the GE wall-wart supplies, no opto-isolators, all grounds tied together. It works because for safety reasons, the wall warts are not ground-referenced to the power line or anything else: They’re floating (so long as they’re not defective, anyhow). So in my opinion, there’s no reason not to just tie the grounds together, and run the signals directly from the Arduino to the strings. That’s what I’m doing, no problem. (Your mileage may vary, so reach your own conclusions and don’t blame me if you roast anything. Any wiring error WILL smoke your Arduino.)
It turns out that the 75451 is completely obsolete and unavailable. The simplest part I can find for this is a 7406 hex inverter with 48mA open-collector output. The inversion should be no problem: If you just go into the GEColorEffects.cpp driver and swap all of the HIGHs and LOWs, it should all come out right. I don’t know how to post a schematic to this board, but the circuit is blessedly simple: The pinout of the 7406 is:
pin signal
1 in-1
2 out-1
3 in-2
4 out-2
5 in-3
6 out-3
7 ground
8 out-4
9 in-4
10 out-5
11 in-5
12 out-6
13 in-6
14 +5 VCC
So you just power the chip from the Arduino’s +5 and ground it to GND. Hook six outputs from the Arduino to the six inputs. Wire each output from the chip to a data line which runs out to a string. At the string, where you hook your Cat5 (or whatever) to the leads from the first bulb, add a 470 ohm pull-up resistor between the data line and the +5 line, and VOILA, you’re running your GE Color Effects from a heck of a long way away.
By the way, the Cat5 idea I wrote about above is working perfectly, although I’m going only 40 feet on my longest run. I did check the data signal at the far end of the 40 feet, and it is razor-sharp, so I’ll bet it works fine at 70 feet. (The power, on the other hand, might be a bit of a problem with all of that cable resistance. You might want to spend the money for some heavier speaker ZIP cord to get the power out there).
I got the crimper needed to put on RJ45 plugs, and the push-down tool needed to punch wires into the matching Ethernet-style RJ45 jacks, so my whole rig plugs together neatly. It will be a breeze to take down and put up again around next season.
I am going to try to finish my modified library tonight, to give me light addressing commands which take only a bulb number from 1-187 and do the string un-scrambling automatically. If I’m happy with it, I’ll post it. (I’m going to do just one bulb at a time this year).
Cheers, All!
Rob—
Rob,
Can you explain a little more about your use of CAT5 for power? I tried using CAT5 on some 20′-30′ runs but am experiencing high voltage drops. I used 3 solid strands for ground, 3 striped for +5V, and 1 for data (leaving one unused). And I got nothing… No light. I measured only ~.5V between my bundles of solid strands and striped strands at the connection to the light string. I’m wondering if the jacks I used have load resistors between the pairs (that would explain the significant drop).
Jerry
Nevermind. Silly me. I had the polarity switched. Also discovered I need to use 4 pairs to reduce the voltage drop. I looks like I’ll be running to CAT5s per light string so I can send the signal too. Blah.
I’m happily running 30-foot strands of single Cat5 for my strings, four ground, three power, one data, with the open-collector driver at the Arduino, and a 470 ohm pullup at the start of the strings. I’m sorry but I did forget to mention that my strings are all cut to exactly match the runs of rain gutters and eaves at my house, so my current drain will be commensurately lower. My longest run is powering 30 bulbs no problem. Here’s a video of my fairly-lame program as of last night: http://youtu.be/iIHYuZD3Q7w
I haven’t had much spare time to work on the code… maybe an hour or two total, and most of that was just getting it to work properly. I never have any glitches any more. I do plan to publish my work, especially the stuff in the library, after I get an evening to polish it up.
Pingback: ToddFun.com » Blog Archive » G35 LED Christmas Lights – A Simple Parallel Sync Hack
I ended up doubling up my CAT5 cable, so I now have 3 pairs power, 3 pairs ground, 1 strand data, 1 strand unused, and 1 pair in reserve.
I’ve based my programs on Keith’s work here (http://www.codeproject.com/Articles/279657/Simulating-and-controlling-GE-Color-Effects-Lights). I’m still working out some of the more difficult sequences (diagonal and round wipes). I’ll try to post a video once I have everything up on the house this weekend.
Glad to hear CAT5 is working out, after a fashion. Just bought a 30 Amp 5-volt supply for $30 (shipping included) from an LED Sign Guy on eBay. I’m looking forward to seeing if I can tweak up the regulator to 7+ volts to overcome the loss in a single strand of CAT5. How are you guys doing with the cable driver circuit(s) I’ve proposed (and which I am using)?
Rob—