Hacking G-35 GE Christmas Lights

Introduction

In 2010, I found an article about hacking the Color Effects GE G-35 string set 50 LED lights on the web.  I don’t recall if it was on LifeHacker.com or maybe even hackaday.com. Regardless, most of the hacking information was found by deepdarc.

These articles intrigued me enough to go out and buy a couple of light sets and an Arduino to control them.  (Several friends had been experimenting with the Arduino board — now, my turn!)  By the time I read the articles and was motivated, the lights were out of the stored (2010).  Now, 2011, lights are in, I bought a couple of strings, and have been working on programming them (from the advice and information found online).

My purpose in blogging this is to share my experiences, and hopefully help a fellow science enthusiast or two “realize the dream!”

Hack Information Sources

References for hacking G-35 lights include:

There are other references online.  Just google something like “hack costco GE christmas lights” and you will find lights flashing to music and scrolling marque signs made from these lights.

Special thanks to “Michael D.” for his post on Scott Harris’ blog referencing the delay_x.h delay library that can be found here:  http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=665&item_type=project (registration required)  And thanks to Hans-Juergen Heinrichs for writing the library!

Hardware

I bought two strings of lights, “Color Effects, G-35 string set 50 LED lights” from Costco around early September 2011.

I bought the Arduino Uno board from adafruit.com.  I got some extras with the board — a few LEDs, a 9v power supply, some transistors, and more.  (I plan to do a little more experimentation after Christmas!)

In addtion to the lights and Arduino, I bought miscellaneous wire, connectors, switches, and a box to mount the whole mess in.  Orvac Electronics.  🙂

The key to the GE lights protocol can be found on the deep darc blog here.  I won’t go into the details except to note that the ground wire on the GE lights has a tiny rib on the insulation, making it easier to to find the ground wire.  Note that deep darc’s blog has a picture identifying the positive/ground/control lines here.

In brief, the light string comes with a 5v power supply (wall wart), and an inline controller.  The inline controller can be replaced with your controller of choice in order to make the light string do your bidding.  I’ve chosen the Arduino Uno.

The5v power supply plugs into 120v AC and outputs 5v DC.  The 5v DC goes into a little green box (inline with the GE lights).  Out of that little green box comes three lines — a ground line, a signal line (“line level” — but I’m not a h/w guy), and a 5v DC line.  The 3 lines “daisy chain” down to each bulb in the string.

Here’s a picture of the box I mounted it in.  I used Molex connectors on the light strings so that I could plug in the original controllers if I wish.

Clockwise from the upper left, note: power switch, green controller that came with light string, 5v DC power supply, lower right, second power supply for second light string, second green controller, lower left note the USB cable plugged into the Arduino (can be removed when I “deploy” this outside with lights), lower left corner has the Molex connector mounted that plugs into one light string, left is the Arduino board with two ground wires (one from each light string), and two control lines (one going to each light string), and back to upper left, the power cord.  Note in the very center, in the bottom of the pile, a 9 VDC transformer for the Arduino.  The yellow electrical “wing nuts” tie in the 120 VAC of the 3 transformers and connect to the power switch.  The dowel traversing bisecting the box simply keeps the transformers and controllers from sagging down into the Arduino when mounted vertically.

Wiring

To wire in the Arduino, you need to:

  • disconnect the GE lights control line from the light string
  • connect the ground from the light string to the Arduino ground
  • connect an Arduino output pin to the control line going to the light string (e.g., pin 2 or pin 4)
  • keep a 5v power source going to the light string (both positive and negative lines)

I didn’t use any pullup resistors, transistors, etc. in my wiring.

Here is my cheesy hand-drawn quickie wiring diagram.

If you look at the photo of my box above, the two coils of wire are the wires between the “connectors” in my hand drawn diagram.  I added these connector/plugs so that I could easily bypass my wiring and use the controller that came with the lights.  Also, looking closely at the photo, you can see two ground wires (one from each of my 2 light strings) connected to the ground on the Arduino, and I think you can see two control lines (yellow) connected to pins 2 and 4.

Another thing I found in my research was that if you control multiple strings of lights, and you have to run a signal line from an Arduino for a long ways, there may be some signal attenuation and some kind of signal boosting may be required.  Read up on the http://doityourselfchristmas.com/ site for details on this.

Software

My goal in writing software for the GE lights was to get a fun set of pleasing light sequences for the GE lights hanging on my house during Christmas.

You are welcome to reuse and modify any of the code I post as long as you leave my name in the “credits”.  Find a link to the code in the references section at the top of this blog post.

While deep darc shows a lot of information about the hardware and timing of the lights, I didn’t find any software on his site to be useful for me.  My best s/w example came from Scott’s blog here.  While this was a good place to start, I often found an occasional bulb to not be addressed correctly.  A comment there by “Michael D.” led me to a delay_x.h library that provided more accurate timing.

Here’s a picture of my test setup.  I mounted the bulbs on a small sheet of plywood to more easily visualize the bulb sequences.

Low Level

It turns out that when you use the Arduino delayMicroseconds(num_us); function, you won’t get a consistent delay.  Interrupts are enabled during this call, and the Arduino does indeed interrupt.  I believe this lead to my inconsistencies in writing to the bulbs.  I switched over to the delay_x.h library.  Those calls don’t enable/disable interrupts.  So, I was able to disable interrupts, write a bit stream to the lights, then re-enable interrupts, resulting in consistent data and timing going to the controller.

One other thing that I attempted was to have the controller write to two strings of lights simultaneously.  That would reduce the overall time to update all of the strings of lights.  I was unable to accomplish this without timing problems.  It seems there was some kind of problem when I would write to two Arduino pins at the same time.  There may be remnants of these functions in the code if anyone wishes to try this.  I figured it was only decorative lighting — I didn’t have to sweat the details if it took slightly longer to refresh two light strings.

Medium Level

Once I got the timing down, I concentrated on core functions for writing the string of lights to the controller (based on Scott’s code).  I created structures representing the light string hardware (a list of bulbs, each bulb with an address, intensity, and red/green/blue value).  I wrote functions that would take those structures and write then to the controller.

Additionally, I created a model whereby my main Arduino loop() method would come back to the same place for delays.  This makes it much easier to do any kind of switch polling or other task during times when the light strings are not being updated.

High Level

On top of the “medium level” software representing the hardware (light string), I created an abstraction whereby I could write fairly high level functions to set light information, without having to deal with the details of forward/reverse addressing and multiple strings.  I was able to boil this thing down to where I could write a new light sequence in only a few lines of code.

I adopted a model whereby a particular light sequence is like a measure in a song.  However I never really got to the point of creating multiple lists of measures, with the exception of a “demo” list (shorter sequence, to show my friends), and an “operational” list for when I put my lights on my house.

Software Configuration

I’ve written my software in such a way that it will support one or more strings of lights.  The number of bulbs is configurable.  Those lights can be configured to be addressed/written either forward or in reverse.  The Arduino pin number is configurable.  There are also hooks in for debugging.  This includes writing to the serial port, and flashing the onboard LED to ensure the Arduino is still “pulsing” through the light software.

My “namespace” is simply to prefix my functions and global variables with “xm_” (For Xmas.)

In xm_lights.h, you can set the number of light strings, bulbs per string, Arduino output pins, and light string direction.

// The number of strings of lights used in the project.
#define XM_NUM_LIGHT_STRINGS 2

