multiple rgb led light fader

This is my first Arduino project and Sketch and I have been helped here by a few over the past weeks (which I’m very grateful for) in getting my idea developed. It’s been a great learning experience for me as I learn to write sketches for my Arduino.
My project is to drive 15 hi-powered RGB leds in a motorized moving shade light art piece. I’m using 2 Adafruit’s TLC5947’s (24 channel PWM) with my Arduino. The program establishes 7 to 10 predefined rgb colors and then randomly assigns them to one of the 15 rgb’s. When assigning the color, it then calls on Led() function to fade between the previous color and then newly assigned color. I’m also doing this “non-block” using the millis() function.

It is working as expected except… that it seems to run slow thru the program (estimate 200 to 300ms) to loop thru the program which results in seeing visible stepping of the fading between colors. I purposely made one of the colors black as a debug feature to see this. The following video here shows the program starting when the code is uploaded to the Arduino. It first turns off all 15 led then waits for the first interval “change_color”. Notice the flashing of all the LED’s.

I’m not sure what I’m doing incorrectly, but I kinda expect the Arduino to execute the program loop faster than this.

Any suggestions would be appreciated. - thanks

Mark

#include <Adafruit_TLC5947.h>

/*
** led light sequencer
** 15 total rgb leds driven by two TLC5947 - program assigns predefined colors randomly to each of the 15
** leds sequentially and also fades between previous color and next color
** written by mark biasotti
** rgb fully on is 0 fully off is 4095 - because I'm using common anode leds and pulling pin high.
**/

// 2 TLC5947 boards = 2 but only using 7 of the 8 rgb channels on board 2
#define totalleds 15

#define data   4
#define clock   5
#define latch   6
#define oe  -1  // set to -1 to not use the enable pin (its optional)
int red, blue, green;
int fadedelay = 0; // define the delay of led fading in ms
#define change_color 15000   // 15 seconds (15000 ms) between changing colours 
#define fademultipler 100  // multiplies rate of count to fade leds (0-5000)

unsigned long prev_time_ch[15];//stores time (in ms)for countdown timer for  each of the 15 leds

Adafruit_TLC5947 tlc = Adafruit_TLC5947(totalleds, clock, data, latch);

//structure for storing rgb LED channel information
struct ledstructure {
  int definedr; //stores predefined Red value for channel
  int definedg; //stores predefined green value for channel
  int definedb; //stores predefined blue value for channel
  int currentr = 5000; // stores current red value for channel
  int currentg = 5000; // stores current green value for channel
  int currentb = 5000; // stores current Blue value for channel
} chrgb[totalleds];

// declare structure for rgb variable and array of predefined colors
struct rgbcolor {
  int r;    // red value 0 to 5000
  int g;   // green value
  int b;   // blue value
}
someColors[] = {       // assign pre-defined colors  to structured array
  { 0 , 5000 , 3000 },  // red
  { 5000 , 0 , 5000 },  // green
  { 5000, 5000, 5000},  // black
  { 5000 , 5000 , 0 },  // blue
  { 1200, 5000, 0 },  // magenta
  { 5000 , 0 , 2200 },  // cyan
  { 700, 0 , 5000 },     // yellow
  { 0 , 2400 , 5000 },  // orange
  { 5000 , 0 , 2000 },  // lt-blue
  { 5000 , 0 , 3300 },  // aqua
  { 0 , 5000 , 2600 }   // pink
};

void setup()  {
  Serial.begin(9600);
  Serial.println("led light sequence version 1");
  tlc.begin();
  if (oe >= 0) {
    pinMode(oe, OUTPUT);
    digitalWrite(oe, LOW);
  }
  //cycle thru all LEDS and turn off
  for (uint16_t i = 0; i < totalleds; i++) {
    tlc.setLED(i, 5000 , 5000 , 5000);
    tlc.write();
  }
}

void loop() {
  //trigger color change for Led channel
  for (uint16_t i = 0; i < totalleds; i++) {
    if ((millis() - prev_time_ch[i]) >= change_color) {
      prev_time_ch[i] = millis(); // reset counter
      int whichColor = random(sizeof(someColors) / sizeof(*someColors)); // choose random predefined color
      chrgb[i].definedr = someColors[whichColor].r;  //assigns predefined Red value
      chrgb[i].definedg = someColors[whichColor].g;  //assigns predefined Red value
      chrgb[i].definedb = someColors[whichColor].b;  //assigns predefined Red value
    }
  }
  LED(); //Run the LED Function to check and adjust the values
}

