5

I'm new to these addressable LED things – I just received a 149-LED WS2812B strip today, and I'm experimenting with various approaches. Adafruit's own tutorial says the FastLED library is faster than their Adafruit_NeoPixel library, so I wanted to test their performance.

I'm running this code on a Nano clone:

// Adafruit
#include <Adafruit_NeoPixel.h>
// FastLED
#include <FastLED.h>
// Common
#define NUM_LEDS 149
#define DATA_PIN 6

// Adafruit initialization
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800);
const uint32_t adaBlack = strip.Color(0, 0, 0);
const uint32_t adaWhite = strip.Color(255, 255, 255);

// FastLED initialization
CRGB leds[NUM_LEDS];

void setup() {
  // Common
  delay(2000);

  // Adafruit setup
  strip.begin();

  // FastLED setup
  FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);

  // Common
  Serial.begin(57600);
}

void loop() {
  unsigned int adafruitMillis = adafruitLoop();
  unsigned int fastLedMillis = fastLedLoop();
  // Yes, this is ugly -- but it works every time
  Serial.print(adafruitMillis);
  Serial.print(",");
  Serial.println(fastLedMillis);
}

unsigned int adafruitLoop()
{
  long unsigned startMillis = millis();
  for (int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed++) {
    strip.setPixelColor(whiteLed, adaWhite);
    strip.show();
    strip.setPixelColor(whiteLed, adaBlack);
  }
  return (unsigned int) millis() - startMillis;
}

unsigned int fastLedLoop()
{
  long unsigned startMillis = millis();
  for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed++) {
    leds[whiteLed] = CRGB::White;
    FastLED.show();
    leds[whiteLed] = CRGB::Black;
  }
  return (unsigned int) millis() - startMillis;
}

The results are totally disastrous for FastLED (shown in red): FastLED is red, Adafruit's library in blue

Am I doing something wrong, or is FastLED winning on features, rather than on speed?

For the record, I did check whether the performance hit comes from setting the pixel values or from sending the data – FastLED is faster at setting the pixel values than Adafruit's library, but that doesn't matter because setting two pixel values takes 3 ms or less for the entire strip, regardless of the library. Sending the data to the strip takes most of the time, and that's where FastLED lags behind big time (900 ms compared to Adafruit's 200 ms).

Bogdan Stăncescu
  • 155
  • 1
  • 1
  • 5

2 Answers2

13

You can't rely on the timing reported by millis when comparing FastLED and Adafruit's neopixel library. Writing out Neopixel data involves disabling interrupts, which is what the clock uses to advance. FastLED accounts for this and attempts to update the system clock time after writing out led data to account for the amount of time that interrupts were disabled, but the adafruit NeoPixel library doesn't. You need to use something else to compare timing.

(WS2812 data has a pretty strict data rate - 800khz, or about 30µs per rgb led)

(I should know, I wrote FastLED :)

rDg
  • 166
  • 2
1

As I understand it, the Fast in FastLED isn't for sending the data, but for manipulating the array/data that holds the colors. The FastLED library contains many functions optimized for dealing with 8-bit unsigned integers for holding color values, including color addition, 8-bit scaling, partially-defined color palettes (for example, you define 8 waypoints in the palette, but can grab a color from the full 8-bit range and it interpolates on the fly using the fast 8-bit math.

Not just math, but also conversion to/from RGB and HSV realms, etc.

It supports pushing multiple strips at the same time (parallel) by writing to the whole PORT instead of just one pin of the 8-pin port, so if you split your strip into multiples, you can really make speed gains in writing to the LEDs.

jose can u c
  • 6,974
  • 2
  • 16
  • 27