Hi all,
I've been working for a while on a project using a few shiftbrites driven by an Arduino Duemilanove, powered via USB (though I've also tried powering the Arduino from a 9v, 1.1a DC wall wart of appropriate polarity). 6 Pots set RGB values for the first and last shiftbrite in the chain. My code then calculates intermediate final RGB values to blend from the first to the last shiftbrite's color. After this is done, I would like to successively fade each shiftbrite from fully off to its final RGB values, one by one.
Unfortunately, I am having trouble with the code for successive fades:
#define clockpin 13 // CI
#define enablepin 10 // EI
#define latchpin 9 // LI
#define datapin 11 // DI
//sets the pin numbers for pots on analog pins 0-3
#define botREDPin 0
#define botGRNPin 1
#define botBLUPin 2
#define topREDPin 3
#define topGRNPin 4
#define topBLUPin 5
#define NumLEDs 6
int LEDChannels[NumLEDs][3] = {0};
float floatLEDChannels[NumLEDs][3] = {0};
float tempLEDChannels[NumLEDs][3] = {0};
int iterationCount [NumLEDs] = {0};
float interval [NumLEDs][3] = {0};
int SB_CommandMode;
int SB_RedCommand;
int SB_GreenCommand;
int SB_BlueCommand;
void setup() {
pinMode(buttonpin, INPUT);
pinMode(datapin, OUTPUT);
pinMode(latchpin, OUTPUT);
pinMode(enablepin, OUTPUT);
pinMode(clockpin, OUTPUT);
SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(0<<SPR0);
digitalWrite(latchpin, LOW);
digitalWrite(enablepin, LOW);
Serial.begin(9600); //for serial debugging
}
void SB_SendPacket() {
if (SB_CommandMode == B01) {
SB_RedCommand = 127;
SB_GreenCommand = 120;
SB_BlueCommand = 120;
}
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)));
}
void WriteLEDArray() {
SB_CommandMode = B00; // Write to PWM control registers
for (int h = 0; h < NumLEDs; h++) {
SB_RedCommand = LEDChannels[h][0];
SB_GreenCommand = LEDChannels[h][1];
SB_BlueCommand = LEDChannels[h][2];
SB_SendPacket();
}
delayMicroseconds(15);
digitalWrite(latchpin,HIGH); // latch data into registers
digitalWrite(enablepin, HIGH); // toggle enable pin simultaneously with latch to attempt flicker-free fading
delayMicroseconds(15);
digitalWrite(enablepin, LOW);
digitalWrite(latchpin,LOW);
SB_CommandMode = B01; // Write to current control registers
for (int z = 0; z < NumLEDs; z++) SB_SendPacket();
delayMicroseconds(15);
digitalWrite(latchpin,HIGH); // latch data into registers
digitalWrite(enablepin, HIGH); // toggle enable pin simultaneously with latch to attempt flicker-free fading
delayMicroseconds(15);
digitalWrite(enablepin, LOW);
digitalWrite(latchpin,LOW);
}
//function to compute fade values for all shiftbrites between top and bottom. Based on mace's "fadeLED" function from
//http://www.arduno.cc/cgi-bin/yabb2/YaBB.pl?num=1243821279
void setBetweenLEDs(int r1, int g1, int b1, int r2, int g2, int b2) {
int steps = NumLEDs - 1;
for (int channel = 0; channel < NumLEDs; channel++)
{
floatLEDChannels[channel][0] = (r1 * (steps - channel) + r2 * channel) / steps;
floatLEDChannels[channel][1] = (g1 * (steps - channel) + g2 * channel) / steps;
floatLEDChannels[channel][2] = (b1 * (steps - channel) + b2 * channel) / steps;
// set iteration count per shiftbrite from greatest R, G, or B value
iterationCount[channel] = max(floatLEDChannels[channel][0], max(floatLEDChannels[channel][1], floatLEDChannels[channel][2]));
// calculate intervals
interval[channel][0] = floatLEDChannels[channel][0] / iterationCount[channel];
interval[channel][1] = floatLEDChannels[channel][1] / iterationCount[channel];
interval[channel][2] = floatLEDChannels[channel][2] / iterationCount[channel];
//// for serial debug: print iteration increment and intervals per shiftbrite
//Serial.print("Shiftbrite");
//Serial.print(channel+1);
//Serial.print(" iteration increment");
//Serial.print(" = ");
//Serial.println(iterationCount[channel]);
//Serial.print("interval0 = ");
//Serial.println(interval[channel][0],4);
//Serial.print("interval1 = ");
//Serial.println(interval[channel][1],4);
//Serial.print("interval2 = ");
//Serial.println(interval[channel][2],4);
//Serial.println();
//Serial.println();
//Serial.println();
}
}
void loop() {
int onTime = 200;
int r1 = analogRead(botREDPin); // Read the bottom red pot value
int g1 = analogRead(botGRNPin); // Read the bottom green pot value
int b1 = analogRead(botBLUPin); // Read the bottom blue pot value
int r2 = analogRead(topREDPin); // Read the top red pot value
int g2 = analogRead(topGRNPin); // Read the top green pot value
int b2 = analogRead(topBLUPin); // Read the top blue pot value
setBetweenLEDs(r1, g1, b1, r2, g2, b2); //sets post-fade maximum rgb values for all shiftbrite LEDs to temporary variables
// show shiftbrite final value colors according to the RGB pots A0-A5
for (int i = 0; i < NumLEDs; i++)
{
LEDChannels[i][0] = floatLEDChannels[i][0];
LEDChannels[i][1] = floatLEDChannels[i][1];
LEDChannels[i][2] = floatLEDChannels[i][2];
WriteLEDArray();
}
////for serial debug: print final RGB values per shiftbrite
//for (int i = 0; i < NumLEDs; i++) {
// Serial.println();
// Serial.print("LED");
// Serial.print(i+1);
// Serial.print(" = ");
// Serial.println();
// for (int j = 0; j < 3; j++) {
// Serial.print(floatLEDChannels[i][j]);
// Serial.println("");
// }
//}
//Serial.println("");
//Serial.println("");
delay(1000);
//sets all shiftbrite LEDS to OFF before fade-in sequence
for (int i = 0; i < NumLEDs; i++) {
for (int j = 0; j < 3; j++) {
LEDChannels[i][j] = 0;
tempLEDChannels[i][j] = 0;
WriteLEDArray();
}
}
for (int m = 0; m < NumLEDs; m++) {
for (int n = 0; n < iterationCount[m]; n++) {
tempLEDChannels[m][0] += interval[m][0];
tempLEDChannels[m][1] += interval[m][1];
tempLEDChannels[m][2] += interval[m][2];
LEDChannels[m][0] = tempLEDChannels[m][0];
LEDChannels[m][1] = tempLEDChannels[m][1];
LEDChannels[m][2] = tempLEDChannels[m][2];
////for serial debug
//Serial.println();
//Serial.print("tempLEDchannel");
//Serial.print(m+1);
//Serial.print(" = ");
//Serial.println();
//for (int j = 0; j < 3; j++) {
// Serial.print(tempLEDChannels [m][j],4);
// Serial.println("");
// }
//
//Serial.println("");
//Serial.println("");
//
//Serial.println();
//Serial.print("LEDchannel");
//Serial.print(m+1);
//Serial.print(" = ");
//Serial.println();
//for (int j = 0; j < 3; j++) {
// Serial.print(LEDChannels [m][j],4);
// Serial.println("");
// }
//
//Serial.println("");
//Serial.println("");
WriteLEDArray();
delayMicroseconds(onTime);
}
}
}
So, I'm getting appropriate numbers for my final RGB values and "iterationCounts"when I print them via serial. But in the fade-in for loop, when the "tempLEDChannels" values are stored in the final "LEDChannels" arrays, a couple really odd things happen.
First, the "LEDChannels" values for the R, G, or B channel corresponding to the iteration count (the greatest of the R, G, and B values) does not increment with its "tempLEDChannels" counterpart; it jumps periodically by a seemingly arbitrary and increasing amount every few iterations, with a max "tempLEDChannels" value of 1019 yielding a final value of 33323 for its respective "LEDChannels" counterpart.
Second, when the serial print statements are commented out as above, the main loop repeats, but the final RGB values for all but the first and last shiftbrites are full white after they fade in.
I've tried a bunch of different tweaks to the code to try and solve the problems, but I can't seem to get it functioning properly. Looking at my code, can anyone give suggestions to get it working as I want it to, or suggest alternative approaches that my work better or more efficiently?