How to make colorWipe move faster

Hello there. I am using the NeoPixel library for my little project with WS2812 led strip. I'm trying to make colorWipe function run faster with large amount of leds in the strip. For example, if I run my code with numLeds = 300, it takes 3sec to completely fill all leds with colorWipe, but with 600 leds (2*5m strip) it takes 10sec to do so. My main target is to completely cover 800 leds in 3sec, is this really possible and how to achieve it if it is. Thanks in advance.

#include <Adafruit_NeoPixel.h>

const int ledPin = 12;
const int numLeds = 300;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numLeds, ledPin, NEO_GRB + NEO_KHZ800);
bool on;
bool off;


void setup() {
  strip.begin();
//  strip.show();
  strip.setBrightness(2);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  }

void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}

void colorWipe2(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i--) { // infinite loop
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}

void reverseColorWipe(uint32_t c, uint8_t wait) {
  for(int16_t i=(strip.numPixels()-1); i>=0; i--) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } 
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } 
  else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*4; j++) { // +-256 for longer/shorter period
    
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i*1+j) & 255));
    }
    
    strip.show();
    delay(wait);
  }
}

void loop() {
  on = digitalRead(2);
  off = digitalRead(3);
  
  if (on == 1) {
    colorWipe(strip.Color(102, 0, 102), 0); // purple
    rainbow(5);
    delay(10);
    colorWipe(strip.Color(0, 0, 0), 0);
    on = 0;
}

  if (off == 1) {
    reverseColorWipe(strip.Color(102, 0, 102), 0); // purple
    rainbow(5);
    delay(10);
    reverseColorWipe(strip.Color(0, 0, 0), 0);
    off = 0;
  }
}

I'm trying to make colorWipe function run faster

    delay(wait);

Change or remove the delay period

UKHeliBob:

    delay(wait);

Change or remove the delay period

Thanks! I already tried that (delete) and it didn't help. Like it's already = 0. I can slow down colorWipe by editing wait > 0 but idk how to make it run faster. Like it's already on its max speed.

I don't think you can.

Your wipe routine looks like:

void colorWipe(uint32_t c, uint8_t wait) 
{
    
    for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
        strip.setPixelColor(i, c);
        //each show is 300 pixels x 1.2uS/bit x 24 bits == 9mS
        //repeated 300 times == 2.7-seconds
        //
        //each show is 600 pixels x 1.2uS/bit x 24 bits == 18mS
        //repeated 600 times == 10.8-seconds
        strip.show();
        delay(wait);
    }
}

You update a single pixel, then show all of them. You update the next pixel, then update all of them and so on.

See the comments inline: approached on a pixel-by-pixel basis there's no way around the math: Each pixel needs 24 bits and each bit takes ~1.25uS. Multiplied by the iterations you simply get ~3 and ~10-seconds.

You need to reduce your iteration count. Can you update 2 pixels per pass instead of 1? Or 3 instead of 2 and then run .show()/2 or .show()/3 times? How badly does that affect your visuals?

You are limited by the bit rate of the data going to the LEDs. There are addressable LEDs that use SPI for data and are therefore faster.

Alternately, split the strip into shorter segments driven from different data lines.

“ Alternately, split the strip into shorter segments driven from different data lines.”

I’ll look again after coffee but how does this help? There are still N pixels and only one processor…

Unless the effect is only happening in subsequences? Which I am again not ready to contemplate.

TIA

a7

Neopixles can only go at one rate. They have really tight timing requirements. Previous post before (Blackfin) said to update groups at a time. I’m betting that’s the hot ticket for this.

-jim lee

Blackfin:
I don't think you can.

Your wipe routine looks like:

void colorWipe(uint32_t c, uint8_t wait) 

{
   
    for(uint16_t i=0; i<strip.numPixels(); i++)
    {
        strip.setPixelColor(i, c);
        //each show is 300 pixels x 1.2uS/bit x 24 bits == 9mS
        //repeated 300 times == 2.7-seconds
        //
        //each show is 600 pixels x 1.2uS/bit x 24 bits == 18mS
        //repeated 600 times == 10.8-seconds
        strip.show();
        delay(wait);
    }
}




You update a single pixel, then show all of them. You update the next pixel, then update all of them and so on.

See the comments inline: approached on a pixel-by-pixel basis there's no way around the math: Each pixel needs 24 bits and each bit takes ~1.25uS. Multiplied by the iterations you simply get ~3 and ~10-seconds.

