Monday, December 6, 2010

Controlling GE Color Effects lights with the Ardunio

Here's the code. Power up the lights first and then the Arduino so that the lights get enumerated properly.

The ground wire (has ridges) from the strand is connected to GND on the Arduino and and the center wire is connected to digital output 4.

Enjoy
 // GE Christmas light control for Arduino  
 // Ported by Scott Harris <scottrharris@gmail.com>  
 // scottrharris.blogspot.com  
   
   
 // Based on this code:  
   
 /*!     Christmas Light Control  
 **     By Robert Quattlebaum <darco@deepdarc.com>  
 **     Released November 27th, 2010  
 **  
 **     For more information,  
 **     see <http://www.deepdarc.com/2010/11/27/hacking-christmas-lights/>.
 **  
 **     Originally intended for the ATTiny13, but should  
 **     be easily portable to other microcontrollers.  
 */  
   
 #define xmas_color_t uint16_t // typedefs can cause trouble in the Arduino environment  
   
 // Eliminate the .h file  
   
 #define XMAS_LIGHT_COUNT          (36) //I only have a 36 light strand. Should be 50 or 36  
 #define XMAS_CHANNEL_MAX          (0xF)  
 #define XMAS_DEFAULT_INTENSITY     (0xCC)  
 #define XMAS_HUE_MAX               ((XMAS_CHANNEL_MAX+1)*6-1)  
 #define XMAS_COLOR(r,g,b)     ((r)+((g)<<4)+((b)<<8))  
 #define XMAS_COLOR_WHITE     XMAS_COLOR(XMAS_CHANNEL_MAX,XMAS_CHANNEL_MAX,XMAS_CHANNEL_MAX)  
 #define XMAS_COLOR_BLACK     XMAS_COLOR(0,0,0)  
 #define XMAS_COLOR_RED          XMAS_COLOR(XMAS_CHANNEL_MAX,0,0)  
 #define XMAS_COLOR_GREEN     XMAS_COLOR(0,XMAS_CHANNEL_MAX,0)  
 #define XMAS_COLOR_BLUE          XMAS_COLOR(0,0,XMAS_CHANNEL_MAX)  
 #define XMAS_COLOR_CYAN          XMAS_COLOR(0,XMAS_CHANNEL_MAX,XMAS_CHANNEL_MAX)  
 #define XMAS_COLOR_MAGENTA     XMAS_COLOR(XMAS_CHANNEL_MAX,0,XMAS_CHANNEL_MAX)  
 #define XMAS_COLOR_YELLOW     XMAS_COLOR(XMAS_CHANNEL_MAX,XMAS_CHANNEL_MAX,0)  
   
 // Pin setup  
 #define XMASPIN 4 // I drive the LED strand from pin #4  
 #define STATUSPIN 13 // The LED  
   
 // The delays in the begin, one, and zero functions look funny, but they give the correct  
 // pulse durations when checked with a logic analyzer. Tested on an Arduino Uno.  
   
 void xmas_begin()  
 {  
  digitalWrite(XMASPIN,1);  
  delayMicroseconds(7); //The pulse should be 10 uS long, but I had to hand tune the delays. They work for me  
  digitalWrite(XMASPIN,0);   
 }  
   
 void xmas_one()  
 {  
  digitalWrite(XMASPIN,0);  
  delayMicroseconds(11); //This results in a 20 uS long low  
  digitalWrite(XMASPIN,1);  
  delayMicroseconds(7);   
  digitalWrite(XMASPIN,0);  
 }  
   
 void xmas_zero()  
 {  
  digitalWrite(XMASPIN,0);  
  delayMicroseconds(2);   
  digitalWrite(XMASPIN,1);  
  delayMicroseconds(20-3);   
  digitalWrite(XMASPIN,0);  
 }  
   
 void xmas_end()  
 {  
  digitalWrite(XMASPIN,0);  
  delayMicroseconds(40); // Can be made shorter  
 }  
   
   
 // The rest of Robert's code is basically unchanged  
   
 void xmas_fill_color(uint8_t begin,uint8_t count,uint8_t intensity,xmas_color_t color)  
 {  
      while(count--)  
      {  
           xmas_set_color(begin++,intensity,color);  
      }  
 }  
   
 void xmas_fill_color_same(uint8_t begin,uint8_t count,uint8_t intensity,xmas_color_t color)  
 {  
      while(count--)  
      {  
           xmas_set_color(0,intensity,color);  
      }  
 }  
   
   
 void xmas_set_color(uint8_t led,uint8_t intensity,xmas_color_t color) {  
      uint8_t i;  
      xmas_begin();  
      for(i=6;i;i--,(led<<=1))  
           if(led&(1<<5))  
                xmas_one();  
           else  
                xmas_zero();  
      for(i=8;i;i--,(intensity<<=1))  
           if(intensity&(1<<7))  
                xmas_one();  
           else  
                xmas_zero();  
      for(i=12;i;i--,(color<<=1))  
           if(color&(1<<11))  
                xmas_one();  
           else  
                xmas_zero();  
      xmas_end();  
 }  
   
   
 xmas_color_t  
 xmas_color(uint8_t r,uint8_t g,uint8_t b) {  
      return XMAS_COLOR(r,g,b);  
 }  
   
 xmas_color_t  
 xmas_color_hue(uint8_t h) {  
      switch(h>>4) {  
           case 0:     h-=0; return xmas_color(h,XMAS_CHANNEL_MAX,0);  
           case 1:     h-=16; return xmas_color(XMAS_CHANNEL_MAX,(XMAS_CHANNEL_MAX-h),0);  
           case 2:     h-=32; return xmas_color(XMAS_CHANNEL_MAX,0,h);  
           case 3:     h-=48; return xmas_color((XMAS_CHANNEL_MAX-h),0,XMAS_CHANNEL_MAX);  
           case 4:     h-=64; return xmas_color(0,h,XMAS_CHANNEL_MAX);  
           case 5:     h-=80; return xmas_color(0,XMAS_CHANNEL_MAX,(XMAS_CHANNEL_MAX-h));  
      }  
 }  
   
   
   
 void setup()  
 {  
  pinMode(XMASPIN, OUTPUT);  
  pinMode(STATUSPIN, OUTPUT);  
  xmas_fill_color(0,XMAS_LIGHT_COUNT,XMAS_DEFAULT_INTENSITY,XMAS_COLOR_BLACK); //Enumerate all the lights  
  xmas_fill_color(0,XMAS_LIGHT_COUNT,XMAS_DEFAULT_INTENSITY,XMAS_COLOR_BLUE); //Make them all blue  
 }  
 
   
 void loop()  
 {  
  digitalWrite(STATUSPIN,1);  
  xmas_fill_color(0,XMAS_LIGHT_COUNT,XMAS_DEFAULT_INTENSITY,XMAS_COLOR_RED);  
  delay(100);  
  digitalWrite(STATUSPIN,0);  
  xmas_fill_color(0,XMAS_LIGHT_COUNT,XMAS_DEFAULT_INTENSITY,XMAS_COLOR_BLUE);  
  delay(100);  
 }   
   

