When I connect chain of LED strips to power from both ends, do I need to make the power line disconnect in the middle?

Like this?
I added msLastSparkle and msSparkleTime variables.

#define NUMPIXELS 4320 // Number of LEDs in strip


//-------------------------------------------------------------------
// Here's how to control the LEDs from SPI pins (Hardware SPI):
//-------------------------------------------------------------------
// Hardware SPI is a little faster, but must be wired to specific pins
// (Core/Photon/P1/Electron = pin A5 for data, A3 for clock)

#define DATAPIN   A5
#define CLOCKPIN  A3
uint32_t pxBuffer[1 + NUMPIXELS + NUMPIXELS/16 + 1]; // element 0 (leadin) ... LEDs ... 1 leadout clock per 2 LEDs (ceil)

struct ANIMATION_DATA
{
  uint8_t g;
  uint8_t b;
  uint8_t r;
  int     pos;
  int     len;
};

// circular buffer with 100 slots will overwrite unfinished animations when full
const int      maxAnim  = 100;
int            animHead = 0;
int            animTail = 0;
ANIMATION_DATA anim[maxAnim];


const uint8_t  brightAnim[] = 
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
, 255, 255, 255, 255, 255, 255, 255, 255, 245, 240
, 240, 240, 240, 235, 230, 230, 230, 230, 225, 220
, 220, 220, 220, 215, 210, 210, 210, 210, 205, 200
, 200, 200, 200, 200, 195, 195, 190, 190, 190, 190
, 190, 195, 180, 180, 180, 175, 170, 165, 160, 155
, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105
, 100,  95,  90,  85,  80,  75,  70 
};

const int      cometLen = sizeof(brightAnim) / sizeof(brightAnim[0]);
const uint32_t msRefresh = 10;
const int stepSpeed = 5;
static int animationStep = 0;

const uint32_t msSparkleTime = 0;
uint32_t msLastSparkle = 0;



//Set Color of pixel at position px, including brightness level
uint32_t setAPA102Color(int px, uint8_t g, uint8_t b, uint8_t r, uint8_t brightness = 31) {
  uint32_t color = 0;

  brightness = map(brightness, 0, 255, 0, 31);  // only the bottom 5 bits available resuliting in 32 discrete levels
  
  // due to big endianness in revers order 
  color |= (brightness <<   0) | 0xE0;  //top 3 bits must be 111
  color |= (r          <<   8);
  color |= (g          <<  16);
  color |= (b          <<  24);

  if (0 <= px && px < NUMPIXELS) {
    return pxBuffer[px] = color;
  }

  return -1;
}

bool needRefresh = true;
volatile bool canRefresh = true;

void refreshDone() {
  canRefresh = true;
}


void setup()
{
  memset(anim, 0, sizeof(anim));
  memset(pxBuffer, 0xE0, NUMPIXELS*4);
  SPI.begin();
  SPI.setClockSpeed(8, MHZ);
  //SPI.setDataMode(0);
  SPI.setBitOrder(MSBFIRST);
  
  Particle.function("led", addComet);
}

void loop()
{
  static uint32_t msDelay = 0;
  if (millis() - msDelay < msRefresh) return;
  msDelay = millis();
  
  static bool sparkleState = false;
  static int  sparklePixel = 0;
  
  if (animHead != animTail)
  {
    ANIMATION_DATA *a;
    for (int animationStep = animTail; animationStep != animHead; ) 
    {
      a = &anim[animationStep];
      if (a->len)
      {
        int px;

        //Draw the Comet
        for (int p = a->len - 1; p >= 0; p--)
        {
          px = constrain(a->pos - p, 0, NUMPIXELS - 1);
          setAPA102Color(px, a->g, a->r, a->b, brightAnim[p]);
        }

        //Erase the pixels behind comet as it moves forward  
        if (a->pos - a->len >= 0)
          for (int k = 0; k <= stepSpeed; k++)
            setAPA102Color(a->pos - k - a->len, 0, 0, 0, 0);

        //Make comet jump forward stepSpeed pixels at a time to make comet run seemingly faster
        if (a->pos < NUMPIXELS + stepSpeed)
          a->pos += stepSpeed;
        else
          a->len -= stepSpeed;

        if (a->len <= 0)
        {
          *a = { 0, 0, 0, 0, 0 };
          animTail++;
          animTail %= maxAnim;
        }
      }

      animationStep++;
      animationStep %= maxAnim;
    }
    needRefresh = true;
  }

  if (millis() - msLastSparkle >= msSparkleTime) {
    msLastSparkle = millis();
    sparkleState = !sparkleState;  // flip state
    if (sparkleState)
    {
      sparklePixel = random(NUMPIXELS);
      setAPA102Color(sparklePixel, random(255), random(255), random(255), 100);
    }
    else
    {
      setAPA102Color(sparklePixel, 0, 0, 0, 0);
    }
    needRefresh = true;
  }
    
  
  if (needRefresh && canRefresh) {
      canRefresh =
      needRefresh = false;
      SPI.transfer(pxBuffer, NULL, sizeof(pxBuffer), refreshDone);
  }

}

