Neopixel strip flicker/glitch issue

New to working with arduino and neopixel leds so I apologize for my inexperience. Looking for some assistance with a flicker and glitch issue I'm having with several 90 led strips I've soldered together totaling to 344 neopixels. The chasing animation I've used has worked on previous soldered together strips but after repairing a small issue I'm having a difficult time replicating what I was able to successfully accomplish in previous projects. I can't figure out what I'm doing wrong. When I turn on the power, leds light up and chase animation starts, but after about 30 seconds the last 2/3rds of the strip flickers and stops animating then begins to glitch.

I have programmed a chasing animation (written by another person) to other strips of around 300 to 250 neo pixels and they have run just fine. So I don't think the problem is in the sketch. This is how I have my neopixels set up:

I thought maybe they were drawing too many amps, but I'm using a 5v 10A power supply and that many lights should only be drawing a little over 2 amps.

I thought perhaps that they were using too much RAM but when I compile the sketch it says that I'm barely making a dent in the total bytes; "4034 bytes (1%) Max is 253952. Global variables use 245 bytes 2% of dynamic memory, leaving 7947 bytes for local variables, max 8192." I'm using an Arduino Mega 2560

I thought maybe the strip was bad so I used an all-new strip and still had the same issue. I thought maybe my solder joints were bad but I had more experienced people solder the joints and still the same issue.

I can only make it work consistently with 90 neopixels. It's just odd because even with the same sketch and the same method of powering and joining the strips together, other projects I've completed have worked just fine. It's suddenly not working for me. I'm at the last bit of patience I have for this, but the project is important and I need to fix it. Any help or direction would be appreciated.

Here is the sketch:

#include <Adafruit_NeoPixel.h>

#define STRIP_PIN 7  // All

#define STREAM_LENGTH 344  //Hydro

#define NUM_CHASES 34      //Hydro

#define CHASE_LENGTH 7     //All

#define CHASE_GAP (STREAM_LENGTH - (CHASE_LENGTH * NUM_CHASES)) / NUM_CHASES
#define ANIMATION_SPEED 20  

Adafruit_NeoPixel strip(STREAM_LENGTH, STRIP_PIN, NEO_GRB + NEO_KHZ800);

uint32_t chaseColor[NUM_CHASES];
uint16_t chaseHeads[NUM_CHASES];
uint16_t chaseStates[NUM_CHASES][STREAM_LENGTH];

void setupChases() {
  for (int i = 0; i < NUM_CHASES; i++) {
    chaseColor[i] = strip.Color(0, 0, 255);
    chaseHeads[i] = i * (CHASE_LENGTH + CHASE_GAP);
    for (int j = 0; j < STREAM_LENGTH; j++) {
      chaseStates[i][j] = 0;
    }
  }
}

void setup() {
  strip.begin();
  strip.clear();
  strip.show();
  setupChases();
  delay(2000);
}

void animateStrip() {
  // Create a buffer for updated LED colors
  uint32_t ledColors[STREAM_LENGTH] = { 0 };

  for (int i = 0; i < NUM_CHASES; i++) {
    chaseHeads[i] = (chaseHeads[i] + 1) % STREAM_LENGTH;  // Update chase heads
    ledColors[chaseHeads[i]] = chaseColor[i];
    chaseStates[i][chaseHeads[i]] = 1;

    int fadePos = (chaseHeads[i] - 1 + STREAM_LENGTH) % STREAM_LENGTH;
    uint8_t fadeStep = 255 / (CHASE_LENGTH + 1);
    uint8_t fadeLevel = 255 - fadeStep;

    for (int j = 0; j < CHASE_LENGTH && fadeLevel > 0; j++) {
      ledColors[fadePos] = strip.gamma32(strip.Color(fadeLevel, fadeLevel, fadeLevel));
      chaseStates[i][fadePos] = 2;
      fadeLevel -= fadeStep;
      fadePos = (fadePos - 1 + STREAM_LENGTH) % STREAM_LENGTH;
    }
  }

  for (int i = 0; i < STREAM_LENGTH; i++) {  // Apply computed colors to the strip
    strip.setPixelColor(i, ledColors[i]);
  }
  strip.show();
}

void loop() {
  animateStrip();
  delay(ANIMATION_SPEED);

}

You likely need to inject 5 volt at several locations along the strip.
Measure the 5 volt along the strip! Surely it is dropping during the strip.

You might need to slow your code or lessen the animation.

