Pages: [1]   Go Down
Author Topic: Code for a Hue Ramp using ShiftBrites  (Read 663 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino socks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a chain of 7 ShiftBrite units that I just started playing with. I would like to have them gradually shift through a range of colors that loops seamlessly, each ShiftBrite will be a different hue and the colors move down the line as the animation progresses. (edit: I found a video of the exact effect I am looking for.) Usually I can look through other people's code and learn from there, but this is proving a bit more difficult for me to figure out.

Right now I am using a portion of code from this Spookotron project. The code is working great, and it does cycle through a hue ramp, but it cycles the entire chain of lights at the same time so that all lights are the same color. I would like to have each ShiftBrite be a unique color. Unfortunately using shift registers and LEDs are new to me so I haven't been able to figure out how to approach this.

What's the best way to approach the math behind the color cycles? Either direct help or even just pointing me to a similar project is appreciated.

Below is the code I am currently using. I've stripped it down to just the basics. It runs the hue ramp code stripped from the spookotron project, alternates a backlight, and after 30 seconds shuts itself down using a Pololu power switch.

Code:
#include <Metro.h>

int dataPin   = 11; // DI
int latchPin  = 9; // LI
int enablePin = 10; // EI
int clockPin  = 13; // CI

int backlightPin = 14;
int boostPin = 17;
int shutdownPin = 8;

int backlightState = LOW;

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

Metro shutdownTimer = Metro(30000);
Metro backlightTimer = Metro(5000);


// Color constants
int colors[12][3] =
{
   { 255,    0,    0},  // Red
   {    0, 255,    0},  // Green
   {    0,    0, 255},  // Blue
   { 255,    0, 255},  // Magenta
   { 255, 255,    0},  // Yellow
   { 255,  70,    0},  // Orange
   {  128,    0, 255},  // Purple
   {    0,  45, 255},   // Cyan
   {    0,    0,    0},   // Off (Black?)
   {   50,    0,    0},   // Dim Red
   {    0,   25,    0},   // Dim Green
   {   75,    0,  100}   // Dim Magenta
};

#define red     colors[0]
#define green   colors[1]
#define blue    colors[2]
#define magenta colors[3]
#define yellow  colors[4]
#define orange  colors[5]
#define purple  colors[6]
#define cyan    colors[7]


// Current frame index in animation. This is used as a central clock
// for various functions.
int frameIndex = 0;

int animationColor1[3];
int animationColor2[3];

void setup()
{
   int index;
  
   pinMode(dataPin, OUTPUT);
   pinMode(latchPin, OUTPUT);
   pinMode(enablePin, OUTPUT);
   pinMode(clockPin, OUTPUT);
  
   pinMode(backlightPin, OUTPUT);
   pinMode(boostPin, OUTPUT);
   pinMode(shutdownPin, OUTPUT);

   digitalWrite(latchPin, LOW);
   digitalWrite(enablePin, LOW);
  
   digitalWrite(backlightPin, backlightState);
   digitalWrite(boostPin, LOW);
   digitalWrite(shutdownPin, LOW);

   Serial.begin(9600);
  
   // Clear every ShiftBrite bit. This helps us get out of
   // reset without setting the damnable "test" bit that
   // makes them go crazy
   SB_CommandMode = 0;
   SB_ColorCommand[0] = 0;
   SB_ColorCommand[1] = 0;
   SB_ColorCommand[2] = 0;
   for (index=0; index<10; ++index)
   {
     SB_SendPacket(false);
   }
  
   // Use a bit more current for the blue LEDs as they aren't
   // anywhere near as bright as the green ones. Red is somewhere
   // in the middle.
   SB_CommandMode = B01; // Write to current control registers
   SB_ColorCommand[0] = 50;
   SB_ColorCommand[1] = 10;
   SB_ColorCommand[2] = 100;
  
   for (index=0; index<10; ++index)
   {
     SB_SendPacket(false);
   }
   SB_SendPacket(true);
}

// www.macetech.com code. The only change is to take a bool
// indicating whether to latch the data in place or not.
// Also reordered the colors so we can think in RGB instead
// of BRG!
void SB_SendPacket(boolean latch)
{
   SB_CommandPacket = SB_CommandMode & B11;
   SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_ColorCommand[2] & 1023);
   SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_ColorCommand[0] & 1023);
   SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_ColorCommand[1] & 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);

   if (latch)
   {
      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);
   }
}

// Light up a given color
void SetColor(int r, int g, int b)
{
  int lights;
  
  // There are 7 ShiftBrites in the chain -- update them all
  for (lights=7; lights>=0; --lights)
  {
      // Send the pixel to the device
      SB_ColorCommand[0] = r*4;
      SB_ColorCommand[1] = g*4;
      SB_ColorCommand[2] = b*4;
      
      // If this is the last pixel, then latch the data to
      // update the display
      boolean latch = lights == 0;
      
      SB_CommandMode = B00; // Write to PWM control registers
      SB_SendPacket(latch);
  }
}

void SetLerpColor(int color1[3], int color2[3], int lerp, int lerpMax)
{
   int r = ((lerpMax-lerp)*color1[0] + lerp*color2[0]) / lerpMax;
   int g = ((lerpMax-lerp)*color1[1] + lerp*color2[1]) / lerpMax;
   int b = ((lerpMax-lerp)*color1[2] + lerp*color2[2]) / lerpMax;
  
   SetColor(r, g, b);
}

bool StepAnimation()
{
  // Hue ramping
  int colorIndex = frameIndex / 30;
  SetLerpColor(colors[colorIndex], colors[colorIndex+1], frameIndex % 30, 30);

  if (frameIndex == 269) {
    SetColor(0,0,0);
    return true;
  }
  return false;
}



void loop()
{
  
  if (shutdownTimer.check() == 1) {
    digitalWrite(shutdownPin,HIGH);
  }
  
  if (backlightTimer.check() == 1) {
    backlightState = !backlightState;
    digitalWrite(backlightPin,backlightState);
  }
  
  
  bool done = StepAnimation();
  
  if (done)
  {
    frameIndex = 0;
  }
  else
  {
    ++frameIndex;
  }
  
  delay(25);
}
« Last Edit: May 01, 2011, 07:54:18 pm by red india » Logged

Rahway, NJ
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Timmy!!!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For a quick test I counted from 0 to 2(pi).
Then just set my colors 120 degrees out of phase (3 phase color)

for angle=0 to 6.28 * cycles
Red=1023*(sin(angle)+1)
Geen=1023*(sin(angle+120)+1)
Blue=1023*(sin(angle+240)+1)

Perhaps that will help you.  (Hopefully my math is right, lol)
The angle step size should be increased so each shiftbright won't appear to have the same color.  This depends on how many shiftbrights you have.
Just clock out one word at a time, the shiftbrights will send the data down the line by themselves.

Sorry if I made any mistakes, I'm going by memory.
Logged

Pages: [1]   Go Up
Jump to: