My old friend Garrett Mace over at MaceTech.com (also @macegr on Twitter) has been tinkering and released his own ShiftBrite RGB LED module. It’s currently out of stock but he says he will have more of them soon. (You can also check out Garrett’s previous DIYs he did on Zedomax.com here)
You can make an easy Knight Rider Scanner with these ShiftBrites that Garrett personally made. The best part about his Knight Rider Scanner (that he made for one of his customers) is the fact that it can use all the colors that RGB can handle, meaning you can make a rainbow too if you wanted to.
Here’s a cool New Years Ball Garrett made with the ShiftBrites, way too cool. (Garrett, next time you tweet me when you make some cool stuff like this!)
After the soldering, I decided to attack a problem that a customer asked me about. He’s working on a Mustang and wants to use ShiftBrites to make a Knight Rider style scanner (2008 TV show version). I wrote some code, it allows any chain length divisible by two, any solid or mixed color, and custom leading and trailing gradients.
Here’ some video of it:
video://www.youtube.com/watch?v=8OVCyp2qzPk
video://www.youtube.com/watch?v=HFqLOHlry7s
Here’s the video of working on his customer Mustang:
video://www.youtube.com/watch?v=SfqmmH8jsjg
Here’s the Arduino code used for it (verified that it works):
#define clockpin 13 // DI
#define enablepin 10 // LI
#define latchpin 9 // EI
#define datapin 11 // CI
#define NumLEDs 16
#define CenterWidth 8
int LEDChannels[NumLEDs * 2][3] = {0};
int SB_CommandMode;
int SB_RedCommand;
int SB_GreenCommand;
int SB_BlueCommand;
// these are small so i'll leave them in RAM, larger data should be moved to PROGMEM
int KittLeadingEdge[] = {600, 400, 200};
int KittTrailingEdge[] = {200, 400, 600};
int KittLeadSize = sizeof(KittLeadingEdge) / sizeof(int);
int KittTrailSize = sizeof(KittTrailingEdge) / sizeof(int);
int KittTotalSize = KittLeadSize + KittTrailSize + CenterWidth;
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);
}
void SB_SendPacket() {
if (SB_CommandMode == B01) {
SB_RedCommand = 127;
SB_GreenCommand = 127;
SB_BlueCommand = 127;
}
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*2;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*2; z++) SB_SendPacket();
delayMicroseconds(15);
digitalWrite(latchpin,HIGH); // latch data into registers
delayMicroseconds(15);
digitalWrite(latchpin,LOW);
}
// Re-use my old array rotating code, but use collapsed fake array to save memory
// (at expense of CPU)
int KittFakeArray(int index) {
if (index >= 0 && index < KittTrailSize) {
return KittTrailingEdge[index];
} else if (index >= KittTrailSize && index < (CenterWidth + KittTrailSize)) {
return 1023;
} else if (index >= (CenterWidth + KittTrailSize) && index < KittTotalSize) {
return KittLeadingEdge[index-CenterWidth-KittTrailSize];
} else {
return 0;
}
}
void NewKittFill(int dir, int FillSpeed, int FadeSteps, int red, int green, int blue) {
int KittFadeFactor = 0;
int revIndex;
for (int FillCount = 0; FillCount < (KittTotalSize+NumLEDs); FillCount++) {
for (int FadeCount = 0; FadeCount < FadeSteps; FadeCount++) {
for (int i = 0; i < NumLEDs; i++) {
KittFadeFactor = ((KittFakeArray(KittTotalSize - FillCount + i)) * (FadeSteps - FadeCount - 1) + (KittFakeArray(KittTotalSize - FillCount - 1 + i)) * (FadeCount)) / (2 * FadeSteps);
if (dir == 0) {
LEDChannels[i][0] = (long) red * KittFadeFactor / 1023;
LEDChannels[i][1] = (long) green * KittFadeFactor / 1023;
LEDChannels[i][2] = (long) blue * KittFadeFactor / 1023;
revIndex = NumLEDs * 2 - i - 1;
LEDChannels[revIndex][0] = LEDChannels[i][0];
LEDChannels[revIndex][1] = LEDChannels[i][1];
LEDChannels[revIndex][2] = LEDChannels[i][2];
} else {
revIndex = NumLEDs - 1 - i;
LEDChannels[revIndex][0] = (long) red * KittFadeFactor / 1023;
LEDChannels[revIndex][1] = (long) green * KittFadeFactor / 1023;
LEDChannels[revIndex][2] = (long) blue * KittFadeFactor / 1023;
LEDChannels[NumLEDs + i][0] = LEDChannels[revIndex][0];
LEDChannels[NumLEDs + i][1] = LEDChannels[revIndex][1];
LEDChannels[NumLEDs + i][2] = LEDChannels[revIndex][2];
}
}
WriteLEDArray();
delay(FillSpeed);
}
}
}
void loop() {
for (int cycles = 1; cycles < 10; cycles++) {
NewKittFill(0, 12, 8, 1023, 0, 0);
delay(200);
NewKittFill(1, 10, 7, 1023, 0, 0);
delay(200);
}
NewKittFill(0, 10, 7, 0, 1023, 0);
delay(300);
NewKittFill(1, 10, 7, 0, 1023, 0);
delay(300);
NewKittFill(0, 10, 7, 0, 0, 1023);
delay(300);
NewKittFill(1, 10, 7, 0, 0, 1023);
delay(300);
NewKittFill(0, 10, 7, 800, 0, 1023);
delay(300);
NewKittFill(1, 10, 7, 800, 0, 1023);
delay(300);
NewKittFill(0, 10, 7, 200, 0, 0);
delay(300);
NewKittFill(1, 10, 7, 200, 0, 0);
delay(300);
}
3 Responses to Arduino Hack – How to Make your Own Knight Rider Scanner!
Leave a Reply

hi i like to know to make my own knigh rider style like the mustang how did u guys solder the leds and stuff can you display the steps and what leds you used etc
i cant really find that board under the sheild to make my own controller from the machtech site can you give details on that too
Well I know the guy personally, actually I hired him for my previous company I used to work for, send me an e-mail and I will send you his email. zedomax at gmail dot com.