Driving multiple LED strings using shiftOut

So a few years ago I brought some LED string, with each pixel being individually controllable. But I struggled to get more than one string to work, for power reasons and the fact that naively I was only using the hard SPI bus of an Arduino. Below is something I made and then put under my bed. So it’s time for a revisit and a rethink.

LED BAR

An old LED BAR I had a while ago

The first thing to note is that the hardware SPI based library that I was using works fine. But the Arduino, more specifically the Atmel microprocessor, only has one hardware SPI data line. Which is great for when you’re controlling various devices using a cable select method (where another line is used to indicate which device data is being sent to). This wouldn’t work for me as the LED strings don’t have a cable select (CS). So I think it’s time to move away from this method.

So I’ve hooked up 4 stings in parallel and they work, which is useful to know. Now I’m going to use the shiftOut to move data to a string, or all of them depending which I have hooked up to the data and clock lines. Below is a video and the code.


int clockpin = 7;
int dataPin = 8;
void setup() {
pinMode(clockpin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
shiftOut(dataPin, clockpin, MSBFIRST, 255);
shiftOut(dataPin, clockpin, MSBFIRST, 255);
shiftOut(dataPin, clockpin, MSBFIRST, 255);
delay(1000);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
delay(1000);
shiftOut(dataPin, clockpin, MSBFIRST, 255);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
delay(1000);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
delay(1000);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 255);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
delay(1000);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
delay(1000);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 255);
delay(1000);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
shiftOut(dataPin, clockpin, MSBFIRST, 0);
delay(1000);
}

The above code is a bit like the blink program except it toggles between colours on the RGB string and only lights the first LED of the string. It’s useful but not what I’m looking for.

 

Next I’m going to modify this code so that there is an array (zero indexed) for the values of the RED, GREEN and BLUE for each LED.
#define numleds 8
int RED[numleds];
int GREEN[numleds];
int BLUE[numleds];
With
for (int i = 0; i < numleds; i = i++)
{RED[i]=0;GREEN[i]=0;BLUE[i]=0;}

In the setup section to initialise the data in the array, and I’ve now added an update function which when called will output the string in a serial fashion.
void updatestring() {
for (int i =0;i<numleds;i++)
{
shiftOut(dataPin, clockpin, MSBFIRST, BLUE[i]);
shiftOut(dataPin, clockpin, MSBFIRST, GREEN[i]);
shiftOut(dataPin, clockpin, MSBFIRST, RED[i]);
}
}

Groovy. So here’s some more code for a fade like program, with a video :).

#define numleds 8
int RED[numleds];
int GREEN[numleds];
int BLUE[numleds];
int clockpin = 7;
int dataPin = 8;
void setup()
{
pinMode(clockpin, OUTPUT);
pinMode(dataPin, OUTPUT);
for (int i = 0; i < numleds; i = i++)
{RED[i]=0;GREEN[i]=0;BLUE[i]=0;}
}
void loop() {
for(int l=0;l<256;l++){
for (int i = 0; i < numleds; i = i++) {RED[i]=l;GREEN[i]=l;BLUE[i]=l;} updatestring(); delay(10); } for(int l=255;l>0;l--){
for (int i = 0; i < numleds; i = i++)
{RED[i]=l;GREEN[i]=l;BLUE[i]=l;}
updatestring();
delay(10);
}
}
//update function
void updatestring() {
for (int i =0;i<numleds;i++)
{
shiftOut(dataPin, clockpin, MSBFIRST, BLUE[i]);
shiftOut(dataPin, clockpin, MSBFIRST, GREEN[i]);
shiftOut(dataPin, clockpin, MSBFIRST, RED[i]);
}
}

Now I’m going to adapt the code such that LED’s 0-7 are on the first string, then additional strings for the later LED’s. The code below is where I’m currently at. I’ve proved that it can be done successfully, and now I know this I’ll be implementing this in many future designs. (You can change the update speed at the top to slow it down a bit….)
#define numleds 32
#define ledsperline 8
#define updatespeed 1
//this code is written for 4 lines of serial data!
int RED[numleds];
int GREEN[numleds];
int BLUE[numleds];
//line pin def's
int clockpin1 = 2;
int dataPin1 = 3;
int clockpin2 = 4;
int dataPin2 = 5;
int clockpin3 = 6;
int dataPin3 = 7;
int clockpin4 = 8;
int dataPin4 = 9;
//setup stuff
void setup()
{
pinMode(clockpin1, OUTPUT);
pinMode(dataPin1, OUTPUT);
pinMode(clockpin2, OUTPUT);
pinMode(dataPin2, OUTPUT);
pinMode(clockpin3, OUTPUT);
pinMode(dataPin3, OUTPUT);
pinMode(clockpin4, OUTPUT);
pinMode(dataPin4, OUTPUT);
for (int i = 0; i < numleds; i = i++)
{RED[i]=0;GREEN[i]=0;BLUE[i]=0;}
}
//main loop
void loop() {
for(int l=0;l<32;l++){
RED[l]=l*8+1;BLUE[l]=0;
updatestring();
delay(updatespeed);
}
for(int l=0;l<32;l++){
GREEN[l]=l*8+1;RED[l]=0;
updatestring();
delay(updatespeed);
}
for(int l=0;l<32;l++){
BLUE[l]=l*8+1;GREEN[l]=0;
updatestring();
delay(updatespeed);
}
}
//update function
void updatestring() {
for (int i =0;i<ledsperline;i++)
{
shiftOut(dataPin1, clockpin1, MSBFIRST, BLUE[i]);
shiftOut(dataPin1, clockpin1, MSBFIRST, GREEN[i]);
shiftOut(dataPin1, clockpin1, MSBFIRST, RED[i]);
}
for (int i =0;i<ledsperline;i++)
{
shiftOut(dataPin2, clockpin2, MSBFIRST, BLUE[i+ledsperline]);
shiftOut(dataPin2, clockpin2, MSBFIRST, GREEN[i+ledsperline]);
shiftOut(dataPin2, clockpin2, MSBFIRST, RED[i+ledsperline]);
}
for (int i =0;i<ledsperline;i++)
{
shiftOut(dataPin3, clockpin3, MSBFIRST, BLUE[i+2*ledsperline]);
shiftOut(dataPin3, clockpin3, MSBFIRST, GREEN[i+2*ledsperline]);
shiftOut(dataPin3, clockpin3, MSBFIRST, RED[i+2*ledsperline]);
}
for (int i =0;i<ledsperline;i++)
{
shiftOut(dataPin4, clockpin4, MSBFIRST, BLUE[i+3*ledsperline]);
shiftOut(dataPin4, clockpin4, MSBFIRST, GREEN[i+3*ledsperline]);
shiftOut(dataPin4, clockpin4, MSBFIRST, RED[i+3*ledsperline]);
}
}