EXTERN uint8_t xm_light_string_pin[] // Arduino output pins for all strings.
#ifdef DEFINE_GLOBALS
= {2, 4}
#endif
;

EXTERN uint8_t xm_light_string_direction[] // Light string bulb address direction.
#ifdef DEFINE_GLOBALS
= {XM_REVERSE_DIRECTION, XM_FORWARD_DIRECTION}
#endif
;

You can configure which light sequences are displayed by modifying xm_measures.h.

EXTERN xm_measure_t measure_list_demo[] // Measures (of light sequences).
#ifdef DEFINE_GLOBALS
= {
{xm_measure_fill_to_blue, 2000},
{xm_measure_rgb, 2000},
{xm_measure_random, 150},
{xm_measure_shift_rt_fill_white, 100},
{xm_measure_random_fade, 25},
{xm_measure_fade_to_color, 200},
{xm_measure_fill_slide_loop, 25},
{xm_measure_fade_slide_loop, 25},
{xm_measure_red_green_alt, 500}
}
#endif
;

You can add “measures” (light sequences) by adding them to xm_measures.c.

Summary

Well, mostly I wanted to blab a little, and post my code in hopes of helping anyone else interested in a fun “light” hardware/software combined project.  Go ahead and post any questions and I’ll do my best to respond.  I didn’t have time to completely discuss the s/w but sometimes you just have to call it “done”.

(Leave me a note below!)

This entry was posted in Uncategorized. Bookmark the permalink.