Two things cause this. (1) insufficient power (2) writing outside the neopixel buffer boundary (the array of LEDs, not memory size).

Added. The compiler would know about that array, so I do not understand why it would not have counted it and given you a report as to why the code would not run. At all.

a7

Read for fun. My bad:

You wrote

uint16_t chaseStates[NUM_CHASES][STREAM_LENGTH];

That's 34 * 344 * 2 bytes. 23392 bytes.

The compiler doesn't know about that, so you get a report that does nowhere near reflect the total memory required.

The begin() method allocates memory for the strip, does not report failure or you fail to check if it does.

Antics ensue.

The library does bounds checking.

a7

@alto777, I do not quite understand your post; it sounds like your contradicting yourself.

vs


And indeed the Adafruit_NeoPixel library uses dynamic memory allocation as you pointed out.

I was cheerfully admitting making a nearly totally erroneous post. It happens; I've lost count.

I did think for some reason that it was the fact that memory for the strip is not known to be needed at compile time that was causing the issue.

But something made me look again, and the large array is known at compile time... so I don't see why that is not reflected in the compiler output...

#define STREAM_LENGTH 344
#define NUM_CHASES 34

//...

uint16_t chaseStates[NUM_CHASES][STREAM_LENGTH];

Where are those 23392 bytes? I'm unable to see where I am going wrong on this. It's a global array in dynamic memory.

a7

> arduino-cli compile -b arduino:avr:mega --warnings all --clean
Sketch uses 4034 bytes (1%) of program storage space. Maximum is 253952 bytes.
Global variables use 245 bytes (2%) of dynamic memory, leaving 7947 bytes for local variables. Maximum is 8192 bytes.

> arduino-cli compile -b MegaCore:avr:2560 --warnings all --clean
Sketch uses 3998 bytes (1%) of program storage space. Maximum is 261632 bytes.
Global variables use 245 bytes (2%) of dynamic memory, leaving 7947 bytes for local variables. Maximum is 8192 bytes.
> nm -SCn build/arduino.avr.mega/forum_1342731.ino.elf | grep chase
00800206 00000044 b chaseHeads
0080024a 00000088 b chaseColor

> nm -SCn build/MegaCore.avr.2560/forum_1342731.ino.elf | grep chase
00800206 00000044 b chaseHeads
0080024a 00000088 b chaseColor

No sign of changeStates.
Both have LTO enabled by default. Let's try without:

> arduino-cli compile -b MegaCore:avr:2560:LTO=Os --warnings all --clean
Sketch uses 4512 bytes (1%) of program storage space. Maximum is 261632 bytes.
Global variables use 23637 bytes (288%) of dynamic memory, leaving -15445 bytes for local variables. Maximum is 8192 bytes.
Not enough memory; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing your footprint.

Something really weird is going on with LTO. :face_with_raised_eyebrow:

For comparison a couple of boards with enough memory:

build/arduino.samd.mkr1000/forum_1342731.ino.elf
200000ac 00000088 B chaseColor
20000134 00000044 B chaseHeads
20000178 00005b60 B chaseStates

build/esp32.esp32.featheresp32/forum_1342731.ino.elf
3ffc1a38 00005b60 B chaseStates
3ffc7598 00000044 B chaseHeads
3ffc75dc 00000088 B chaseColor

Well at least

0x5B60 = 23392.

OK, if I add

      chaseStates[i][j] = i * j;

to setupChases() and call a function I wrote called printChases() which does what it says, compiling for the Mega fails, viz:

Global variables use 21800 bytes (266%) of dynamic memory, leaving -13608 bytes for local variables. Maximum is 8192 bytes.
Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint.
Error compiling for board Arduino Mega or Mega 2560.

I did not think the optimizer, which I assume is the problem here, could optimize its way out of a ridiculous use of memory.

And besides the fact that there seems to be plenty of use of that array that I don't see being optimized away.

I surrender and await the heavies who will 'splain this. Going horizontal now...

a7

So at 60mA per neopixel you need a power supply capable of supplying at least 20.6 Amps. So your power supply is too small. You could reduce this power requirement by limiting the brightness in the setup function.

You need to also to have a 1000uF capacitor between power and ground at the beginning and end of each strip, and maybe in the middle of a strip as well. Also as mentioned extra power and ground at each end and middle of strips.

Please show how these 90 pixel strips are aggregated.

So:-
344 * 34 = 11696 points in the array. But as each point is a uint16_t , each point takes 2 bytes
giving
11696 * 2 = 23392 bytes