struct topic {
  char    title[16];
  uint8_t rgb[3];
};

const topic topicList[] = 
{ { "login"  , { 200, 200, 200 } }  // white
, { "idea"   , { 255,   0, 255 } }  // yellow
, { "comment", {   0, 255,   0 } }  // blue
, { "outcome", { 255,   0,   0 } }  // green
, { "project", { 255,   0,   0 } }  // green
, { "status" , { 100,   0, 255 } }  // orange
, { "step"   , {   0, 255,  75 } }  // purple
, { "vote"   , {   0,   0, 255 } }  // red
, { "view"   , { 105, 200, 255 } }  // pink
};

const int   topics = sizeof(topicList)/sizeof(topicList[0]);


//Add a comet to the strip whenever initated by cloud event
int addComet(String command)
{
  int retVal = -1;

  for (int i = 0; i < topics; i++)
  {
    if (strcmp((const char*)command, topicList[i].title) == 0)
    {
      anim[animHead] = { topicList[i].rgb[0], topicList[i].rgb[1], topicList[i].rgb[2], 0, cometLen };
      Particle.publish(command);
      animHead++;
      animHead %= maxAnim;
      retVal = i;
      break;
    }
  }
  return retVal;
}
1 Like

Looks good

I want to run this animation across a very long continuous line of Dotstar strips.

The distance is about 100 feet. I’m going to use 144/m strips.
That turns out to be 5,040 LEDs…

Looks like I need 5,040 X 60mAmps = 302,400 mAmps of power (302.4 Amps).

What is the best way to power this long strip of LEDs?
I’ve found 60Amp 5V power supplies…would multiple of these work best?

Why is the sparkle in the background sometimes not work? It comes on but then at some periods, the sparkle completely turn off…

I just wanted to make sure you are aware that if you found say a ~300A 5v power supply, you cannot use 14 AWG wire running 100' along its length connected at multiple points like the scenario listed earlier in this post. That scenario is for short runs with that size gauge wire.

For instance, lets say we just want to use one 15M led strip 100' away from the power supply. Displaying white draws about 3A, so using the Voltage Drop calculator chipmc linked to, Using 100' of 14 AWG wire, the voltage at the end would be 3.48v. You would need at least 5 AWG just to get 4.81V at the end. 200' (100' Red / 100' Black) is going to be big bucks.

You are better off, (if possible) getting several power supply's and placing them along its run, and using the 14 AWG wire for powering several strips like the example above. Just remember that the GND of ALL the strips need to be tied together.

2 Likes

Hard to tell from my perspective, since I haven’t built a full blown setup, so debugging is probably done best on your side.
But when you talk about 5000+ LEDs and you (possibly) haven’t wired them all in yet, then the sparkle might just be at some blind spot.

Ah, thanks for letting me know about the need for a larger wire for a larger power supply to travel a long distance. I agree, that doesn’t seem realistic.

I’ll stick to the several smaller power supplies.

You mentioned a 15M led strip. Do those exist or was that just used as an example? Right now, I’m using just DotStar strips and they come in just 1-meter lengths. Is is possible to get a longer length of LED strip? I’m okay at soldering, but I have damaged solder pads before and want to stay away from ruining any strips if possible, since I need a large supply of them.

Sorry, I meant to say 5M length the standard size. Google APA102C and you'll be given a plethora of places to get it.
places like Adafruit will rape you blind in the cost for them.
Here is my set on my garage door.

