Shiftbrite Fading

I am a newbie so I don't fulling understand all the concepts yet.

I am using the following code (slightly modified from http://arduino.cc/forum/index.php/topic,15963.0.html) to fade my shiftbrites. The original code cycles very fast. I tried to slow it down by increasing the delay. That worked but now it looks like it is stepping from each color instead of a nice smooth fade. I assumed I could change the void fadeall i to a higher number thus sampling more. But this caused the stepping. Any ideas?

// Defines for use with Arduino functions
#define clockpin   13 // CL
#define enablepin  10 // BL
#define latchpin    9 // XL
#define datapin    11 // SI

// Defines for direct port access
#define CLKPORT PORTB
#define ENAPORT PORTB
#define LATPORT PORTB
#define DATPORT PORTB
#define CLKPIN  5
#define ENAPIN  2
#define LATPIN  1
#define DATPIN  3

// Variables for communication
unsigned long SB_CommandPacket;
int SB_CommandMode;
int SB_BlueCommand;
int SB_RedCommand;
int SB_GreenCommand;

// Define number of ShiftBrite modules
#define NumLEDs 3

// Create LED value storage array
int LEDChannels[NumLEDs][3] = {0};
int wait = 0;
int rate = 250;

// Set pins to outputs and initial states
void setup() {
  pinMode(datapin, OUTPUT);
  pinMode(latchpin, OUTPUT);
  pinMode(enablepin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(enablepin, LOW);
  SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(0<<SPR0);
}

// Load values into SPI register
void SB_SendPacket() {

    if (SB_CommandMode == B01) {
     SB_RedCommand = 127;
     SB_GreenCommand = 110;
     SB_BlueCommand = 110;
    }

    SPDR = SB_CommandMode << 6 | SB_BlueCommand>>4;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_BlueCommand<<4 | SB_RedCommand>>6;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_RedCommand << 2 | SB_GreenCommand>>8;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_GreenCommand;
    while(!(SPSR & (1<<SPIF)));

}

// Latch values into PWM registers
void SB_Latch() {

  delayMicroseconds(1);
  LATPORT += (1 << LATPIN);
  //ENAPORT += (1 << ENAPIN);
  delayMicroseconds(1);
  //ENAPORT &= ~(1 << ENAPIN);
  LATPORT &= ~(1 << LATPIN);

}

// Send all array values to chain
void WriteLEDArray() {

  SB_CommandMode = B00; // Write to PWM control registers

  for (int i = 0; i<NumLEDs; i++) {
    SB_RedCommand = LEDChannels[i][0] & 1023;
    SB_GreenCommand = LEDChannels[i][1] & 1023;
    SB_BlueCommand = LEDChannels[i][2] & 1023;
    SB_SendPacket();
  }

  SB_Latch();

  SB_CommandMode = B01; // Write to current control registers

  for (int z = 0; z < NumLEDs; z++) SB_SendPacket();

  SB_Latch();

}

// Fade between two colors at specified interval
void fadeall(int fromred, int fromgreen, int fromblue, int tored, int togreen, int toblue) {

 for (int i = 0; i < 33; i++) {

     for (int j1 = 0; j1 < NumLEDs; j1++) {
	 LEDChannels[j1][0] = (fromred * (32 - i) + tored * i)/32;
	 LEDChannels[j1][1] = (fromgreen * (32 - i) + togreen * i)/32;
	 LEDChannels[j1][2] = (fromblue * (32 - i) + toblue * i)/32;
     }

    WriteLEDArray();
    delay(rate);

   }
}

void loop() {

  fadeall(1023,0,0,1023,0,1023); //red to magenta
  delay (wait);
  fadeall(1023,0,1023,0,0,1023); //magenta to blue
  delay (wait);
  fadeall(0,0,1023,0,1023,1023); //blue to cyan
  delay (wait);
  fadeall(0,1023,1023,0,1023,0); //cyan to green
  delay (wait);
  fadeall(0,1023,0,1023,1023,0); //green to yellow
  delay (wait);
  fadeall(1023,1023,0,1023,0,0); //yellow to red


}

The function was designed for quick fades. As you can see it only has a few steps between colors. Also it originally had a rate variable in the function parameters; you've moved that to a global variable??

There is a small performance penalty moving to floating point calculations, but it can really streamline color calculations. The updated function below adds the rate parameter back in, and also adds a steps parameter. Simply call the command with the delay between each color update, and the number of steps you want the fade to have: fadeall(25, 100, 1023, 0, 0, 0, 1023, 0);

// Fade between two colors at specified interval
void fadeall(int rate, int steps, int fromred, int fromgreen, int fromblue, int tored, int togreen, int toblue) {
 
 for (int i = 0; i < (steps+1); i++) {
  
   float fadefactor = i * (1.0/steps);
   
     for (int j1 = 0; j1 < NumLEDs; j1++) {
       LEDChannels[j1][0] = fromred * (1.0 - fadefactor) + tored * fadefactor;
       LEDChannels[j1][1] = fromgreen * (1.0 - fadefactor) + togreen * fadefactor;
       LEDChannels[j1][2] = fromblue * (1.0 - fadefactor) + toblue * fadefactor;
     }
  
    WriteLEDArray();
    delay(rate);
  
   }   
}

Thanks, that looks much better. Would it cause problems to switch the rate and steps to a global variable? That way I can change the values once when trying out different effects? Also, what would be the better performance way to accomplish fading through different colors? Once again thank you for your time and help!!! :smiley:

You could just create a global variable, or a #define, and put that in the fadeall() calls instead of modifying the function.

Better performance would be integer math only, maybe some kind of efficient linear interpolation algorithm, but I haven't figured out a cure-all solution. The floating point solution is not really that bad, and you can probably keep using it forever.