Controlling 6 LED strips

Hi,

We’re looking to create a project using six LPD8806 digitally addressable RGB LED strips, each with approximately 20 - 35 LEDs. We want the LEDs to be fast and responsive, to real-time inputs, and have had a successful test with a single strip of 32 LEDs on the Arduino Uno, having it respond in real time to data received over the serial port. We sent a single byte of data, which represented a audio volume, which controlled the number of LEDs displayed like an equalizer bar. This was fast and responsive.

We then extended the test to three small strips of 10 LEDs, sending three bytes of data in a string, one for each strip. We’re finding that the performance is choppy, although it does appear to work in essence. We’re starting to doubt the feasibility of running this project on an Arduino, as even with a small amount of LEDs we’re struggling. Are we approaching this from the right angle? The code we’re using is posted below.

We would like to do some more complex calculations on the animations, involving trigonmetric functions. Would a Raspberry Pi be a better option? Or an Arduino Mega?

Thanks in advance!

#include "LPD8806.h"
#include "SPI.h"
#include <string.h>

// Example to control LPD8806-based RGB LED Modules in a strip

/*****************************************************************************/

// Number of RGB LEDs in strand:
int nLEDs = 10;

// Chose 2 pins for output; can be any valid output pins:
int dataPinA  = 2;
int clockPinA = 3;

int dataPinB = 4;
int clockPinB = 5;

int dataPinC  = 6;
int clockPinC = 7;

//Define our index array
const int NUMBER_OF_FIELDS = 3;
int fieldIndex = 0;
int thisLevels[NUMBER_OF_FIELDS] = {0, 0, 0};
int prevLevels[NUMBER_OF_FIELDS] = {0, 0, 0};


// First parameter is the number of LEDs in the strand.  The LED strips
// are 32 LEDs per meter but you can extend or cut the strip.  Next two
// parameters are SPI data and clock pins:
LPD8806 stripA = LPD8806(nLEDs, dataPinA, clockPinA);
LPD8806 stripB = LPD8806(nLEDs, dataPinB, clockPinB);
LPD8806 stripC = LPD8806(nLEDs, dataPinC, clockPinC);

// You can optionally use hardware SPI for faster writes, just leave out
// the data and clock pin parameters.  But this does limit use to very
// specific pins on the Arduino.  For "classic" Arduinos (Uno, Duemilanove,
// etc.), data = pin 11, clock = pin 13.  For Arduino Mega, data = pin 51,
// clock = pin 52.  For 32u4 Breakout Board+ and Teensy, data = pin B2,
// clock = pin B1.  For Leonardo, this can ONLY be done on the ICSP pins.
//LPD8806 strip = LPD8806(nLEDs);

void setup() {
  // Start up the LED strip
  stripA.begin();
  stripB.begin();
  stripC.begin();

  // Update the strip, to start they are all 'off'
  stripA.show();
  stripB.show();
  stripC.show();
  
  //start the serial port
  Serial.begin(115200);
}


void loop() {
    while (Serial.available())
    {
      for (fieldIndex = 0; fieldIndex < 3; fieldIndex++) {      
        thisLevels[fieldIndex] = Serial.parseInt();
      }
      
      changeLevel(stripA.Color(0, 0, 255), 10, thisLevels, prevLevels);
      prevLevels[0] = thisLevels[0];
      prevLevels[1] = thisLevels[1];
      prevLevels[2] = thisLevels[2];
    }
}

// Fill the dots progressively along the strip.
void changeLevel(uint32_t c, uint8_t wait, int* thisLevels, int* prevLevels) {
  int i;

  if (thisLevels[0] > prevLevels[0]) {
    for (i=0; i <= thisLevels[0] - prevLevels[0]; i++) {
      stripA.setPixelColor(i + prevLevels[0], stripA.Color(0, 255, 0));
    } 
  } else {
    for (i = prevLevels[0]; i > thisLevels[0]; i--) {
       stripA.setPixelColor(i, stripA.Color(0, 0, 0));
    } 
  }
  
  if (thisLevels[1] > prevLevels[1]) {
    for (i=0; i <= thisLevels[1] - prevLevels[1]; i++) {
      stripB.setPixelColor(i + prevLevels[1], stripB.Color(0, 255, 0));
    } 
  } else {
    for (i = prevLevels[1]; i > thisLevels[1]; i--) {
       stripB.setPixelColor(i, stripB.Color(0, 0, 0));
    } 
  }

  if (thisLevels[2] > prevLevels[2]) {
    for (i=0; i <= thisLevels[2] - prevLevels[2]; i++) {
      stripC.setPixelColor(i + prevLevels[2], stripC.Color(0, 255, 0));
    } 
  } else {
    for (i = prevLevels[2]; i > thisLevels[2]; i--) {
       stripC.setPixelColor(i, stripC.Color(0, 0, 0));
    } 
  }

  stripA.show();
  stripB.show();
  stripC.show();
 
}

The bottleneck seems to be the fact that we're parsing three ints out of the string sent over the serial port. Sending one value and using it for all three strips makes it feel responsive again.

How can we speed this up?

Sorry, we solved this! The problem was in the parsing of the string not being done correctly - we had to clear the serial port after each loop().

Cheers