42 comments on “GE Color Effects Arduino Library

  1. 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 “.

  2. 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!

  3. It’s in the example sketch. I’ll start compiling notes and send you any errors/tweaks I find. Thanks!

  4. Pingback: Arduino + GE Color Changing Lights + new Library + printing PCB, please! | TATYANA'S COOKBOOK

  5. 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.

  6. 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.

  7. 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!

  8. Hey Paul, mind if I put the library up on GitHub with a friendly license (something like BSD)? Thanks for writing it!

  9. 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!

  10. 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.

  11. 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.

  12. 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.

  13. 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.

  14. 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!

  15. 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);

    }

  16. 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!

  17. 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);
    }

  18. 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!

  19. 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.

  20. /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?

  21. 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…

  22. Pingback: Arduino, Circular Linked Lists, and Christmas Lights | Gnewt's Blag

  23. 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—

  24. 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—

  25. 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

  26. Pingback: ToddFun.com » Blog Archive » G35 LED Christmas Light Review and Teardown

  27. 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—

  28. 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

  29. 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.

  30. 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.

  31. Pingback: ToddFun.com » Blog Archive » G35 LED Christmas Lights – A Simple Parallel Sync Hack

  32. 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—

  33. Pingback: Weekend Project: Web-controlled Christmas Lights with Node.js, Arduino, and Raspberry Pi | Gnewt's Blag

  34. I know this is an old topic on here but is there anyway to get a Arduino Mega to command 24 pins to come on all at the same time? I have 24 strands of 25 bulbs each. After writing the code as a novice, The lights have a 1/2 second delay from pin 1 to pin 24. If you watch pin 1 to pin 5, You cant tell but once you go from pin 1 to pin 10, You see it and you really see it from pin 1 to pin 24. Thanks in advance!!!

  35. Paul-

    Probably the easiest way is to use Direct Port Manipulation. Tronixstuff has a great tutorial on Arduino Port Manipulation. Basically you can change 8 pins simultaneously assuming they are on the same port. You would have to do this 3 times in series for the 24 pins. For example, on the Mega you could use Port A, Port C, and Port L – all 8 pins of each port are available on the 18×2 connector at the end of the board. Doing direct port writes in series will only add several microseconds of delay between the first and the 24th strand instead of hundreds of milliseconds as you are seeing now.

    Paul

  36. I submitted the following under the “contact” section of your website, but was unsure whether it was received, so decided to post here as well…

    Paul, I started playing with these lights last year after discovering them. My current project is a 46-light star (video here: https://dl.dropboxusercontent.com/u/91581855/20131105_203753.mp4). Anyway, I want to be able to fade lights from one color to a different color using your libraries. I don’t see a command that allows me to “read” what color any given light currently is, though. For example, I may have all the lights turn on to different random colors. Then, if I want to fade any given light to a different color, I need to be able to access what color it currently is to be able to fade it to the color I want it to be. With your libraries, is there a way to access the current color of any given light?

    Someone else (Mark Evans) did an implementation where he are able to fade the lights. I looked into his code and I understand how he does it, but I don’t understand how to adapt his code to yours. (FYI, I am an engineer, and know a fair amount about coding, but by no means am I a hard-core programmer that lives, eats, and breaths C++)

    I love these lights, and I love this project. It would add another level to the variations if I could get the lights to fade, though. Any help would be appreciated.

    Thanks,
    Ed DeWitt

  37. Big thanks to everyone for the work so far!

    Where is the current discussion for the code?

    In program_runner.h, switch_program_to, this line is being used:
    program_ = program_creator_(program_index_);
    but I think it should be this:
    program_ = program_creator_(program_index);

    Also, BIG FYI, TiconXmas example ignores any requests for new programs and generates its own random one. I started making my own manual controlled lights program using this example and got burned for a few hours of time.

  38. Has anyone yet extended the code do LED matrix (text/graphics) style displays? How many strands are addressable (time slice wise)? Or more precisely, how may X Y pixles can you realisticalay address given these timing contraints?

    Tweeks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>