2 Likes

Thanks for the info! Where did you get yours? I’m not finding that length as easily…

Are yours 144LEDs/meter?

I am so sorry, I meant to say 5M is the standard. I got mine from a china suppler which has long since gone.
If you find the right suppler, you they will allow you to select many different options, like leds per meter, silicone sealed or in the silicone tube, white PCB strip or black and so on.

https://www.ebay.com/sch/i.html?_from=R40&_trksid=p2380057.m570.l1313.TR0.TRC0.H0.XAPA102C.TRS0&_nkw=APA102C&_sacat=0

https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20180207144525&origin=y&SearchText=APA102C

1 Like

How would I slow down the sparkle? I.e. Make the sparkle flash less quickly without slowing down the comet animation.

I am running the following code: The comet animation really slows down by a lot at some points and then speeds back up again (really fast). How can I keep the animation from slowing down?

#define NUMPIXELS 4320 // Number of LEDs in strip


//-------------------------------------------------------------------
// Here's how to control the LEDs from SPI pins (Hardware SPI):
//-------------------------------------------------------------------
// Hardware SPI is a little faster, but must be wired to specific pins
// (Core/Photon/P1/Electron = pin A5 for data, A3 for clock)
// Yellow: clock   Green: data

#define DATAPIN   A5
#define CLOCKPIN  A3
uint32_t pxBuffer[1 + NUMPIXELS + NUMPIXELS/16 + 1]; // element 0 (leadin) ... LEDs ... 1 leadout clock per 2 LEDs (ceil)


// Compensate for frequency variation among strips {r, g, b}
#define STRIP_COUNT NUMPIXELS/144
float gamma_s0[ 3 ] = { 1.0, 1.0, 1.0 }; //no change
float gamma_s1[ 3 ] = { 0.4, 0.9, 1.0 }; //less green
float gamma_s2[ 3 ] = { 0.8, 0.2, 0.2 }; //less red and blue
float gamma_s3[ 3 ] = { 0.6, 0.4, 0.3 }; // ,g,


float* gamma[ STRIP_COUNT ] = {
    gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0,
    gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0,
    gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0
};

//ADD MORE VALUES IF LENGTH OF STRIP INCREASES
int strip_position[ STRIP_COUNT ] = {
       0,  144,  288,  432,  576,  720,  864, 1008, 1152, 1296,
    1440, 1584, 1728, 1872, 2016, 2160, 2304, 2448, 2592, 2736,
    2880, 3024, 3168, 3312, 3456, 3600, 3744, 3888, 4032, 4176
};

uint8_t red_for_pixel ( int p, int n ) {
float* ga;
  for (int i = 0; i < STRIP_COUNT; i++) {
    if (p >= strip_position[i] && p < strip_position[i+1])  {
      ga = gamma[ i ];
    }
  }
  
  int r = n * ga[ 0 ];
  
  return r;
}

uint8_t green_for_pixel ( int p, int n ) {
    int i;
    for ( i=0 ; p < strip_position[ i ] ; i++ ) {}
    float* ga = gamma[ i ];
    
    int g = n * ga[ 1 ];
    
    return g;
}

uint8_t blue_for_pixel ( int p, int n ) {
    int i;
    for ( i=0 ; p < strip_position[ i ] ; i++ ) {}
    float* ga = gamma[ i ];
    
    int b = n * ga[ 2 ];
    
    return b;
}


struct ANIMATION_DATA
{
  uint8_t g;
  uint8_t b;
  uint8_t r;
  int     pos;
  int     len;
};

// circular buffer with 100 slots will overwrite unfinished animations when full
const int      maxAnim  = 200;
int            animHead = 0;
int            animTail = 0;
ANIMATION_DATA anim[maxAnim];


const uint8_t  brightAnim[] = 
{ 255, 255, 255 
, 255, 255, 255
, 255, 255, 255
, 255, 255, 255
, 240, 240, 240
, 220, 220, 220
, 200, 200, 190
, 180, 165, 140
, 120, 100,  90
,  80,  70,  50
};

const int      cometLen = sizeof(brightAnim) / sizeof(brightAnim[0]);


const uint32_t msRefresh = 10;
const int stepSpeed = 2;
const float bright_percent = .1; //percent in decimal form


