Problems with Arduino + ShiftBrites

I'm working on a project involving 20 ShiftBrites controlled by an Arduino Uno and receiving information from a Processing program that analyzes the frequencies of music. I only have 4 of the ShiftBrites so far, and I've been testing my code with them. It was working great when I had all of the ShiftBrites attached with short wires, but I have since spread them out to the actual distance they will be in the final project, about 3 feet apart. Now, they work fine for anywhere from two to fifteen minutes, but eventually they always have the same problem. The first ShiftBrite will continue to work fine, the second will usually go dark, and the third and fourth stay lit forever. They can be reset either by restarting the Processing program or by unplugging the Vin pin from the Arduino and then plugging it back in.

I'm wondering if anybody has had a similar problem, and I believe this to be hardware related in some way because they would work for hours before i lengthened the wire. If anybody has a solution, that would be great, but I would also be happy with a work-around that basically restarts the Processing program without having to manually click stop and then start again, since that resets the lights so they work again.

What are you using as a power source? Are you pulling power from the Vin pin, or sending power from an external supply to the Arduino through the Vin pin? (the second one is correct, you cannot draw much power from the Arduino Vin pin).

Long cables are prone to noise. All the example code on our site continually resets the Command register, which needs to happen before the ShiftBrites can start working again after a glitch.

Please post your code, and maybe some photos of your wiring, and I can provide some suggestions.

So, I'm using a 9 volt, 600 mA power supply through the Arduino and then through Vin.

My Arduino Code is pretty simple, basically just the example given on the Macetech website.

#define clockpin 13 // CI
#define enablepin 10 // EI
#define latchpin 9 // LI
#define datapin 11 // DI

#define NumLEDs 4

int LEDChannels[NumLEDs][3] = {0};
int SB_CommandMode;
int SB_RedCommand;
int SB_GreenCommand;
int SB_BlueCommand;

void setup() {

  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);
}

void SB_SendPacket() {

  if (SB_CommandMode == B01) {
    SB_RedCommand = 120;
    SB_GreenCommand = 100;
    SB_BlueCommand = 100;
  }

  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
  delayMicroseconds(15);
  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
  delayMicroseconds(15);
  digitalWrite(latchpin,LOW);

}
/*
Reads in values from the Serial port until tempArray
is filled, and then writes them to the LEDChannels array.
*/
void loop() {
while (Serial.available() < NumLEDs*3){
  Serial.println(Serial.available());
}

    LEDChannels[0][0] = Serial.read();
    LEDChannels[0][1] = Serial.read();
    LEDChannels[0][2] = Serial.read();
    LEDChannels[1][0] = Serial.read();
    LEDChannels[1][1] = Serial.read();
    LEDChannels[1][2] = Serial.read();
    LEDChannels[2][0] = Serial.read();
    LEDChannels[2][1] = Serial.read();
    LEDChannels[2][2] = Serial.read();
    LEDChannels[3][0] = Serial.read();
    LEDChannels[3][1] = Serial.read();
    LEDChannels[3][2] = Serial.read();
  Serial.flush();

  WriteLEDArray();
  delay(20);
}

My Processing program is long and messy, but it just writes an array of the values for each LED through serial. Here's the part of it that does the writing to the serial:

void draw(){
//Do some stuff to specify the values of output[][]
//...
//...

for (int i =0; i < NumLEDs; i ++){
  for (int j =0; j < 3; j++){
    myPort.write(output[i][j]);
  }
}
delay(20);
}

I'm not sure if I'm resetting the Command register like you said, but if I'm not could you help me do that? I really appreciate your help!

All right, there are a couple things that might help. First, a 9V supply is right at the top end of what you can use with ShiftBrites. We've found that, for some reason, while the ShiftBrites will work at 9V they are more reliable at a lower voltage, such at 6V. One customer even discovered that some problems with long cables went away with a large 5V supply.

Next, your protocol could use a little work. Right now there is no way for your Arduino code to know when a new packet starts, so if you ever get a missed byte on your RS232 connection, it'll be out of sync. A favorite technique is to make sure that your Processing code never sends a number higher than 254, and then you use 255 as a packet start command...basically, every byte you receive, increment a value and dump the data into the array. When you get a 255, reset the index and start over.

Lastly, your code is only sending up to 255 to the LEDs. They can handle up to 1023, so your brightness is far less than it could be. If you multiply the received values by 4, it'll let you access the full scale.

Ok, so I'm trying to use 255 to sync like you suggested, and I know that the Processing program is outputting the values I want because I had it print its outputs. I'm still doing something wrong with my Arduino code though, because even when I tell the ShiftBrites to stay a constant color, they are always flickering between the correct color and another color. This is my updated Arduino code:

#define clockpin 13 // CI
#define enablepin 10 // EI
#define latchpin 9 // LI
#define datapin 11 // DI

#define NumLEDs 4

int LEDChannels[NumLEDs][3] = {0};
int tempArray[NumLEDs*3];
int SB_CommandMode;
int SB_RedCommand;
int SB_GreenCommand;
int SB_BlueCommand;
int index;

void setup() {

  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);
  
}

void SB_SendPacket() {

  if (SB_CommandMode == B01) {
    SB_RedCommand = 120;
    SB_GreenCommand = 100;
    SB_BlueCommand = 100;
  }

  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
  delayMicroseconds(15);
  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
  delayMicroseconds(15);
  digitalWrite(latchpin,LOW);

}
void loop() {
  Serial.flush();
  while(Serial.read()!=255){    //Wait for sync
  }
  while( Serial.available()<NumLEDs*3){
  }
  index = 0;
  while ((index < NumLEDs*3)){
    tempArray[index] = Serial.read();
    index ++;
  }
  for(int i = 0; i<NumLEDs; i++){
    for(int j=0; j<3; j++){
      LEDChannels[i][j] = tempArray[3*i+j]*4;
    }
  WriteLEDArray();
  delay(20);
}
}

And here's part of the Processing code:

void draw(){
//Do some stuff to write the values of output[][]
//...
for (int i =0; i < NumLEDs; i ++){
  for (int j =0; j < 3; j++){
    myPort.write(output[i][j]);
  }
}
myPort.write(255);
delay(20);
}

Is there anything noticeably wrong with this? I haven't been able to try with a different power supply yet, but I'll try to get one tomorrow.

Ok, so I have updates! Now I'm using the USB cable to power the lights, and the problem with the lights freezing up has gone away. This is with the original code I posted, I still haven't gotten the code with the sync bit working. Because I don't have the sync working, I still have weird flickering problems when trying to set the lights to a constant color. Thanks for the suggestion on the power supply though! It has really improved things when the lights are constantly changing and the flickering is not noticeable.