90 Responses to Hacking G-35 GE Christmas Lights

  1. Hey, could you post a link to the delay_x.h library? I was never able to track it down.

  2. mevans77 says:

    The delay_x.h library can be found here http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=665&item_type=project and is linked in the references above. You have to register for an account on avrfreaks to access this link.

    Your other option is to download my code (link in reference or currently here http://dl.dropbox.com/u/83025/xm_lights.13-Nov-2011.zip). I’ve included it in my zip file with permission from the author.

    As I noted above, the key to my timing success was to disable interrupts (cli() function) while writing the bulb data (with the non-interrupt-enabling delay_x.h code), then reenabling interrupts (sei() function).

  3. mwoodward says:

    I really appreciate the work you put in to refine the timing sequences. That is the key to getting the lights to behave properly.

    Just one question though…does the code that is in the zip file you provided, successfully compile for you? I’m getting “multiple definition” errors, on all of the xm_measures functions. I know that it’s happening because they are all using the the lower case “extern” keyword. Therefore, the functions have not been declared anywhere in the project.

    How are you getting this to compile successfully, without the the functions in xm_measures.cpp being declared anywhere?

  4. mevans77 says:

    The code does compile for me (Mac OS X 10.6). (Also for a friend of mine, WinXP.) I’m using the Arduino environment. 5 files are part of the project — delay_x.h, xm_lights.h, xm_lights.pde, xm_measures.cpp, and xm_measures.h.

    the xm_measures.h file declares the xm_measure_*() methods as extern so that the measure_list_* arrays have visibility to them (when included in xm_measure.cpp). In the xm_measures.cpp file (after including xm_measures.h), we should simply end up with an extern declaration for the functions defined within the xm_measures.cpp file, above the definitions of the functions.

    You could post your error messages here and I can take a look. Or you could try commenting all xm_measure_* functions except one or two and see what kind of errors you see.

    Did you make any code mods? xm_measures.h should be fairly robust if included multiple times (with XM_MEASURES_H “skip code if already defined”).

    • mwoodward says:

      I figured it out…I was adding it to the “libraries” directory, so the IDE was processing it as one.

      Man, that’s rather embarrassing…*laffs*

      It didn’t hit me until I got home and almost did the same thing again. While I’m here, I guess I can ask another quick question. How do the predefined measures behave, if there is only one string connected?

      • mevans77 says:

        If you change:
        #define XM_NUM_LIGHT_STRINGS 2
        to 1, they will work just fine. (All the functions operate in terms of this define.) You may wish to modify the pin definition in xm_light_string_pin and perhaps the string direction in xm_light_string_direction (all described in blog above). The only one that will be a tiny bit strange are ones called xm_measure*segment*() (one or two functions). These allow you to write bulb colors in segments. My house has lights across the front, down the side, up the garage, down the garage, etc. These functions allow me to have each segment a different color (then change colors). If you set the seg_index array to values <= 50, then these will work fine with a single string of lights.

      • ND915 says:

        @MWOODWARD – I’m new to all this, found some good stuff and will be playing with it a lot more. However, i get errors also and looked as to what “other” way there would be than to extract into libraries… i cannot figure it out, i’m a noob i know but help me out if you will, i would love to see some more peoples code and cannot figure out how to get it working.

      • mevans77 says:

        It’s been over a year since I programmed my arduino, so I’m a little rusty. I know there are lots of arduino help websites. Perhaps searching the net for your specific error may provide a solution.

  5. Jason says:

    Could you please post a diagram or more pictures of how you connected everything?

    • mevans77 says:

      OK. I threw in my “cheesy hand drawn” diagram along with a little clarifying text and a little re-write of the wiring section. I hope that helps you visualize the wiring. It is really pretty simple. No extra components.

  6. Lord Hotwing says:

    Should the code just work “out of the box”? Or is there something I need to do? I uploaded to my Arruino Demimila, connect as per the digram, but I cannot get the lights to do anything. If I connect up to the signal line, the bulbs immediately work. I have connect th ground, and am using pin 2. (also tried 4) What am I missing if yo have an idea? I did test my board by uploading the blink test program, and my LED started blinking as expected.

    At a loss,
    John

    • mevans77 says:

      I would set the number of strings, pin, and direction, and it should work. Others have used the code successfully. To track this down, I would turn on the debug flag and activate the serial output through the USB to see if the program is cycling. The Diecimila seems to have the same clock 16mhz and just less memory. If that doesn’t work, I’d google for differences between the boards. Perhaps someone else has an idea.

      • John says:

        Well, bought a new Uno. uploaded the code and it worked immediately. You did some great work here, I have been playing with the different schemes and it is flawless. Thank you!
        john

  7. Jay says:

    Have you ever been able to locate any information about running these sequences to music? I would like to step mine up a little more but haven’t been able to sort out the sync issues.

    • mevans77 says:

      I searched around the net quite a bit last year when I did my hack. I recall finding a program or two that did some music coordination/synchronization. It was a little more ambitious than the time I had available. Plus, I wasn’t planning on broadcasting or playing music at my home. Google around a bit and you’ll likely find it. I don’t recall if it was directly adapted/ported to the G-35. It might take some additional programming to get the two working together. Post back if you come up with a solution!

      Regards,
      Mark

    • I’ve done some work adapting my relay synchronization software to drive G35 strings. Blogged about it here: http://austinlightguy.wordpress.com/2011/09/11/driving-ge-g-35-light-string-with-diligent-uno32/ There are links to download the software in the posts.
      The software urns on a PC and sends serial commands to the Arduino. This works, but I’ve continued to have problems with “glitchiness”, especially with my “grid” version which basically renders 24×12 bitmaps to a grid made of 6 strings. I believe (but am still not sure) this is probably due to the Arduino not having enough horsepower to service the serial port while keeping up with the G35 protocol timing. Using a much faster Digilent UNO Arduino compatible helped a lot, though. The new DUE might also be good. If I have time this year, I want to create a version that downloads the bitmap matrices to the Arduino, then simply sends commands and timing signals to it while running the sequence. This will dramatically reduce the serial port usage, but will require an Arduino or compatible with a LOT more SRAM. Realistically, I’m not sure I’ll get to this in time for Xmas this year.

  8. KC says:

    What’s the likelihood of someone who loves to tinker and who has a slight electronic aptitude (but without programming experience) being able to do something like this? Really… you won’t hurt my feelings. I don’t particularly care for the 14 pre-programmed settings and would love to change it!

  9. mevans77 says:

    Well, if you are not easily discouraged, and don’t mind digging into some technology a little deeper, and if you like the sequences that I’ve programmed, and you are OK with the idea of changing a few parameters in the code, and handy with clipping/stripping/joining a few wires, then you have a good chance of succeeding. You could buy an Arduino board, connect it to your computer, connect a resistor and diode, and run through a couple of tutorials. If you can get the LED to blink as per the tutorials, then you have a very good chance of getting this to work. You could get the Arduino and a few parts for about $50. You could also download my code (above links) and look through where I program the sequences, to decide if you are ambitious enough to try a little C programming to change those sequences.

    Do you have any family or friends that have some spare time to dig if you get stuck?

    And beware, this will take far more time than you imagine!

    (I may be biased on the optimistic side because I’ve done it and I think it is neat. And I enjoy sharing it with others. I have fiddled with electronics some — that was the scary part for me, and I have a lot of programming experience — but much of that has been done for us.)

  10. eEric says:

    I have really enjoyed playing around with these lights thanks to your code. I have modified a few of the existing sequences and have really struggled to write my own. As of late I have been searching for a way to develop a sequence in Vixen for use with these lights. I managed to find a python script that parses the .vix file and converts to a .cpp file which can be included in an arduino sketch. I am unsure at the moment how to implement this code or if it will even work. Do you think it is possible? I can give more details if interested. Also, I have noticed tha two of my bulbs seem to dim and flicker for the colors green and magenta. Would this have something to do with color intensity or is it possible I have an address issue? Running two 36 strands on pins 2 and 4. Number of strings set to ‘2’ and XM_NUM_BULB_ADDR set to ’36’. Thanks.

    • mevans77 says:

      I’m glad you were able to use my code. (It’s fun for me to see others get some enjoyment out of it!)

      I’m not familiar with Vixen. I googled it and it looks like a very powerful tool. The issue would be, can Vixen control the G-35 lights at a low level, or does Vixen need a “driver” to interface between the Vixen light controlling algorithms and the hardware. It is possible that Vixen publishes a driver interface so people can write what is essentially a G-35 to Vixen adapter driver. I don’t have time to do that. (However, looking around on google, it appears that the G-35 hacking continues strong this year!)

      Regarding your two dim/flickering colors — If you are seeing this when you set the whole string to a solid value, then the LED bulbs themselves may have a problem. I had one bulb that seemed to be missing its blue component, but at other times it worked correctly. “Flickering” may indicate a hardware problem if it occurs when you are not writing data to the string.

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

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

  13. jimnguyen07@yahoo.com says:

    So I purchased an Arduino Uno and downloaded the codes (thanks for that btw). I’m quite new to all this and would like to experiment a little more. I’m getting certain errors when trying to upload the sketches. One person above mentioned that they got an Arduino Uno and the sketch uploaded with no problems. Here are my errors…can you help me out?

    m1_index = rand() % XM_VBULB_SIZE; // Random bulb.
    ‘rand’ was not declared in this scope

    along with these errors:
    xm_measures.cpp:15:36: error: WProgram.h: No such file or directory
    xm_measures.cpp: In function ‘void xm_measure_random_fade()’:
    xm_measures.cpp:286: error: ‘rand’ was not declared in this scope
    xm_measures.cpp: In function ‘void xm_measure_random()’:
    xm_measures.cpp:306: error: ‘rand’ was not declared in this scope
    xm_measures.cpp: In function ‘void xm_measure_fade_slide_loop()’:
    xm_measures.cpp:703: error: ‘max’ was not declared in this scope
    xm_measures.cpp:704: error: ‘min’ was not declared in this scope
    xm_measures.cpp: In function ‘void xm_fade_slide_to_color(xm_color_t)’:
    xm_measures.cpp:722: error: ‘max’ was not declared in this scope
    xm_measures.cpp:723: error: ‘min’ was not declared in this scope
    xm_measures.cpp: In function ‘void xm_measure_fade_slide_segments()’:
    xm_measures.cpp:766: error: ‘max’ was not declared in this scope
    xm_measures.cpp:767: error: ‘min’ was not declared in this scope

    • eEric says:

      I know this is extremely late but I believe changing “WProgram.h” in xm_measures.cpp to “Arduino.h” will solve most of if not all your problems.

  14. Glen Maxwell says:

    i have the same “rand” not declared in this scope fault. i am not finding the “WProgram.h” to change. Help!
    Can anyone point me somewhere to do a “baby steps” sketch in my uno for the ge-35 lights, just a basic get me started kind of thing. i am just starting tyying to learn some programming.

  15. eEric says:

    Under the xm_measures.cpp tab, the second ‘#include’ statement is ‘#include WProgram.h’. Change it to ” #include Arduino.h”
    If you still cant find it you can use the handy dandy find tool (CTRL+F) after you have clicked on xm_measures.cpp tab.

    I don’t know of any other “baby steps” sketches other than the ones cited as sources in this blog.

  16. Charlie U says:

    Thank you SO much for your work. I started reading on this last year and finally got to realizing this on my own set of GE lights. It will take me a while to digest the code in order to add more sequences (it’s been more than 10 years since i touched C). Would you mind pointing me in the right direction? Say, if I wanted to add plain Orange (for the Halloween) color to be static, where would I start messing to combine the RGB colors of each bulb? Thanks so much again!

    • mevans77 says:

      Search for xm_measure_fill_to_red in xm_measures.cpp. Create one similar but for orange. Search for measure_list_operational in xm_measure.h. Create your own list. And set XM_MEASURE_LIST to it. You can have a single method in that list if you wish. Or you can add others like the fade to black.

      • Charlie U says:

        Thank you!
        Apparently you already had a predefined orange. I changed the RGB value to a desirable Halloweeny color and it worked out great!
        Is it safe to assume XM_MAX_RED is 255?
        Once again, many thanks.

      • Charlie U says:

        {xm_measure_fill_to_red, 2000}
        what is the value 2000 for? Tried messing with it, without much change. Perhaps it is not apparent for static colors.

      • Charlie U says:

        sorry, got it, its the delay between changes

  17. mevans77 says:

    Glad you got it working. Yes, the 2000 is the number of milliseconds wait before the next sequence is executed. the XM_MAX_RED value is defined in xm_lights.h as (0xf) so its value is 15. That’s the maximum value of the red LED in one bulb. I believe that the red, blue, and green values for each bulb are 4 bit values (thus 0xf which is 4 bits — all set to 1).

    • Charlie U says:

      thank you. I tried re-using and modify xm_measure_fade_to_blue() to create a fade-in and fade-out glow from brighter orange(XM_MAX_RED, XM_MAX_GREEN/10,0) to darker orange(XM_MAX_RED,XM_MAX_GREEN/20,0) and visa versa.
      The result was just a sharp switch from one orange to the darker orange, back and forth instead of fading.
      in the xm_fade_to function (sorry if this is wrong terminology)
      XM_INC(dest->color.green, XM_MAX_GREEN)
      does the above increment 1.5 to 1.6 or 2.5 or there are no decimals (or am I completely clueless) assuming XM_MAX_GREEN/10 = 1.5

      Hopefully this makes sense.
      Thanks again!

      • Charlie U says:

        and again, sorry. 15 values max like you said. too bad, the fade (from one color orange to another) is quite jerky with such a small palette. Can’t quite make it fade smooth and slow. I will do more reading on these lights.

      • mevans77 says:

        Each color (R/G/B) has a value from 0 to 15 and each bulb has an intensity from 0 to 0xCC (204). I found that changing the values of the RGB was more effective than trying to mess with the intensity. I found the intensity to not be very linear. So, to change a bulb brightness from off to full RGB brightness takes 16 steps (0 to 15). And, the XM_MAX_RED, BLUE and GREEN values — well you can really only have 16 values of each, so I wouldn’t spend much time dividing them by anything but 2 or maybe 4. Dividing by 20 quickly gets you to zero.

        With each method call in the table, you provide it with a number of milliseconds you wish to delay between each “step”. If you are fading a string of “max color” anything (say red), then it will step from perhaps zero to 15. So, if you specify a value of 1000/16 (62), that will step your lights from black to max red in 1000 millisec (1 sec). So specify in the table, something like this:

        {xm_measure_fade_to_red, 62},

        Each sequence method (e.g., xm_measure_fade_to_read) had an inherent number steps when reached, signals the caller to move on to the next method. So the following example:

        {xm_measure_fill_to_black, 0},
        {xm_measure_fade_to_green, 200},
        {xm_measure_sleep, 4000},
        {xm_measure_fade_to_red, 200},

        Would set all bulbs to black, then fade all to green in (200 * 16) ms, then delay 4 seconds, then fade them all to red in (200 * 16) ms. (Times 16 because that’s the number of steps inherent to the “fade-to” methods — stepping from 0 to 15.) When the end of the list is reached, the list of methods starts over.

        So, if I were to simply set a string of lights to red, I’d have a list like this:

        {xm_measure_fill_to_red, 0},
        {xm_measure_sleep, 10000},

        Every 10 seconds it would re-fill to red. The 10000 could be larger — perhaps 60000, then it would do it once a minute.
        You could fade from black to orange and back like this:

        {xm_measure_fill_to_orange, 0}, // Start out solid orange
        {xm_measure_sleep, 4000}, // Sleep 4 seconds
        {xm_measure_fill_to_dark_orange, 200}, // If the value of “orange” is 15 and the value of “dark orange” is 3, then in (15-3) 12 steps and a delay of 200ms per step, the string would change from orange to dark orange. You would probably get some strange intermediate colors here because the “fade_to” method simply increments or decrements the R or G or B to its destination so it would transition dark/light R, G, or B to light/dark R, G, or B well. But it might look weird transitioning orange since orange is 15 red 8 green 0 blue. The green would achieve zero faster than the red, so the string would look orange, then more red on its decent to dark orange. I’m rambling.

        You are welcome to create new xm_measure_XXXXX methods, too.

  18. Dave M says:

    As someone who has never used an Arduino (or any other type of microcontroller) before, or programmed anything… is there something I need to do to make this program actually do something on an Uno? I have done the hardware hacking per AustinLightGuy’s blog and have my Arduino hooked up, and successfully verified and uploaded your program to my Uno (thanks to eEric!) but with the Uno plugged in the lights just freeze in whatever color they were in when I plug the board in.

  19. Charlie U says:

    Thank you very much!

  20. Peter says:

    Hi, I got everything to work, but I arranged my lights in a 7×7 array. I can’t see where in the code I can change the order in which the bulbs are addressed. I am a bit of a noob at the Arduino and have not programmed for a long time, sorry if this is way too obvious.

    • mevans77 says:

      This comment applies if you are using my code.

      In the xm_lights.h file, there is an array called xm_light_string_direction[]. It contains a list of the directions of the strings. (The values are XM_REVERSE_DIRECTION and XM_FORWARD_DIRECTION.)
      The default value is as follows:

      EXTERN uint8_t xm_light_string_direction[] // Light string bulb address direction.
      #ifdef DEFINE_GLOBALS
      = {XM_REVERSE_DIRECTION, XM_FORWARD_DIRECTION}
      #endif
      ;

      That’s because I run my first string in the “reverse” direction and my second string in the “forward” direction.

      If you have only one string of lights (therefore one entry in this array) traveling in the “forward direction, you have:
      EXTERN uint8_t xm_light_string_direction[] // Light string bulb address direction.
      #ifdef DEFINE_GLOBALS
      = {XM_FORWARD_DIRECTION}
      #endif
      ;

      • Peter says:

        Thanks, I seem to be hacking my way through the code, and I think I have it more or less figured out… except my lights seem to have a completely random address assigned to them rather than sequentially down the line. very odd. Everything else works, but if I run say the “slide to red” measure, the bulbs light up in a seemingly random order… 😦

      • Peter says:

        Whoa! It works. Who would have thought that turning it off and then turning it back on again would solve the problem.

        Has anyone figured out a way to reset all the bulbs back to accept enumeration at the again?

      • mevans77 says:

        To the best of my knowledge, the only way to address the bulbs is on power-on. That’s probably why I start all my sequences with xm_measure_fill_to_black(). Sometimes I have an addressing problem with my lights — on one string, sometimes the first bulb gets addressed as the last bulb. Sometimes a power-cycle will fix the addressing, sometimes not.

  21. Charlie says:

    Good day again!
    Would you pretty please point me out in the right direction? My programming skills appear to be non-existent.
    I am trying to slightly modify the xm_measure_red_green_alt() to fade color instead of straight red to green transitions.
    void xm_measure_red_green_alt() {
    for (int vb = 0; vb intensity = XM_MAX_INTENSITY; // Likely not necessary.
    xm_copy_color(vbulb[vb], ((vb % 2) == 0 ? xm_red : xm_green));
    }
    for (int vb = 0; vb intensity = XM_MAX_INTENSITY; // Likely not necessary.
    xm_fade_to(vbulb[vb], ((vb % 2) == 0 ? xm_green : xm_red));
    }
    I am coloring every odd/even bulb in alternate color in the first FOR loop. Second FOR loop should be fading to the opposite color but the result is just static coloring of the first FOR loop.

    Once again, please forgive me for my programming incompetence but i just don’t get it:(

    • mevans77 says:

      I think your copy/paste missed a few lines of code for xm_measure_red_green_alt. Here’s the complete method:

      // Green/red alternating lights, switching every second.
      void xm_measure_red_green_alt() {
      for (int vb = 0; vb < XM_VBULB_SIZE; vb++) {
      vbulb[vb]->intensity = XM_MAX_INTENSITY; // Likely not necessary.
      if (vb % 2 == 0) {
      xm_copy_color(vbulb[vb], ((m1_seq % 2) == 0 ? xm_red : xm_green));
      }
      else {
      xm_copy_color(vbulb[vb], ((m1_seq % 2) == 1 ? xm_red : xm_green));
      }
      }

      // Increment sequence.
      m1_seq++;
      if (m1_seq >= 20) next_measure = 1; // Flag main to go to next measure.
      }

      I believe it flips even bulbs from red to green, and odd bulbs from green to red (then back). I think this just changes the bulbs in one shot — no fade.

      If you wish to fade even bulbs to one color and odd bulbs to another color, take a look at xm_measure_fade_to_two_colors_alt(). I believe you set the color_pairs array to a list of, well, color pairs. Then the first go round, evens are faded to the first color in the pair and odds faded to the second color in the pair. If you simply put one pair in the array, you would get a single fade to that color pair. If you wished to go back and forth, then you could put a list of alternating color pairs. (Or, you could put two color pairs [red, green] and [green, red], then in the measure_list_operational[] array, you could include xm_measure_fade_to_two_colors_alt() several times.)

      Or, if you simply wish to fix your code (providing you include the missing code from the fol loop), you might change the second line to something like:

      xm_fade_to(vbulb[vb], ((vb % 2) == 1 ? xm_green : xm_red));

      Note the “== 1” instead of “==0”. That picks up the odd bulbs instead of the even ones.

      For kicks, here’s the source for xm_measure_fade_to_two_colors_alt():

      xm_color_t color_pairs[][2] = {
      {xm_white, xm_red},
      {xm_green, xm_red},
      {xm_green, xm_blue},
      {xm_yellow, xm_blue},
      // {xm_yellow, xm_red},
      {xm_blue, xm_red},
      {xm_blue, xm_white},
      {xm_green, xm_white},
      // {xm_green, xm_yellow},
      // {xm_white, xm_yellow}
      };
      #define XM_COLOR_PAIRS_SIZE (sizeof(color_pairs) / sizeof(color_pairs[0]))

      // ==================================

      // Fade bulbs to two alternating colors.
      // The period depends on 3 numbers — the sleep (50), the m1_index change (100), and the exit number (10000).
      // This gives 1000/100 changes (10), and a period of 50 * 100 (5000ms).

      void xm_measure_fade_to_two_colors_alt() {
      if (m1_seq == 0) { // Make sure we initialize m1_index.
      m1_index = 0;
      }
      if (m1_seq % 100 == 0) {
      m1_index = (m1_seq / 100) % XM_COLOR_PAIRS_SIZE; // Color pair index. 0 to XM_COLOR_PAIRS_SIZE-1
      }

      for (int vb = 0; vb color.red;
      uint8_t green = vbulb[vb]->color.green;
      uint8_t blue = vbulb[vb]->color.blue;

      xm_color_t fade_to_color = color_pairs[m1_index][vb % 2];

      if (red != fade_to_color.red) {
      if (red color.red, XM_MAX_RED);
      if (red > fade_to_color.red) XM_DEC(vbulb[vb]->color.red, 0);
      vbulb[vb]->modified = XM_TRUE;
      }
      if (green != fade_to_color.green) {
      if (green color.green, XM_MAX_GREEN);
      if (green > fade_to_color.green) XM_DEC(vbulb[vb]->color.green, 0);
      vbulb[vb]->modified = XM_TRUE;
      }
      if (blue != fade_to_color.blue) {
      if (blue color.blue, XM_MAX_BLUE);
      if (blue > fade_to_color.blue) XM_DEC(vbulb[vb]->color.blue, 0);
      vbulb[vb]->modified = XM_TRUE;
      }
      }

      m1_seq++;
      if (m1_seq >= 1000) next_measure = 1; // CHANGE THIS NUMBER TO GET MORE OR FEWER TRANSITIONS.
      }

      • Charlie says:

        Thank you!
        I am now messing around with the xm_measure_fade_to_two_colors_alt() which i find much easier for my poor mind to digest and understand.
        Sorry i skewed xm_measure_red_green_alt() so badly above.

        Initially i tried replacing the original xm_measure_red_green_alt

        for (int vb = 0; vb intensity = XM_MAX_INTENSITY; // Likely not necessary.
        if (vb % 2 == 0) {
        xm_copy_color(vbulb[vb], ((m1_seq % 2) == 0 ? xm_red : xm_green));
        }
        else {
        xm_copy_color(vbulb[vb], ((m1_seq % 2) == 1 ? xm_red : xm_green));
        }
        }

        with

        for (int vb = 0; vb intensity = XM_MAX_INTENSITY; // Likely not necessary.
        if (vb % 2 == 0) {
        xm_fade_to(vbulb[vb], ((m1_seq % 2) == 0 ? xm_red : xm_green));
        }
        else {
        xm_fade_to(vbulb[vb], ((m1_seq % 2) == 1 ? xm_red : xm_green));
        }
        }
        which just lit all bulbs in either red or green, back and forth,
        then i tried

        for (int vb = 0; vb intensity = XM_MAX_INTENSITY; // Likely not necessary.
        if (vb % 2 == 0) {
        xm_fade_to(vbulb[vb], ((vb % 2) == 0 ? xm_red : xm_green));
        }
        else {
        xm_fade_to(vbulb[vb], ((vb % 2) == 1 ? xm_red : xm_green));
        }
        }
        which replaces m1_seq with vb but that fades the odd bulbs (or even, cant remember now) leaving the even static in color.

        m1_seq does not like xm_fade_to. I do not have enough knowledge to debug m1_seq to see what values are passing with through that variable each cycle and why it breaks xm_fade_to meanwhile being totally fine in xm_copy_color.
        m1_seq being a global variable counts ALL cycles, in ALL functions unless gets re-initialized?

        Also, ive noticed (in xm_measures.h) if i called just the original xm_measure_red_green_alt() without any other preceding color filling functions, no results are produced, all bulbs are off. So I have to add:

        {xm_measure_fill_to_red, 0},
        then
        {xm_measure_red_green_alt, 50},

        in order for the latter to generate something on the bulbs. So if i understand correctly,
        {xm_measure_red_green_alt, 50}, needs existing color to fade off from otherwise it just doesn’t do anything. Sorry for my primitive explanations, questions. Hopefully you follow what i am trying to express.(aside from being completely over my head)

        I greatly appreciate your time!

      • mevans77 says:

        I found the problem with the cut/paste of the code segment. If we post “less-than” or “greater-than” symbols, we need to make them &lt; and &gt; in order for wordpress to render them correctly. So, the xm_measure_red_green_alt() method is as follows:

        // Green/red alternating lights, switching every second.
        void xm_measure_red_green_alt() {
        for (int vb = 0; vb < XM_VBULB_SIZE; vb++) {
        vbulb[vb]->intensity = XM_MAX_INTENSITY; // Likely not necessary.
        if (vb % 2 == 0) {
        xm_copy_color(vbulb[vb], ((m1_seq % 2) == 0 ? xm_red : xm_green));
        }
        else {
        xm_copy_color(vbulb[vb], ((m1_seq % 2) == 1 ? xm_red : xm_green));
        }
        }

        // Increment sequence.
        m1_seq++;
        if (m1_seq >= 20) next_measure = 1; // Flag main to go to next measure.
        }

        Let’s tear this apart a little.
        This for statement loops through the array of all bulbs (vbulb[]):
        for (int vb = 0; vb < XM_VBULB_SIZE; vb++)

        This statement selects even bulbs:
        if (vb % 2 == 0)
        The “then” clause therefore selects odd bulbs.

        This statement copies TO vbulb[vb], either red or green:
        xm_copy_color(vbulb[vb], ((m1_seq % 2) == 0 ? xm_red : xm_green));
        So, how does it decide to use red or green? If the m1_seq is even (mod 2 == 0), then red, else green.
        So, what is m1_seq?? It’s the pulse of the “measure”. It’s the pulse of this method. Everytime this method is called, m1_seq is incremented. That gives the method some kind of idea as to where it is in its sequence. For many more simple methods, this value plays a minor role. (In this method, it simply provides an even/odd pulse, plus a total number of times the lights switch back and forth before jumping out of this method and going to the next method. Where is that decision done? Look at the next lines of code here:
        // Increment sequence.
        m1_seq++;
        if (m1_seq >= 20) next_measure = 1; // Flag main to go to next measure.
        What’s happening here is we increment m1_seq (the “pulse” of the method — so the next time the method is called, it knows where it is). When the method “pulses” or is called 20 times, the decision to leave the method (or “measure” in our musical analogy) — with setting “next_measure” to 1.
        So, when this xm_measure_red_green_alt() is included in the XM_MEASURE_LIST (measure_list_operational) in xm_measures.h, like this:
        {xm_measure_red_green_alt, 500},
        Then what happens is, the main loop() calls xm_measure_red_green_alt() which establishes the bulb colors. Then it delays half a second (500 ms), then calls it again. The method is called repeatedly with a 500 ms delay until the method sets next_measure to 1. That’s the signal to the main loop to jump to the next method listed in the XM_MEASURE_LIST (measure_list_operational).

        Now, let’s look at a method that fades all of the bulbs to one color.
        // Fade current bulbs to black.
        void xm_measure_fade_to_blue() {
        for (int vb = 0; vb < XM_VBULB_SIZE; vb++) {
        xm_fade_to(vbulb[vb], xm_blue);
        }
        m1_seq++;
        if (m1_seq >= XM_MAX_GREEN) next_measure = 1;
        }

        This method is in the measure_list as follows:
        {xm_measure_fade_to_blue, 250},

        That means the method is called repeatedly with a 250ms delay between calls.
        In each call, it calls xm_fade_to(vbulb[vb], xm_blue) on each bulb, moving the existing color toward xm_blue. If the bulb is already blue, it makes no change. If the bulb is white (full red, blue, and green), it fades the red to black and fades the green to black (resulting in a blue bulb).
        This method increments the “pulse” (m1_seq) so that it knows it how many times it has been called. It compares m1_seq to the value of XM_MAX_GREEN, and if greater than or equal (should be equal at one point, never greater, but code for safety), then we pop down to the next method listed in the measure_list.
        XM_MAX_GREEN is not magical. It’s value is 0xf (15 base 10). So we are basically looping 16 times. That way, if we have a bulb that starts out as black (zero red, zero green, zero blue), then in 16 steps (0 to 15), the bulb will have full intensity blue. If we wish the string of lights to remain full blue for a period of time, we would follow the xm_measure_fade_to_blue, 250 call with:
        {xm_measure_sleep, 1000},
        which would simply delay 1000 ms (1 second). Then we could call another method.
        Now, the xm_fade_to() is kind of a tricky method which looks at the red/green/blue component of the bulb. If the current red component is greater than the desired, it reduces the value until it equals the desired value. If the current red component is less than the desired, it increases the value until it equals the desired value. It does the same for the green and blue components. So, after xm_fade_to() is called 16 times, we are guaranteed that any bulb color (values 0 to 15) will be incremented/decremented to the requested bulb color. (Sometimes we can get some short-lived unusual shades between color shifts but that’s just how this little algorithm works.)

        Now let’s look at your particular question. I’m not exactly sure what you were asking so I’ll assume you want to fade even bulbs to green and odd bulbs to red, once. The below method will be called 16 times (because of m1_seq at the bottom — hits 16 and goes to next measure). It will fade the even bulbs to green and the odds to red.
        void xm_measure_fade_to_green_red() {
        for (int vb = 0; vb < XM_VBULB_SIZE; vb++) {
        if (vb % 2 == 0) {
        xm_fade_to(vbulb[vb], xm_green);
        }
        else {
        xm_fade_to(vbulb[vb], xm_red);
        }
        }
        m1_seq++;
        if (m1_seq >= XM_MAX_GREEN) next_measure = 1;
        }

        If you wanted to delay a second, then fade back, you could place this measure in the measure_list multiple times with the “sleep” method between, or you could make this method much smarter — that is, check where it is in the m1_seq, with respect to the delay set in the measure_list, and so forth.

  22. Charlie says:

    Thanks SO much again for the detailed explanation. I now understand exactly what ml_seq is which makes things clear. The music analogy set me straight.
    The intention was to change xm_measure_red_green_alt to do fade instead of fill.

    I created two methods which do what xm_measure_fade_to_green_red() but with fading.
    void xm_measure_evenbulb_red_fade() {

    for (int vb = 0; vb intensity = XM_MAX_INTENSITY; // Likely not necessary.
    if (vb % 2 == 0) {
    xm_fade_to(vbulb[vb], xm_red);
    }
    else {
    xm_fade_to(vbulb[vb], xm_green);
    }
    }
    // Increment sequence.
    m1_seq++;
    if (m1_seq >= XM_MAX_GREEN) next_measure = 1; // Flag main to go to next measure.
    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    void xm_measure_oddbulb_green_fade() {

    for (int vb = 0; vb intensity = XM_MAX_INTENSITY; // Likely not necessary.
    if (vb % 2 == 0) {
    xm_fade_to(vbulb[vb], xm_green);
    }
    else {
    xm_fade_to(vbulb[vb], xm_red);
    }
    }
    // Increment sequence.
    m1_seq++;
    if (m1_seq >= XM_MAX_GREEN) next_measure = 1; // Flag main to go to next measure.
    }

    So basically these two fade to opposite color of the other. For the lack of better programming skills, I have to put these methods quite a few times in xm_measures.h to achieve as many transitions as i like. Very inefficient i know, but i could not figure out a way to combine the two in one method without ruining measure.

    Also, one more question. Unless I include a method to fill the bulbs to black or any other color, running JUST the two methods i pasted above produces no color at all. Is that intentional?
    as in

    {xm_measure_evenbulb_red_fade, 20},
    {xm_measure_oddbulb_green_fade, 20},
    vs
    {xm_measure_fill_to_back, 0},
    {xm_measure_evenbulb_red_fade, 20},
    {xm_measure_oddbulb_green_fade, 20},

    Thank you!!!

    • Charlie says:

      xm_measure_fade_to_two_colors_alt, like you said… does exactly what I was trying to achieve. I guess it took me some effort to figure it out, including the wheel reinvention.
      My apologies! I feel like an idiot now.

      Still though, the question about the very first method needing to initialize lights with something still remains.

      Once again, many thanks!

      • mevans77 says:

        I have the same method in my measure list. When the string of lights first powers on, addresses must be assigned to each bulb. I may have used this method to achieve that goal. In that case, you would also need to call that same method. I don’t recall specifically, and I don’t have time right now to look back through the code.

  23. Barry says:

    Judging from what I’m reading you all seem to understand these lights.I’m just looking for some info.I just put up my G35 50 light strings for the second year.One string only lights the first half.On/off works as does function control on first half.Any idea’s? Should I toss em?Any suggestions would be great.
    Thanks very much…

  24. Hey thanks for the code and all the help, I am hacking my way ungracefully through this, and I managed to get it to work, and modified some of the measures. What I am working on now is to add a second string, then write something in processing where I can build animation in “frames” and then pump those to the arduino. I’d have to convert your software into something that will accept an array (10x10x4 I guess) from the (?) serial port, and then convert it to your format and bang it out to the lights. This is ambitious for me, as i have not programmed seriously for some 20 years, and am new to processing, but hey, anything beats watching TV. I’m wondering if anyone else has done something similar, or if anyone can advise if the serial port communications would be the way to do it, or if there are better protocols that are still simple enough for a hack like me to use?

    I’m thinking if I can successfully output an array from processing and have it display at a reasonable refresh rate, that will open up the possibility for a lot of really fun animations, patterns and interactive stuff, and I could build up long sequences without filling the Arduino memory. In the long term, this might be a good way to sync the lights with music as well? Anyone?

  25. Re: power cycling… I wonder if a fix would be to reset the lights by cycling the power with a relay controlled off another pin? Maybe a relay for each string?

    • mevans77 says:

      I’m not exactly sure why simply assigning addresses to the lights at power-on is a problem. If you wish to re-address lights on-the-fly, then I see two options. 1) Do what you say — have a relay that shuts off lights for half a second, then turns them back on. Or 2) Have fixed addressing, then do your “re-addressing” (or re-mapping) in software. That is, if you wish to change their normal ordering, just have a table that maps the bulbs in a different order. You could re-map behind the scenes and all the algorithms could remain the same. (Kind of like how I do the forward/reverse direction stuff.)

      • The problem I am having is when I power up the lights, sometimes the initial addressing gets mixed up, and they get assigned wrong, sometimes totally random-seeming with multiple bulbs having the same address, other times it is just a few on the end of the string. I’m just thinking of a way to have the arduino powered on, and then have it reset the lights and start fresh a second or so before enumerating them. I don’t know why it does this, the last few times it has been OK.

        Yes, as to the re-adressing, I am going to have to do that anyway – I’ll translate the Processing array(s) to the format you use (for now). I’ll let you know how it works out – I better get going if I want this up and running for the holidays. – Cheers!

  26. david says:

    Today is 12/31/2013. I just purchased 6 boxes (25 count each) of the GE brand G35 color effects lights at Lowes on clearance. Only when I got home did I realize that the strings can not be connected end to end. Being they are seasonal items and on sale,they can not be returned so I have to keep them. the conversations that you all are having in the above posts may as well be rocket science to me as I totally do not understand any of what I was reading!!! I do have a question though. I would really like to keep and use these lights in my Christmas display next year. I did some looking online and found an 8 way jumper for LED lights. Does anyone know if this could be used to connect all 6 of my sets to a single control box and have the lights synched??? Of course i would be using the box that came with the lights. What you all seem to be doing with these lights appears to be interesting but it’s way above my head. I just want to be able to use the lights as they are but be able to connect more than a single set

  27. david says:

    Hopefully this link will work and you’ll be able to view the “tap” that I mentioned. I got out a box of my lights and realized also that the control box is part of the main wire and not the control box itself. I purchased a new GE LED light Christmas tree this year with multi function as well and the control box actually detaches from the light sets themselves. I thought these G35 lights were like that as well but apparently I was wrong. My plans for the G35’s is to also put them on my tree next year and I am just trying to find a way ( an easy one I hope) to get them all plugged in using as few outlets as possible.
    http://www.ledholidaylighting.com/8waytap.aspx

  28. Stuart Fuller says:

    Just wanted to say thanks for posting this information about the GE light sets. I’ve taken your code and doctored it to suit my needs. I was pretty impressed that once I corrected a library issue (likely Arduino software version changes), your code worked “out of the box”. When I first started on this, I read about all the issues that other people were having with signal timing, but your code worked great. Thanks again!

  29. Hi! I also want to thank you very much for making this code available. I managed to arrange 2 strings of lights in a 10×10 array, and am using part of your code to control it. I am using processing on my mac, and serial communications to the Arduino with the intention of syncing lights to music and maybe having an interactive display. While it works great so far, I am finding the refresh rate is not so great, and am wondering if anyone else has experience with that and managed to get it going faster?

    I found this reference on how to write to the pins a little faster than digitalWright http://www.instructables.com/id/Arduino-is-Slow-and-how-to-fix-it/step4/Overview/
    have not tried it yet though.

    • mevans77 says:

      Thanks for the positive feedback. I’m glad you have been able to use the code!
      Regarding writing faster — the writes to the bulbs require precisely timed serial communications so I don’t think it is possible to write faster to a single string of bulbs. But, since I have two strings, I did (at one time) attempt to write to both strings at the same time. It required a more complex write routine — the code had to sleep until the next time one or the other or both strings needed a 0-1 or 1-0 transition. I couldn’t get the timing to work so I went back to writing one string at a time. If you have 100 bulbs, I suppose you could break them into shorter strings (5 strings of 20 perhaps), then write to all 5 strings at the same time. But again, I couldn’t get the arduino to write to 2 strings in parallel. Perhaps one could use multiple arduinos — one per string — then somehow coordinate the arduinos to work together. But that’s beyond the scope of my goal of just having pretty lights on my house at Christmas. 🙂

  30. Chris says:

    Thanks for the code. I have been wanting to control these lights for several years and I have only just gotten around to doing it. One note to readers, the #include “WProgram.h has changed its name to #include “Arduino.h” for newer version of arduinos or newer version of the app.

    • mevans77 says:

      Yes, thanks. I should change this and repost. It’s on my to do list now.

      • kyle Olson says:

        Is there any updates for this project as most of this is 2 – 3 years old.

      • mevans77 says:

        A year or so ago, I change the include file required by the Arduino development environment (search the comments on the blog for specifics). I don’t think I re-posted those modifications. My Arduino board failed to drive the lights correctly last Christmas (2014) so I will be building and loading the code on a different Arduino in the next month or so. I’ll know if the code still builds with a new Arduino environment then.

      • I had mine working, and was experimenting last December with trying to get it running via serial interface, with Processing on my MAC. I did get it going, but the refresh was very slow, and so I had set it aside. I’m planning to get it going for this christmas though. I’ll post an update if I do.

  31. Duane G. says:

    Delay x.h compiler issues.

    I just tried to update some sequences on my programs only to find that none of my old programs would compile anymore. Errors about undeclared voids in the delay x.h files. I went to the AVRFREAKS.NET website to see if there was an updated version of delay x.h which might clear up the problem. There was only a 2006 version that seemed newer than the 2005 version that was in the original xm zip file. I downloaded the 2006 version and replaced in in the directory hoping that would clear up the problem. Nope same compiler errors. After some soul searching I tried compiling the programs on an older version of arduino software 1.0.6 and found that version 1.0.6 will compile the software properly. The same files won’t compile on my current installed version 1.6.1. I am afraid that solving this is beyond my programming abilities, so I thought I would throw it back up on the forum and see if anyone is interested in digging into this a bit further and possibly creating a download zip file with some fixes.

    Just a passing thought, I have done some programming on a number of christmas light projects long before these addressable lights came along and have some wonderful sequences that have been done using some pretty old school array lookup routines. I would be quite keen to trade some insights on sequences for some cooperation on some programming skills to convert these sequences into the “measures” formats that this program uses and share them with everybody. So if anybody has some time to update and add some new tricks to this already great software please let me know.

    • Mark Evans says:

      I just downloaded Arduino 1.6.13 and built my lights project that I last updated either Dec 2013 or 2014 and I didn’t have any trouble with building delay_x.h. I do recall having to change one of the includes around (see comments above). Perhaps if you post the kinds of error messages you are getting, someone could provide a diagnosis.

      Also, perhaps someone on an Arduino forum might have some insight.

      • Duane G says:

        Wow, I was not expecting such a quick reply! I would be happy to send some more info, but I thought I would see if anyone was monitoring the thread Since the last activity was quite a while ago. Perhaps I will update the compiler to the latest version and see if my issue persists before getting into the gory details of why 1.6.1 is giving grief. Thanks for your reply.

  32. Duane G. says:

    Good news, 1.6.13 works just fine for me too. I have no affinity for 1.6.1 so good riddance!

  33. Duane Grzyb says:

    Hi mike, i have been using your software on my house each christmas with new measures for several years now. I have gotten reasonably proficient at changing up the sequences to meet my needs. This year though I have been digging into the code a bit further with some new ideas and have run into some difficulty. I picked up a budweiser goal synced gass and want to run a goal sequence of team colors and a right shifted goal light sequence. Thus my issue is leaving the lights sleeping when not in use or off season, running the goal sequence upon a pin trigger, and preferrably running normal christmas sequences on a timer. All pretty basic stuff. My issue is building two or three xm_measures during the compile to switch between in the loop section. So i an a bit mystified where the demo and operational measures are selected and compiled into one or the other or not both. I have tried compiling three sets of sequences but cant seem to get it to compile as the “extern” and “define” stuff is more than i can deal with. Any thoughts about offering some programming advice or dusting off the project? Thanks

    • mevans77 says:

      Hi Duane. I’m not exactly sure what you are trying to do here. I googled “budweiser goal synced glass” — it looks like a cup that communicates via bluetooth to a phone to light up when a goal is scored. Did you want that to trigger an arduino program to make the lights flash in a particular sequence? And did you want something like a switch connected to an arduino pin that would select between bud-goal-mode and Christmas mode?

      • Duane Grzyb says:

        Yeah, you got it, when my team scores the house blinks team colors! I need a way to have at least two different light measures compiled and ready to go dependant on a pin condition.

        As the lights need to be energized when its not christmas too i need a pin or timer selected sleep mode.

        Thus i have three states, goal, off, and christmas!

        i just can’t figure out how to compile both demo and operational sequences at the same time and pin switch between them.

  34. Duane Grzyb says:

    I’m a hardware guy, if i have to, i can program two arduinos, one for christmas and one for team goal outputs and logic switch with hardware the light string, but that seem wrong on many levels. :).

    I just dont have a handle on why your program picks one or the other measure instead of both. Well i know why, i just don’t know how to change it. I tried duplicating the code after defining which measure set to compile, but it is not compiling for me cause im guessing how it works due and trying to dupicate a lot of stuff i don’t quite get the mechanics of do to lack of programming understanding.

    There are about 10 lines of code right at the end of xm_measures.h that i think just need to be run twice to generate two different XM_MAX_MEASURES, xm_measure_t, xm_measure_size, but i don’t get the Extern, ifdef define globals pieces if code.

    Thus i’m hoping that the 10 lines of code needed to compile TWO measures might be a simple cut and paste of code for you.

    i wish to generate a second xm_measure_2, besides xm_measure to switch between in “loop”

    and maybe xm_measure_size_2

    the section of code at the top,

    #ifdef DEFINE _GLOBALS
    #define EXTERN
    #else
    #define EXTERN extern
    #endif

    doesn’t look like anything i’ve seen before.

  35. mevans77 says:

    Regarding the #ifdef DEFINE_GLOBALS code, the xm_measures.h file defines variables. If DEFINE_GLOBALS is defined, then in files you say #include “xm_measures.h”, then the actual variables are declared (instance created), because the code expands like:
    int x;
    In code where DEFINE_GLOBALS is NOT defined, then in files you say #include “xm_measures.h”, then the actual variables are defined (says x exists of type int so code knows what it is), but not declared, because the code expands like:
    extern int x;

    To address the larger problem, it is probably easiest to create two measure list tables in xm_measures.h, then in xm_lights.ino ?? (main file), in the setup() or setup1() method, read an I/O port (switch connected), and if high, assign one table and size, and if low, assign the other.

    Something like:

    void setup() {
    delay(1000); // Pause half a second to let bulbs power up.

    // read switch
    if (switchon) {
    xm_measure = XM_MEASURE_LIST_XMAS;
    xm_measure_size = XM_MAX_MEASURES_SPORTS;
    }
    else {
    xm_measure = XM_MEASURE_LIST_SPORTS;
    xm_measure_size = XM_MAX_MEASURES_SPORTS;
    }
    setup1();
    }

    Over in xm_measures.h, something like this:

    #define XM_MEASURE_LIST_XMAS measure_list_operational
    #define XM_MAX_MEASURES_XMAS (sizeof(XM_MEASURE_LIST_XMAS) / sizeof(XM_MEASURE_LIST_XMAS[0]))

    #define XM_MEASURE_LIST_SPORTS measure_list_sports
    #define XM_MAX_MEASURES_SPORTS (sizeof(XM_MEASURE_LIST_SPORTS) / sizeof(XM_MEASURE_LIST_SPORTS[0]))

    EXTERN xm_measure_t *xm_measure;
    EXTERN int xm_measure_size;

    So, you are defining lists and sized in xm_measures.h, but assigning which table and size to use, in setup() in xm_lights.ico (main file).

    Try something like that.

  36. mevans77 says:

    Of course, you will have to cycle power between changes of the switch.

  37. Laurie Downs says:

    I just need to know how to fix a string ? Half isnt working ( no lights) cant find information anywhere. If you have any info? Thanks!

    • Stu Fuller says:

      I have a light on my string that doesn’t work right (missing color, or lights “downwind” from it don’t work). I just took another string, cut out one of the lights, and spliced it into the failed string.

      • Laurie Downs says:

        This is half the string that is out,would one bulb make half a string not work?

      • Jacko Flychuck says:

        Yes, because each bulb has a data receiver and a data transmitter. one failure stops the data flow to subsequent bulbs. either that or you have lost power to the latter half of the string due to a wire break.

      • Stu Fuller says:

        As Duane was referring to, the lights are a daisy chain. The controller connects to the first one, it passes commands to the second one, and it passes commands to the third one, and so on. If one of the has failed, it won’t pass the commands to the ones downwind of it.
        Or, it could just a bad wire between the last lit bulb and the rest.
        On my strings, they’re outside. On cool/cold days, things work normally, but if it gets above 50F, one light fails to pass the command data along, and so all the lights downwind of it don’t work, or don’t work right.

    • Duane says:

      Because each bulb re enumerates ever time it is powered on a single bulb failure can be removed from the string and spliced back together. It might be the last working one or the first non working one. Check for 5v on the two power supply wires past the failure.

  38. Matt says:

    I would like to download the software that you created to run the lights. Im just starting playing with these. Also the web pages mentioned about dedarc dont seem to work. does anybody have a offline version

  39. Terri Zinchini says:

    Do you happen have a remote from the light set?

Leave a reply to mevans77 Cancel reply