static int animationStep = 0;


//Set Color of pixel at position px, including brightness level
uint32_t setAPA102Color(int px, uint8_t g, uint8_t b, uint8_t r, uint8_t brightness = 255) {
  uint32_t color = 0;

  brightness = map(brightness, 0, 255, 0, 31);  // only the bottom 5 bits available resulting in 32 discrete levels
  
  // due to big endianness in revers order 
  color |= (brightness <<   0) | 0xE0;  //top 3 bits must be 111
  color |= (r          <<   8);
  color |= (g          <<  16);
  color |= (b          <<  24);

  if (0 <= px && px < NUMPIXELS) {
    return pxBuffer[px] = color;
  }

  return -1;
}

bool needRefresh = true;
volatile bool canRefresh = true;

void refreshDone() {
  canRefresh = true;
}


void setup()
{
  memset(anim, 0, sizeof(anim));
  memset(pxBuffer, 0xE0, NUMPIXELS*4);
  SPI.begin();
  SPI.setClockSpeed(8, MHZ);
  SPI.setDataMode(0);
  SPI.setBitOrder(MSBFIRST);
  
  Particle.function("led", addComet);
}

void loop()
{
  static uint32_t msDelay = 0;
  if (millis() - msDelay < msRefresh) return;
  msDelay = millis();
  
  static bool sparkleState = false;
  static int  sparklePixel = 0;
  
  if (animHead != animTail)
  {
    ANIMATION_DATA *a;
    for (int animationStep = animTail; animationStep != animHead; ) 
    {
      a = &anim[animationStep];
      if (a->len)
      {
        int px;

        //Draw the Comet
        for (int p = a->len - 1; p >= 0; p--)
        {
          px = constrain(a->pos - p, 0, NUMPIXELS + cometLen);

          if (p < 1) {
            setAPA102Color(px, green_for_pixel(px, 255), red_for_pixel(px, 255), blue_for_pixel(px, 255), brightAnim[p]*bright_percent);
          } else if (p < 3) {
            setAPA102Color(px, green_for_pixel(px, a->g) + ((green_for_pixel(px, 255)-green_for_pixel(px, a->g))*.5), red_for_pixel(px, a->r) + ((red_for_pixel(px, 255)-red_for_pixel(px, a->r))*.5), blue_for_pixel(px, a->b) + ((blue_for_pixel(px, 255)-blue_for_pixel(px, a->b))*.5), brightAnim[p]*bright_percent);
          } else if (p < 5) {
            setAPA102Color(px, green_for_pixel(px, a->g) + ((green_for_pixel(px, 255)-green_for_pixel(px, a->g))*.1), red_for_pixel(px, a->r) + ((red_for_pixel(px, 255)-red_for_pixel(px, a->r))*.1), blue_for_pixel(px, a->b) + ((blue_for_pixel(px, 255)-blue_for_pixel(px, a->b))*.1), brightAnim[p]*bright_percent);
          } else {
            setAPA102Color(px, green_for_pixel(px, a->g), red_for_pixel(px, a->r), blue_for_pixel(px, a->b), brightAnim[p]*bright_percent);
          }
          
        }

        //Erase the pixels behind comet as it moves forward  
        if (a->pos - a->len >= 0)
          for (int k = 0; k <= stepSpeed; k++)
            setAPA102Color(a->pos - k - a->len, 0, 0, 0, 0);

        //Make comet jump forward stepSpeed pixels at a time to make comet run seemingly faster
        if (a->pos < NUMPIXELS + cometLen)
          a->pos += stepSpeed;
        else
          a->len -= stepSpeed;

        if (a->len <= 0)
        {
          *a = { 0, 0, 0, 0, 0 };
          animTail++;
          animTail %= maxAnim;
        }
      }

      animationStep++;
      animationStep %= maxAnim;
    }
    needRefresh = true;
  }

  sparkleState = !sparkleState;  // flip state
  if (sparkleState)
  {
    sparklePixel = random(NUMPIXELS);
    setAPA102Color(sparklePixel, random(255), random(255), random(255), 50);
    needRefresh = true;
  }
  else
  {
    setAPA102Color(sparklePixel, 0, 0, 0, 0);
    needRefresh = true;
  }
    
  
  if (needRefresh && canRefresh) {
      canRefresh =
      needRefresh = false;
      SPI.transfer(pxBuffer, NULL, sizeof(pxBuffer), refreshDone);
  }

}