Why do you have to use a two dimensional array at all?
The Arduino Mega has 8K of dynamic memory

In fact for 334 Leds, each LED requires three bytes of dynamic memory, gives :-

334 * 3 = 1002 bytes of memory, which is only about one eighth of the total memory available on that processor.

True it can't.
So the optimizer is not your problem. It doesn't kick in at all and has no role in your code.

What do you think the optimizer does? It's job is to replace or remove redundant code, that is code that exists but is never used. Like a line of code that does nothing, or a line that can never be reached.

Your problem is requiring such a massive array in the first place.

I do not disagree, but I find my sloppy coding doing similar gymnastics when I do not keep the math inside [zero..NUMPIX-1] for placement and [zero..255] for color and brightness. I add this to my sketches to keep me honest.

void debugValues(int i, int r, int g, int b) {
  // Call this function to:
  // verify index matches starting color values
  // verify no values < 0 or > 255
  // verify index matches ending color values
  Serial.print(i); // index
  Serial.print(" ");
  Serial.print(r); // red
  Serial.print(" ");
  Serial.print(g); // green
  Serial.print(" ");
  Serial.print(b); // blue
  Serial.println();
}

I approve!

I like to write code that wouldn't need to know it's being checked in some library function.

I will cop, however, to being lazy. When running a train of LEDs off the end of the track, for example, it's just easier to let it and rely on something else to keep the damages to a minimum. Either end of the track.

FastLED is different, in that case you are the owner of the array and no one but you will keep trouble at bay.

On the same hand, or it's it the other, if you are using those indices in other code then you are back to wanting to keep everything on bounds.

My own honesty-enforcer is, um, somewhat primitive. This function can be called from anywhere, and I call it when something that "can't happen" has, in fact, occurred.

void fork(char *message)
{
  Serial.println(message);
  Serial.flush();

  for (; ; );
}

and usually like

  fork("Rotten Denmark!");

I have another version that just blinks an LED when the fork is stuck into the machine.

a7

Agreed, it is a problem.

But you don't seem to be reading this thread. The code compiles even though it has a massive array that is clearly being used in some algorithm @dlvarner wrote or found…

And only when I wrote an explicit initialisation meant to provoke an error by frustrating any optimisation, and had to also add printing out the array, did the compiler finally notice that the code was trying to use more memory than available.

So something besides knowing everything about everything is going on here. I can't say what it is. I hope someone who actually knows more about this than, it seems, either of us can add something to the discussion.

a7

1 Like

Clearly this function does not work.

Why on earth should it not compile? The compiler can know nothing about any arrays that are defined inside the code.

It gives an error when it finds out there is not enough memory for it to run?

I think you are missing the point.

What on Earth are you talking about? Please try to make that make any sense.

If anyone is missing any point it would be you. A program with a too-large array to compile does, until you start actually using the array in a certain way it was not previously.

Where are arrays ever defined except "inside the code"?

This is a global array of the simplest kind; the code should not compile but rather give an error, the same kind of error it is possible to get it to eventually issue.

int largeTwoDimensionalArray[TOO][BIG];

Where the product of TOO and BIG times two is very much larger than the available RAM. Would you not expect help from the compiler to show you the folly of trying to do that?

This is not normal. I want to know what is happening, nothing about it seems right to me.

Have you actually read the thread?

a7

1 Like

Did you have to ask?

Whatever else is going on, the 23392 bytes for the chaseStates array is a red herring. It was totally optimised out of being any problem, here were the four references to it in the code, which in my haste I read as making it safe from being simply disregarded.

uint16_t chaseStates[NUM_CHASES][STREAM_LENGTH];
      chaseStates[i][j] = 0;
     chaseStates[i][chaseHeads[i]] = 1;
           chaseStates[i][fadePos] = 2;

Defined, assigned but never used otherwise.

So it was not a factor. As soon as I made it important, it caused a compiler error.

I could have just added the volatile qualifier.

All the behaviour around this part of the sketch is completely plausible.

It does make me wonder about who wrote it and what they may have been thinking they were accomplishing.

Or what kind of surprise would pop up the minute any attempt to benefit from all the work that went into its pointless use was made.

a7

1 Like

So having indulged in your effort to solve your problems maybe you could remember that the whole point of this thread was to solve @dlvarner 's problem not yours. You are better than this.

1 Like

The OP has indicated he/ she no longer requires help so I have closed the topic. If you really want to add something feel free to request it be opened.