ShiftBrite RGB Mood Light

Not sure if anyone else got in on some of these before they sold out, but I thought I’d post some code in case someone was interested. Basically it picks a random value for each color and then fades to it. The effect is pretty cool. I may make a video if I get a chance. You can check out the module here:

http://macetech.com/blog/node/54

A very good deal compared to similar modules out there and the service was excellent. It’s also pretty cool that you can string them together and they all shift together.

On to the code:

/*
 * ShiftBriteLEDRandom
 * -----------------
 * Fade ShiftBrite RGB LED Module(s) between random colors
 *
 * Created 5/19/2008 by Digger450
 *
 * Adapted from code by Mace @ http://macetech.com
 */

int datapin  = 10; // DI
int latchpin = 11; // LI
int enablepin = 12; // EI
int clockpin = 13; // CI

int colorSelected[3];
boolean fadeComplete = false;

unsigned long SB_CommandPacket;
int SB_CommandMode;
int SB_ColorCommand[3];

void setup()
{
   pinMode(datapin, OUTPUT);
   pinMode(latchpin, OUTPUT);
   pinMode(enablepin, OUTPUT);
   pinMode(clockpin, OUTPUT);

   digitalWrite(latchpin, LOW);
   digitalWrite(enablepin, LOW);
   
   SB_CommandMode = B01; // Write to current control registers
   SB_ColorCommand[0] = 127; // Full current
   SB_ColorCommand[1] = 127; // Full current
   SB_ColorCommand[2] = 127; // Full current
   SB_SendPacket();
   
   randomSeed(analogRead(0));
}

void SB_SendPacket()
{
   SB_CommandPacket = SB_CommandMode & B11;
   SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_ColorCommand[0] & 1023);
   SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_ColorCommand[1] & 1023);
   SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_ColorCommand[2] & 1023);

   shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 24);
   shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 16);
   shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 8);
   shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket);

   delay(1); // adjustment may be necessary depending on chain length
   digitalWrite(latchpin,HIGH); // latch data into registers
   delay(1); // adjustment may be necessary depending on chain length
   digitalWrite(latchpin,LOW);
}

void colorSelect()
{
  for (int i = 0; i <= 2; i++)
  {
    colorSelected[i] = random(1024);
  }
}

void fadeColors()
{
  fadeComplete = true;
    
  for (int i = 0; i <= 2; i++)
  {
    if (SB_ColorCommand[i] < colorSelected[i])
    {
      SB_ColorCommand[i]++;
      fadeComplete = false;
    }
    else if (SB_ColorCommand[i] > colorSelected[i])
    {
      SB_ColorCommand[i]--;
      fadeComplete = false;
    }
  }
    
  SB_CommandMode = B00; // Write to PWM control registers
  SB_SendPacket();
  delay(10);
}

void loop()
{
  if (fadeComplete)
  {
    colorSelect();
  }
  fadeColors();
}

Neat...I had wondered if the Arduino code I posted would actually work. :)

The craziness with left and right shifts was to work around the Arduino's hardcoded 8 bit shift routine. You might get slightly better performance with a custom 32 bit shift. However, there is a need for an Arduino shift function that can do arbitrary bit lengths...lots of neat chips want a non-multiple-of-8 packet.

If you want to fade smoothly between actual RGB colors (choose random R G and B, fade to it) I found it useful to move to floating point calculations. Subtract the three new values from the three old values, then divide each by the number of steps between color fades. Say, 100. Then use that floating point value as an increment, cast to integer before shifting out. Repeat 99 more times. That makes each color fade smoothly to the target color, and arrive at the same time. Interpolation, basically. I should post some code soon, unless you figure it out first.