You need to reduce your iteration count. Can you update 2 pixels per pass instead of 1? Or 3 instead of 2 and then run .show()/2 or .show()/3 times? How badly does that affect your visuals?

Thanks!! This is exactly what's happening here. In my case, when the colour of colorWipe(strip.Color(102, 0, 102), 0) is smoothly turns from pink to red, I believe it won't affect visuals at all, even with /3 or /4 of reducing iteration count. How to do that in code?

int group =0;
for (int i=0;i<... {
group++;
if (group==3) {
show();
group=0;
}
set pixel..
}
show(); // just in case.

Sorry hard to write code on phone.

-jim lee

critical7:
Thanks!! This is exactly what's happening here. In my case, when the colour of colorWipe(strip.Color(102, 0, 102), 0) is smoothly turns from pink to red, I believe it won't affect visuals at all, even with /3 or /4 of reducing iteration count. How to do that in code?

Something like this does 3-pixels at a time:

void colorWipe(uint32_t c, uint8_t wait) 
{
    for(uint16_t i=0; i<strip.numPixels(); i+=3) 
    {
        strip.setPixelColor(i, c);
        strip.setPixelColor(i+1, c);
        strip.setPixelColor(i+2, c);
        strip.show();
        //delay(wait);
    }
}

In theory that would reduce your 300-pix time to (300 x 1.25uS x 24) x 200 == 1.8-sec and your 600pix time to 5.4-sec.

If you did:

void colorWipe(uint32_t c, uint8_t wait) 
{
    for(uint16_t i=0; i<strip.numPixels(); i+=4) 
    {
        strip.setPixelColor(i, c);
        strip.setPixelColor(i+1, c);
        strip.setPixelColor(i+2, c);
        strip.setPixelColor(i+3, c);
        strip.show();
        //delay(wait);
    }
}

(so 4 pix at a time) you should see 675mS and 2.7-sec.

Of course the "cost" to this speed up is less smoothness.

Blackfin:
Something like this does 3-pixels at a time:

void colorWipe(uint32_t c, uint8_t wait) 

{
   for(uint16_t i=0; i<strip.numPixels(); i+=3)
   {
       strip.setPixelColor(i, c);
       strip.setPixelColor(i+1, c);
       strip.setPixelColor(i+2, c);
       strip.show();
       //delay(wait);
   }
}




In theory that would reduce your 300-pix time to (300 x 1.25uS x 24) x 200 == 1.8-sec and your 600pix time to 5.4-sec.

If you did:



void colorWipe(uint32_t c, uint8_t wait)
{
   for(uint16_t i=0; i<strip.numPixels(); i+=4)
   {
       strip.setPixelColor(i, c);
       strip.setPixelColor(i+1, c);
       strip.setPixelColor(i+2, c);
       strip.setPixelColor(i+3, c);
       strip.show();
       //delay(wait);
   }
}




(so 4 pix at a time) you should see 675mS and 2.7-sec.

Of course the "cost" to this speed up is less smoothness.

Thanks again, it works perfect, but now with this "speedy" version I found out another problem. If numLeds >= 622, code doesn't work, no reaction from triggering inputs. It doesn't work on both versions, with and without reducing iteration count, I just didn't check it with more then 600 leds. How to trick it for 800 leds?

critical7:
Thanks again, it works perfect, but now with this "speedy" version I found out another problem. If numLeds >= 622, code doesn't work, no reaction from triggering inputs. It doesn't work on both versions, with and without reducing iteration count, I just didn't check it with more then 600 leds. How to trick it for 800 leds?

Which Arduino are you using?

If each pixel requires 3 bytes (24 bits) then 800 would be 2400 bytes. 622 pixels is 1866 bytes. You may be running into a RAM problem if you only have, say, 2K available.

Neopixles can only go at one rate. They have really tight timing requirements. Previous post before (Blackfin) said to update groups at a time. I'm betting that's the hot ticket for this

Sounds like a good weekend project

Blackfin:
Which Arduino are you using?

If each pixel requires 3 bytes (24 bits) then 800 would be 2400 bytes. 622 pixels is 1866 bytes. You may be running into a RAM problem if you only have, say, 2K available.

I'm using Arduino Nano with 2k SRAM. Sounds like I need to switch into Mega or something like that. Thanks again, you saved me a ton of time! A lot of love and luck to you sir :wink:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.