struct topic {
  char    title[16];
  uint8_t rgb[3];
};

const topic topicList[] = 
{ { "login"  , { 255, 255, 255 } }  // white
, { "idea"   , { 255,   0, 255 } }  // yellow
, { "comment", {   0, 255,   0 } }  // blue
, { "outcome", { 255,   0,   0 } }  // green
, { "project", { 255,   0,   0 } }  // green
, { "status" , { 100,   0, 255 } }  // orange
, { "step"   , {   0, 255,  75 } }  // purple
, { "vote"   , {   0,   0, 255 } }  // red
, { "view"   , { 105, 200, 255 } }  // pink
};

const int   topics = sizeof(topicList)/sizeof(topicList[0]);


//Add a comet to the strip whenever initated by cloud event
int addComet(String command)
{
  int retVal = -1;

  for (int i = 0; i < topics; i++)
  {
    if (strcmp((const char*)command, topicList[i].title) == 0)
    {
      anim[animHead] = { topicList[i].rgb[0], topicList[i].rgb[1], topicList[i].rgb[2], 0, cometLen };
      Particle.publish(command);
      animHead++;
      animHead %= maxAnim;
      retVal = i;
      break;
    }
  }
  return retVal;
}

I have a continuous strip of 4,320 LEDs (30m). Upon an event occurring in the cloud, a ā€˜comet’ will run the full length of the strip. However, when there are a lot of comets running, the entire animation begins to drastically slow down. Is there any way for me to keep this animation from slowing down?

Here is my code:

#define NUMPIXELS 4320 // Number of LEDs in strip


//-------------------------------------------------------------------
// Here's how to control the LEDs from SPI pins (Hardware SPI):
//-------------------------------------------------------------------
// Hardware SPI is a little faster, but must be wired to specific pins
// (Core/Photon/P1/Electron = pin A5 for data, A3 for clock)
// Yellow: clock   Green: data

#define DATAPIN   A5
#define CLOCKPIN  A3
uint32_t pxBuffer[1 + NUMPIXELS + NUMPIXELS/16 + 1]; // element 0 (leadin) ... LEDs ... 1 leadout clock per 2 LEDs (ceil)


// Compensate for frequency variation among strips {r, g, b}
#define STRIP_COUNT NUMPIXELS/144
float gamma_s0[ 3 ] = { 1.0, 1.0, 1.0 }; //no change
float gamma_s1[ 3 ] = { 0.4, 0.9, 1.0 }; //less green
float gamma_s2[ 3 ] = { 0.8, 0.2, 0.2 }; //less red and blue
float gamma_s3[ 3 ] = { 0.6, 0.4, 0.3 }; // ,g,


float* gamma[ STRIP_COUNT ] = {
    gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0,
    gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0,
    gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0, gamma_s0
};

//ADD MORE VALUES IF LENGTH OF STRIP INCREASES
int strip_position[ STRIP_COUNT ] = {
       0,  144,  288,  432,  576,  720,  864, 1008, 1152, 1296,
    1440, 1584, 1728, 1872, 2016, 2160, 2304, 2448, 2592, 2736,
    2880, 3024, 3168, 3312, 3456, 3600, 3744, 3888, 4032, 4176
};

uint8_t red_for_pixel ( int p, int n ) {
float* ga;
  for (int i = 0; i < STRIP_COUNT; i++) {
    if (p >= strip_position[i] && p < strip_position[i+1])  {
      ga = gamma[ i ];
    }
  }
  
  int r = n * ga[ 0 ];
  
  return r;
}

uint8_t green_for_pixel ( int p, int n ) {
    int i;
    for ( i=0 ; p < strip_position[ i ] ; i++ ) {}
    float* ga = gamma[ i ];
    
    int g = n * ga[ 1 ];
    
    return g;
}

uint8_t blue_for_pixel ( int p, int n ) {
    int i;
    for ( i=0 ; p < strip_position[ i ] ; i++ ) {}
    float* ga = gamma[ i ];
    
    int b = n * ga[ 2 ];
    
    return b;
}