void LED()
{
  //Check Values and adjust "current" Value
  for (uint16_t i = 0; i < totalleds; i++) {
    if (chrgb[i].definedr != chrgb[i].currentr) {
      if (chrgb[i].currentr < chrgb[i].definedr) chrgb[i].currentr = (chrgb[i].currentr + fademultipler);
      if (chrgb[i].currentr > chrgb[i].definedr) chrgb[i].currentr = (chrgb[i].currentr - fademultipler);
    }
    if (chrgb[i].definedg != chrgb[i].currentg) {
      if (chrgb[i].currentg < chrgb[i].definedg) chrgb[i].currentg = (chrgb[i].currentg + fademultipler);
      if (chrgb[i].currentg > chrgb[i].definedg) chrgb[i].currentg = (chrgb[i].currentg - fademultipler);
    }
    if (chrgb[i].definedb != chrgb[i].currentb) {
      if (chrgb[i].currentb < chrgb[i].definedb) chrgb[i].currentb = (chrgb[i].currentb + fademultipler);
      if (chrgb[i].currentb > chrgb[i].definedb) chrgb[i].currentb = (chrgb[i].currentb - fademultipler);
    }
    //Assign modified values to the pwm outputs for each colour led
    tlc.setLED(i, chrgb[i].currentr , chrgb[i].currentg , chrgb[i].currentb);
    tlc.write();
  }
}

define change_color 15000 // 15 seconds (15000 ms) between changing colours

if ((millis() - prev_time_ch*) >= change_color) {* Seems like a long time all the time?

Hi. maby its because you call tlc.Write() 16 times, each time led() is called. you only need to do it once.

its like a buffer first you make all the changes into the buffer. and then you send everything thats inside the buffer.

but now when 1 RGB led has changed settings, you send all! the data.

in your case: 48 channels * 12 bits = 576 a pin goes HIGH or low. but its not 1 pin but 3 HIGH or LOWS every Bit you send. CLOCK DATA CLOCK so 576 * 3 = 1728 high and lows for all the data. for a pin to turn HIGN or LOW takes +-4.5 Micros 1728 * 4.5 = 7776 Micros and you are doing it 16 times 7776 * 16 = 124416 Micros or 124 millis 1000 millis (1sec) / 124 millis to execute 16 time the Write function. means a frame rate of 8FPS

i made a similare system you made. only i can control Variable fadetime, and variable scenetime for each led. and it calculates the differnce between the old value and new value / fadetime to create a fademultiplier. yours are fixed. so you dont need to have prev_time_ch as a Array. its all fixed they change colors all at the same time.

And you're bit banging the control lines

define data 4

define clock 5

define latch 6

instead of using SPI at 8 MHz to send data out. That makes ton of difference there.

AND!!! i see this

#define totalleds 15
Adafruit_TLC5947 tlc = Adafruit_TLC5947(totalleds, clock, data, latch);

Must be

#define NUM_TLC5974 2
Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch);

your saying to the library you used 15 driver so 360! Channels or 120 RGB leds. so when you use tlc.write it send all Data for 15 drivers!

as the sketch says

// How many boards do you have chained?

#define NUM_TLC5974 1

@Spirit

define totalleds 15

Adafruit_TLC5947 tlc = Adafruit_TLC5947(totalleds, clock, data, latch);

thanks for that. Yeah, that's my mistake because I thought that I could replace "NUM_TLC5974" with my own "totalleds" variable - but I can see now that it wrong and reverting back to NUM_TLC5974 = 2 [u]makes a big difference[/u] but still would like it to execute faster. I will make comments elsewhere in this thread as I read comment and make changes.

Thanks

mark

@Spirit,

maby its because you call tlc.Write() 16 times, each time led() is called.
you only need to do it once.

Ah, yes, I see that also. That makes a lot of sense. So I made the following change and it’s made a huge difference - runs much faster now. - thank you.

  //Check Values and adjust "current" Value
  for (uint16_t i = 0; i < totalleds; i++) {
    if (chrgb[i].definedr != chrgb[i].currentr) {
      if (chrgb[i].currentr < chrgb[i].definedr) chrgb[i].currentr = (chrgb[i].currentr + fademultipler);
      if (chrgb[i].currentr > chrgb[i].definedr) chrgb[i].currentr = (chrgb[i].currentr - fademultipler);
    }
    if (chrgb[i].definedg != chrgb[i].currentg) {
      if (chrgb[i].currentg < chrgb[i].definedg) chrgb[i].currentg = (chrgb[i].currentg + fademultipler);
      if (chrgb[i].currentg > chrgb[i].definedg) chrgb[i].currentg = (chrgb[i].currentg - fademultipler);
    }
    if (chrgb[i].definedb != chrgb[i].currentb) {
      if (chrgb[i].currentb < chrgb[i].definedb) chrgb[i].currentb = (chrgb[i].currentb + fademultipler);
      if (chrgb[i].currentb > chrgb[i].definedb) chrgb[i].currentb = (chrgb[i].currentb - fademultipler);
    }
    //Assign modified values to the pwm outputs for each colour led
    tlc.setLED(i, chrgb[i].currentr , chrgb[i].currentg , chrgb[i].currentb);
  }
   tlc.write();
}