Controlling more then 100 LEDs is causing flickering

Hey,
I’ve started working on a LED project, basically, i need to control 500 LEDs over serial communication. I’m working with only 30LED strip (so i don’t have to move around my desk 500LEDs (I tried all 500 LEDs and the problem is still there)), but i’m simulating it by code by just setting the length of the strip to 500 instead of 30.

I’ve found out that the limit is around 100 with the flickering.
If i call the .show function less (10x times a second instead of every serial input), it extends it to around 150LEDs and then it starts flickering again.

Anybody knows what could i be doing wrong ?
Thanks in advence!

My code:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h>
#endif
Adafruit_NeoPixel pixels0(150, 7, NEO_GRB + NEO_KHZ800);
int RedGlobal = 0;
int GreenGlobal = 0;
int BlueGlobal = 0; 
int BrightnessGlobal = 10;
 
 
void setup() {
  Serial.begin(9600);
  delay(10);
  pixels0.begin();
  setcolor(255,255,255,1);
}
 
 
 
void setcolor(int red, int green, int blue, int brightness) {
  pixels0.setBrightness(brightness);
  pixels0.fill(pixels0.Color(red,green,blue));
  pixels0.show();
}
 
 
void loop() {
  if (Serial.available()){
    char led_specifier = Serial.read();
    int led_brightness = Serial.parseInt();
    write_leds(led_specifier, led_brightness);
  }
}
 
 
 
void write_leds(char led, int value){
if (led == 'r'){
      RedGlobal = value;
      setcolor(RedGlobal, GreenGlobal,BlueGlobal,BrightnessGlobal);        
    return;
  }
  if (led == 'g'){
    GreenGlobal = value;
    setcolor(RedGlobal, GreenGlobal,BlueGlobal,BrightnessGlobal);
    return;
  }
  if (led == 'b'){
    BlueGlobal = value;   
    setcolor(RedGlobal, GreenGlobal,BlueGlobal,BrightnessGlobal);     
    return;
  }
  if (led == 'j'){
    BrightnessGlobal = value;   
    setcolor(RedGlobal, GreenGlobal,BlueGlobal,BrightnessGlobal);
    return;
  }
  return;
 }

(This is just a demonstration code for the problem, my real code is much more complex,but the problem is same)

How it works - How it works with 500 LEDs set in the code
How it should work - How it works with 30 LEDs set in the code (the right way)

Ok a few questions what kind of board are you using ? 500 leds is a lot for that you need 1500 bytes of buffer, but if you say that it happens with 150 leds defined it shouldn’t be the issue.
What type of leds are you using ?
Oh yeah and how are you powering the leds (since you can get it to work when you define 30 in the code it is not relevant at the moment but i still want to know)
I suspect your issue is here :

  if (Serial.available()){
    char led_specifier = Serial.read();
    int led_brightness = Serial.parseInt();
    write_leds(led_specifier, led_brightness);
  }

You do no error checking at all, not only that, when you read ‘int led_brightness = Serial.parseInt();’ you have not even checked to see if those 2 bytes are there.
because ‘pixels0.show();’ turns off interrupts for the time that it takes to send the signal, the more leds, the longer the time it is turned off, which may (and probably does at 500 leds) cause the Serial input register not to be read and transferred to the Serial buffer in time before the next byte comes in.
If you want your program to respond correctly to received data, you need to verify that the data isn’t somehow corrupted.

Hello
How do you feed your array of LED´s?
Does the powersupply is able to provide the needed current without to drip the supply voltage?

Or let’s be more specific.

Do you actually have a power supply capable of powering your LEDs with regulated 5 V? :roll_eyes:

You don’t say how fast you are sending the data but I completely agree with the below

The update of one led takes 24x1.25 microseconds = 30 microseconds; updating 150 leds will take 4.5 milliseconds.
As explained, interrupts are disabled while the update of the strip happens (pixels0.show()). So during those 4.5 milliseconds, you can loose data (probably 2 bytes as there is a 2-byte fifo in the serial hardware of the microcontroller).

My solution is to use a protocol with a handshake between Arduino and sender; the basics are

  1. Sender sends one byte / character to Arduino
  2. Arduino echoes (sends) it back to sender when it reads the character.
  3. Only when sender receives the echo, it will send the next byte / character.
  4. Back to (2).

Once the full message is received, you can process the received data and update the strip.

Some of the Adafruit boards can update the strip without disabling interrupts. They use hardware SPI and DMA channels to update the strip, leaving the processor free to process serial or other inputs. Some even have a special pin for driving strips, which often require a 5V signal, and these boards run at 3.3V.

There may not be enough time to create a fade effect. If you consider 30uS then you have 33,333 updates per second. However with 4.5mS you only have 222.

If you update 3 times for each color group and do a total of 256 colors, then you will need to update 768 times. You can fix this with a update command. Accumulate on ‘r’, ‘b’ and ‘g’ commands. Only call setcolor on ‘j’ command.

This will create overhead by forcing extra command which is not currently needed. However it could prove if the problem is in serial protocol or if there is a time problem.

It would be nice to know what pattern is being sent per second. It is possible for there to be an attempt at 16777216 colors. That is not going to work. However I doubt this is what is being attempted.

Edit:
This is a very simple protocol which can have data corruption and/or lose state. The posted protocol revision would likely throttle/serialize enough to prevent this. Many 8-bit controllers simply do not support more advanced things.

This is why you never bit bang! This is why I have never really cared for the NeoPixels. They create blocking logic, which is hell to work through. The issue here is the NeoPixels work off very specific timing. Which cripples your software model. All kinds of portability losses, despite the portability gains.

Edit 2:
Can these be used as shift register? If these work like shift registers, you can update in sections. Then use a state machine in the super loop. This may allow enough time to get serial data.

Overall this will waste a lot of cycles. Honestly I do not recommend this. Super loops have their appeals this is probably not the correct case for it. This will likely create data overflow condition.

Only 30 LEDs are actually connected. He has not got to that yet.

The peak current requirement of 30 “NeoPixels” is of the order of 1.7 Amps. The concern is that someone with no engineering expertise may fantasise that you can somehow connect these to obtain power from the Arduino board. :roll_eyes:

Why do you use addressable diodes instead of ordinary 12V RGB strip? The program only changes the color and brightness of the entire strip and no addressable diodes are needed. With RGB strip and 3 FET transistors is even cheaper.

Now… yes, but do you know what the future plans of the OP are ? Not to mention the extra work of ordering new / different parts.