Last fall when I was working on the now-defunct ‘Footwell NeoPixels’ project I wrote a short post talking the fact that you cannot use the FastLED library with RGBW leds, and have to deal with the clunkier Adafruit NeoPixels library.

Well last week, a man named Jim Bumgardner commented on that post and shared his method for doing just that: using the FastLED library with RGBW leds.


Before we get started, you should know one thing: this is a hackIt is not a supported part of the library, it only works with SK6812 leds (that I’m aware of), and it does not work perfectly. But, it does work!

Daniel Garcia and the rest of the FastLED team have said that they are working on an RGBW upgrade behind the scenes, but they have no time table for when it will be completed. In the meantime, this is a quick and dirty fix.

The Hack

This hack works by exploiting the fact that WS2812B LEDs and SK6812 LEDs have similar data timing. It’s not identical, but it’s close enough to make this work. The trick is to tell FastLED that we’re writing to a WS2812B strip, but insert an extra ‘white’ byte between each RGB group.

To do this, we create a special ‘CRGBW’ struct that adds the extra byte, and a few helper functions to integrate with FastLED. I rewrote Jim’s code a bit so the assignment methods more closely match their FastLED counterparts, and I also added an operator overwrite so you can assign CRGB colors directly. Here’s the code, in full:

Download and save this file as “FastLED_RGBW.h”, and place it the same folder as your sketch. Then include it in your sketch by typing:

When defining the LED array, we also need a CRGB pointer to send to the addLEDs function. We do this like so:

Lastly, when we create the FastLED controller we need to inflate the number of LEDs to account for the extra bytes. The header file has a helper function for this, named getRGBWsize . The function takes the number of RGBW LEDs as an argument and returns the number of CRGB elements that cover that many bytes.

Now when we create the FastLED controller in the setup  function, we use both the CRGB pointer and the size function:

Once the strip is set up, you can set LED colors just like you would normally:

Example Sketch

Here is a basic example sketch that works with SK6812 strips. It does a color wipe for each channel (red, green, blue, and white), then does a rainbow pattern for a 5 seconds and repeats.


FastLED is a huge library, and unfortunately not all of its helper functions work with this hack. From my testing, while the basic features of the library work the more advanced ones do not. For instance – while non-desctructive brightness works perfectly, the color temperature functions do not work at all.

These problems come down to the additional bytes added by the CRGBW struct, in combination with the hard-coded color order. Any function that references the raw array members will be cyclically referencing the wrong color channels.

The other obvious limitation is that this only works with RGBW strips that share protocols already in the FastLED library. SK6812 strips (RGBW NeoPixels) work fine using the WS2812B protocol, but you may need to write your own protocol class if you cannot find one already supported.

Lastly, a not-so-obvious limitation is that for LED byte counts that are not factors of 12, junk data is sent past the defined LED array, causing stray colors to show up on the next LED. This is only an issue if the number of LEDs in the code is less than the number of physical LEDs. You can also get around this by defining the CRGBW array as one element larger than necessary, and leaving those last four bytes at 0.


This is mostly a proof of concept, rather than a turn-key solution. But if you have some color patterns generated using the FastLED library, this will let you use those patterns with RGBW strips until the library properly supports RGBW strips.

A huge thanks to Jim Bumgardner for sharing his method. If you found this post useful, please check out his website at


  1. Thanks a lot for your article!
    However the script doesn’t compile and gives me that error:

    sketch\FastLED_RGBW.h:45:64: error: ISO C++ forbids declaration of ‘operator=’ with no type [-fpermissive]

    What could cause the issue?

    1. What compiler are you using? This compiles fine for me using the Arduino IDE (1.8.2).

      Trying adding the keyword ‘void’ between ‘inline’ and ‘operator’ in the header file. That might be an oversight on my part.

      1. I’m using the IDEversion 1.8.5. Declaring it as void helped.

        Now I tried running your demo script, but the LEDs (SK6812 RGBW) do nothing.
        Everything works fine with the Neopixel Library.
        What else could have gone wrong?

        Thanks in advance!

        1. I’m not sure. I just tried using the code above and it works perfectly for me.

          Make sure you have the latest version of FastLED installed, and then check the hardware. My hardware setup for the RGBW strips is an Arduino Uno connected through a 470 Ω resistor, with everything powered directly by USB (only 8 LEDs on my demo board). Check that the voltages are as expected and if you have a logic analyzer or oscilloscope, check the output of the data pin.

          As I said in the post – this is a hack, and the timings between the two strip types are at their min/max limits. If your hardware is different the timings may be off enough to not work at all.

  2. Hi.
    Impressive work!

    I did get the example sketch to run all RGBW. Do you have any idea how to get this to work with Ambibox or Prismatik?

    note: I know very little about this stuff. Just trying to learn and to get some ambilight up and running. 🙂

    Manne Danneman
    1. I wouldn’t use RGBW leds if you’re getting started, because none of the ambilight software I know of uses RGBW either. You’d just be using an RGBW strip as RGB, and going through quite a bit of hassle to get it to work.

      That being said, you could use my ambilight code as a foundation. Though you’d need to add some extra code to keep track of the channel index to insert a ‘0’ byte at each white address.

      1. Hey! Thanks for the answer! Didn’t notice it until now.

        Yes I noticed it was way harder to figure it out with RGBW. So much I actually put it on hold for now. Haha. I just figured that eventually I will find more time to learn more about this or that someone would put up a working template that I could use. I was looking for a challenge but soon realised it was above my head.

        One thought I had was to just buy a ordinary RGB strip and use that. But it feels like such a shame when I have 3 m of this amazing looking (and expensive) strip. 🙂

        Thank you again for the answer!

        Manne Danneman Lundkvist
  3. This saved my project! I made a couple enhancements, having it auto-calculate the white value instead of leaving at zero if it’s not specified. Add this constructor in addition to the given one, and overwrite operator= as follows:

    CRGBW(uint8_t rd, uint8_t grn, uint8_t blu){ // If we pass in three values, correct for white
    w = min(rd, grn);
    w = min(w, blu); // Now w is the smallest of the three values

    r = rd – w;
    g = grn – w;
    b = blu – w;

    inline void operator = (const CRGB c) __attribute__((always_inline)){ // Turn RGB into RGBW with automatic white correction
    uint8_t w = min(c.r, c.g);
    w = min(w, c.b); // Now w is the smallest of the three values

    this->r = c.r – w;
    this->g = c.g – w;
    this->b = c.b – w;
    this->w = w;

    Daniel Stelzer

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.