struct ANIMATION_DATA
{
  uint8_t g;
  uint8_t b;
  uint8_t r;
  int     pos;
  int     len;
};

// circular buffer with 100 slots will overwrite unfinished animations when full
const int      maxAnim  = 100;
int            animHead = 0;
int            animTail = 0;
ANIMATION_DATA anim[maxAnim];


const uint8_t  brightAnim[] = 
{ 255, 255, 255 
, 255, 255, 255
, 255, 255, 255
, 255, 255, 255
, 240, 240, 240
, 220, 220, 220
, 200, 200, 190
, 180, 165, 140
, 120, 100,  90
,  80,  70,  50
};

const int      cometLen = sizeof(brightAnim) / sizeof(brightAnim[0]);


const uint32_t msRefresh = 10;
const int stepSpeed = 2;
const float bright_percent = .1; //percent in decimal form


static int animationStep = 0;


//Set Color of pixel at position px, including brightness level
uint32_t setAPA102Color(int px, uint8_t g, uint8_t b, uint8_t r, uint8_t brightness = 255) {
  uint32_t color = 0;

  brightness = map(brightness, 0, 255, 0, 31);  // only the bottom 5 bits available resulting in 32 discrete levels
  
  // due to big endianness in revers order 
  color |= (brightness <<   0) | 0xE0;  //top 3 bits must be 111
  color |= (r          <<   8);
  color |= (g          <<  16);
  color |= (b          <<  24);

  if (0 <= px && px < NUMPIXELS) {
    return pxBuffer[px] = color;
  }

  return -1;
}

bool needRefresh = true;
volatile bool canRefresh = true;

void refreshDone() {
  canRefresh = true;
}


void setup()
{
  memset(anim, 0, sizeof(anim));
  memset(pxBuffer, 0xE0, NUMPIXELS*4);
  SPI.begin();
  SPI.setClockSpeed(8, MHZ);
  SPI.setDataMode(0);
  SPI.setBitOrder(MSBFIRST);
  
  Particle.function("led", addComet);
}

void loop()
{
  static uint32_t msDelay = 0;
  if (millis() - msDelay < msRefresh) return;
  msDelay = millis();
  
  static bool sparkleState = false;
  static int  sparklePixel = 0;
  
  if (animHead != animTail)
  {
    ANIMATION_DATA *a;
    for (int animationStep = animTail; animationStep != animHead; ) 
    {
      a = &anim[animationStep];
      if (a->len)
      {
        int px;

        //Draw the Comet
        for (int p = a->len - 1; p >= 0; p--)
        {
          px = constrain(a->pos - p, 0, NUMPIXELS + cometLen);

          if (p < 1) {
            setAPA102Color(px, green_for_pixel(px, 255), red_for_pixel(px, 255), blue_for_pixel(px, 255), brightAnim[p]*bright_percent);
          } else if (p < 3) {
            setAPA102Color(px, green_for_pixel(px, a->g) + ((green_for_pixel(px, 255)-green_for_pixel(px, a->g))*.5), red_for_pixel(px, a->r) + ((red_for_pixel(px, 255)-red_for_pixel(px, a->r))*.5), blue_for_pixel(px, a->b) + ((blue_for_pixel(px, 255)-blue_for_pixel(px, a->b))*.5), brightAnim[p]*bright_percent);
          } else if (p < 5) {
            setAPA102Color(px, green_for_pixel(px, a->g) + ((green_for_pixel(px, 255)-green_for_pixel(px, a->g))*.1), red_for_pixel(px, a->r) + ((red_for_pixel(px, 255)-red_for_pixel(px, a->r))*.1), blue_for_pixel(px, a->b) + ((blue_for_pixel(px, 255)-blue_for_pixel(px, a->b))*.1), brightAnim[p]*bright_percent);
          } else {
            setAPA102Color(px, green_for_pixel(px, a->g), red_for_pixel(px, a->r), blue_for_pixel(px, a->b), brightAnim[p]*bright_percent);
          }
          
        }

        //Erase the pixels behind comet as it moves forward  
        if (a->pos - a->len >= 0)
          for (int k = 0; k <= stepSpeed; k++)
            setAPA102Color(a->pos - k - a->len, 0, 0, 0, 0);

        //Make comet jump forward stepSpeed pixels at a time to make comet run seemingly faster
        if (a->pos < NUMPIXELS + cometLen)
          a->pos += stepSpeed;
        else
          a->len -= stepSpeed;

        if (a->len <= 0)
        {
          *a = { 0, 0, 0, 0, 0 };
          animTail++;
          animTail %= maxAnim;
        }
      }

      animationStep++;
      animationStep %= maxAnim;
    }
    needRefresh = true;
  }

  sparkleState = !sparkleState;  // flip state
  if (sparkleState)
  {
    sparklePixel = random(NUMPIXELS);
    setAPA102Color(sparklePixel, random(255), random(255), random(255), 50);
    needRefresh = true;
  }
  else
  {
    setAPA102Color(sparklePixel, 0, 0, 0, 0);
    needRefresh = true;
  }
    
  
  if (needRefresh && canRefresh) {
      canRefresh =
      needRefresh = false;
      SPI.transfer(pxBuffer, NULL, sizeof(pxBuffer), refreshDone);
  }

}