13 comments:

  1. Thanks for posting this, especially the timing tweaks. I'm planning to use an Arduino Uno and I don't think I could have figured them out on my own. I'm writing my own Arduino code too, but I don't have my Uno or lights to test with yet. I could post it here if you're interested in another take.

    ReplyDelete
  2. im having some trouble. While running the lights flicker randomly... could this be a timing issue?

    ReplyDelete
  3. I think I've solved the timing issues by using the more precise delay functions in the delay_x library available at http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=665&item_type=project (registration required). The _delay_us() function should give you the more precise timing required. I'll cross-post to darco's blog and doityourselfchristmas.com.

    ReplyDelete
  4. Hi, do you have the code for using the delay_x library? I'm new to Arduino and the environment and not 100% sure about how to include it!

    Tks

    ReplyDelete
  5. You just need to put it in the same folder and then add the following line:
    #include "delay_x.h"

    My code isn't working yet, but a couple people are working on it. I suggest you follow the thread at http://www.doityourselfchristmas.com/forums/showthread.php?t=13062

    ReplyDelete
  6. Hey, I've messed with this code a little. You can get it running without the weird delays using direct port manipulation. I think the arduino digitalWrite command is very slow for something like this.

    Check this out.
    http://arduino.cc/en/Reference/PortManipulation

    ReplyDelete
  7. Hmmm, I'm using this code with the 50 light strand and I wrote a simple chase sequence just to test all the bulb, but I noticed that it skips around and sometime lights two or three bulbs at a time, is this the timing issue you're speaking of?
    I've been trying to change it and still cant figure out why it's doing that.

    ReplyDelete
  8. Hey there,
    I'm very new to arduino, and have no previous programming experience. I picked up an Uno, SF's spectrum shield, and a set of ge's lights. Unfortunately this code is currently beyond me, as I've never done anything like this before, and I can't make the MGSEQ7 work with it. Any help would be appreciated!

    ReplyDelete
  9. Hi Scott,

    I've been using your code for running the GE lights. I've found the timing to be a bit off (If I run in a loop setting the color to 0,0,0 I'll get some flicker on the end of the strand). I've re-written the function to get rid of all loops and function calls (I assumed that the CPU overhead, while very small, may have been affecting the timing. Below is the code I'm running now if you're interested. I get no flicker with it.

    Thanks

    --Richard

    /***********************
    * rkfoote@gmail.com
    * 9/26/2011
    * GE xMas lights controller code
    *
    ************************/
    #define OUTPIN 5
    #define DELAYLONG 16 //DigitalWrite takes ~ 3.4us
    #define DELAYSHORT 6
    #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 SETBULB(byte IOPin, byte Bulb, byte Brightness, byte R, byte G, byte B)
    {

    digitalWrite(IOPin,HIGH);
    delayMicroseconds(DELAYSHORT);

    //Bulb
    if (Bulb & 0x20) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Bulb & 0x10) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Bulb & 0x08) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Bulb & 0x04) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Bulb & 0x02) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Bulb & 0x01) { ONE(IOPin) } else { ZERO(IOPin) };


    //Brightness
    if (Brightness & 0x80) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Brightness & 0x40) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Brightness & 0x20) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Brightness & 0x10) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Brightness & 0x08) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Brightness & 0x04) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Brightness & 0x02) { ONE(IOPin) } else { ZERO(IOPin) };
    if (Brightness & 0x01) { ONE(IOPin) } else { ZERO(IOPin) };

    //Blue
    if (B & 0x8) { ONE(IOPin) } else { ZERO(IOPin) };
    if (B & 0x4) { ONE(IOPin) } else { ZERO(IOPin) };
    if (B & 0x2) { ONE(IOPin) } else { ZERO(IOPin) };
    if (B & 0x1) { ONE(IOPin) } else { ZERO(IOPin) };


    //Green
    if (G & 0x8) { ONE(IOPin) } else { ZERO(IOPin) };
    if (G & 0x4) { ONE(IOPin) } else { ZERO(IOPin) };
    if (G & 0x2) { ONE(IOPin) } else { ZERO(IOPin) };
    if (G & 0x1) { ONE(IOPin) } else { ZERO(IOPin) };

    //Red
    if (R & 0x8) { ONE(IOPin) } else { ZERO(IOPin) };
    if (R & 0x4) { ONE(IOPin) } else { ZERO(IOPin) };
    if (R & 0x2) { ONE(IOPin) } else { ZERO(IOPin) };
    if (R & 0x1) { ONE(IOPin) } else { ZERO(IOPin) };

    digitalWrite(IOPin,LOW);
    delayMicroseconds(40);

    }

    ReplyDelete
  10. Thanks for posting Richard.... runs much smoother

    ReplyDelete
  11. For those who are interested in controlling GE Color Effects lights within the Arduino environment, I have created an Arduino library (http://www.digitalmisery.com/2011/11/ge-color-effects-arduino-library/) and an Arduino-compatible board that is a wireless drop-in replacement for the stock controller (http://www.digitalmisery.com/projects/colornode/). Feel free to use and modify the designs - I hope they can help others get started with these lights.

    ReplyDelete
  12. ge led christmas lights good blog and product to see here i like it and impressed from it so keep it up dear for more

    ReplyDelete
  13. This comment has been removed by the author.

    ReplyDelete