struct topic {
  char    title[16];
  uint8_t rgb[3];
};

const topic topicList[] = 
{ { "login"  , { 255, 255, 255 } }  // white
, { "idea"   , { 255,   0, 255 } }  // yellow
, { "comment", {   0, 255,   0 } }  // blue
, { "outcome", { 255,   0,   0 } }  // green
, { "project", { 255,   0,   0 } }  // green
, { "status" , { 100,   0, 255 } }  // orange
, { "step"   , {   0, 255,  75 } }  // purple
, { "vote"   , {   0,   0, 255 } }  // red
, { "view"   , { 105, 200, 255 } }  // pink
};

const int   topics = sizeof(topicList)/sizeof(topicList[0]);


//Add a comet to the strip whenever initated by cloud event
int addComet(String command)
{
  int retVal = -1;

  for (int i = 0; i < topics; i++)
  {
    if (strcmp((const char*)command, topicList[i].title) == 0)
    {
      anim[animHead] = { topicList[i].rgb[0], topicList[i].rgb[1], topicList[i].rgb[2], 0, cometLen };
      Particle.publish(command);
      animHead++;
      animHead %= maxAnim;
      retVal = i;
      break;
    }
  }
  return retVal;
}

This is my breadboard setup. Right now, it’s being powered by 5v 15A power supply.

I need to power 4,320 LEDs with this setup. I was thinking of just supplying power every few meters. I haven’t done this yet but the ground wire has started to melt and smoke when I attached one of the long LED strips to it. I thought the lights would dim out but didn’t know wires would overheat. Wires were fine when I powered 10 LED strips (1,440 LEDs) with it.

What is the issue here? Are the wires too thin? Do I need to attach power to the LEDs farther down the LED strip, input power at the 0th position?

You need to understand Ohm's Law and do the maths.

2 Likes

Furthermore, a single 15A supply, running over 4000 neopixels? ā€œYou’re gonna have a bad timeā€.
A single LED can consume up to 60mA, so the whole lot can consume a fair bit more than your power supply is capable of delivering.

1 Like

Okay, I’m learning this…

Ohm’s Law:
Resistance = Voltage / Current

Load: 4,320 LEDs at 60mA each: 259.2A
LED Strip: 5V
Power Supply: 5V 10A

There’s too much current being drawn. Resistor is required because it will limit the current?

For Ohm’s Law…
In this case…
Is Voltage = 5V
and Current is 259.2A?

Yeah, I was thinking I could solder on additional power supplies every few meters, and it would be okay…

Added resistors will also impact the brighness of the LEDs and even with a current limited to 15A you'll disipate 75W which will be a nice little heater :wink:

Also copper wires are no superconductors. They have a resistance ( R = ρ * l / A - for copper ρ is 0.0171 Ohm*mm²/m) and you need to power at multiple places with Vcc and GND with cables thick enough to withstand the current draw.
The thinner the wire the higher the resistance the higher the dissipation energy (aka heat) P = I² * R.

Okay, so if I added power every few strips, would that work? That would allow power at multiple places.

And I should use a thicker wire–like 14AWG wire? It’s much thicker…how does one solder that to a perma proto board, though (the holes in the board are tiny)?