RGBW neopixel leds

Posted on
  • (edited with some clarification) Just got a strip with "RGBW WS2812B" Leds from banggood. The good news is, the neopixel library it just works! If the number of LEDs is divisible by 3, or you pad it.
    For example (on MDBT42Q module):

    require("neopixel").write(D14, [50,0,0,0, 0,50,0,0, 0,0,50,0, 0,0,0,50, 50,50,50,50, 50,50,50,0]);

    produces green, red, blue, and three "white"s.
    But the library throws an exception if I try to write a single RGBW pixel:

    require("neopixel").write(D14, [50,0,0,0]);

    Tried to dig into the c code, and create a writeRGBW method, initially I thought it's just checking for different length :) But that rabbit hole is a bit deeper with all the device specific drivers...

    @Gordon you have done a great job documenting the build process, had a custom build for the MDBT42Q module in a couple of minutes!

    Do you plan to modify the library for official support? Or just add the workaround to the docs?

  • There is always the fallback solution

    SPI2.setup({baud:3200000, mosi: B15);
    SPI2.send4bit(g.buffer, 0b0001, 0b0011); 

    @Gordon showed me when I had issues (w/ 2v01), see x by y w/ 24 bpp Graphics buffer visualized with neopixel string (conversation), post #7, where colors were off and unexpected pixels showed...

    The fix is/will be in for 2v02+

  • Thr 2019.02.07

    'Just got a strip with RGBW WS2812B Leds'

    The above needs clarification as WS2812b are Neopixels, while RGBW are most likely SK6812 Neopixel LEDs. Subtle naming convention. Either one or the other, but not RGBW WS2812b Leds   32 vs 24


    'the neopixel library it just works'

    Well yes and no. While the Neopixel library referenced using the require instruction does work as described right out of the box illuminating with color, if and only if, the array referenced is in the correct RGB format. If true Neopixels were what was tested, then the output would have been GRB not RGB.

    'If the number of LEDs is divisible by 3, or you pad it'

    Did you mean the referenced array is three times the size of the equivalent number of Neos in the strip?

    'and create a writeRGBW method'

    What exactly will this function do? Is the intent to individually address each Neo by way of an array offset or something of the sort? 32 bit data variant?

  • Ok, there are more things to RGB / RGBW leds that I knew :)

    The "RGBW WS2812B" Leds are from banggood. So maybe the seller knows what exact chip it usess...
    For example (on MDBT42Q module):

    require("neopixel").write(D14, [50,0,0,0, 0,50,0,0, 0,0,50,0, 0,0,0,50, 50,50,50,50, 50,50,50,0]);

    produces green, red, blue, and three "white"s. Not visible on the image, but the uC is at the green side.

    But the library throws an exception if I try to write a single RGBW pixel, because the array length is not divisible by 3:

    require("neopixel").write(D14, [50,0,0,0]);

    My writeRGBW idea would be simply a write that works with multiples of 4 bytes out of the box :)

    1 Attachment

    • rgbw_.jpg
  • ...either a separate module or and extra parameter could help with that, I guess. But there is more to it.

    Did you give the approach as described in post #2 a shot?

  • Back in the days where there was no neopixel module we did this with send4bit(). I had no problems with RGBW led pixels. The pixels are SK6812 with three variants RGBNW (natural white), RGBCW (cold white) and RGBWW (warm white). I used them for a bike lights project. If you add plastic lenses to the chips, they get quite bright ;-)

    Edit: there's a RGBW neopixel library at Adafruit.

  • Thanks for the comments! I guess didn't make it clear: it's working fine. Sorry for the confusion!

    Just couldn't find any info in the docs or in the forum (TIL forum search doesn't search in message bodies). Not knowing the proper chip type didn't help either. So I thought just post what I found. Just to find out later, that info was already posted in different threads. These are nothing new after all...

    @allObjects Didn't try, because it is working with neopixel.write. :)
    That issue didn't affect me, because I use an NRF52.

    But now I know more about these LED chips, thanks everybody!

  • Here you go. 0b0001 and 0b0011 are approximations of the timings for logical 0 and 1 in the WS2812B/SK6812 spec sheets.

  • There is always the fallback solution

    I'm afraid that only works on STM32 - not nRF52s :)

    forum search doesn't search in message bodies

    I know - I believe it can be turned on via a checkbox (I think?), but the default is off which is kind of confusing!

    @AkosLukacs there's absolutely no reason why what you're doing is a problem. I wouldn't add a specific RGBW write command - the ideal solution would be to remove the check.

    However I just had a quick poke around and the nRF52 code is nontrivial to change and would potentially cause problems if we did that - so for now I have just documented the need for rounding up.

    I do eventually want to merge this mass of different code. It's basically all doing the same thing (with the exception of the crazy hard-coded one for Wio LTE) so I could make the code that created the bit patterns common - and at that point I'd like to remove that 3 byte limit and also add the ability to invert the signal (to allow 5v logic level output using just a single transistor and resistor).

  • ...to finish @Spocki 's comment

    ...0b0001 and 0b0011 are approximations of the timings for logical 0 and 1...

    relative to the baud rate SPI is set up.

    In @Gordon 's fall back sulution (see post #2): 3200000. Because: 3200000 / 4 = 800kHz as specified to be the max speed (of today) neopixel strings can be driven.

    See data sheets:

    Surprisingly - or not - the timing specs do not match exactly... but most of the time stay within each other's tolerances...:

  • Fri 2019.02.08

    Thank you @AkosLukacs for the source and image from #4 above.

    @Spocki thanks for the trio variant summary: RGBNW (natural white), RGBCW (cold white) and RGBWW (warm white)

    AkosLukacs, how did you determine that quad Uint's were needed, as the BangGood page specifies RGB+White and also indicates (while incorrect) WS2812 (tripplet Uint's), which you (array divide by three) have proven can't be - see what follows. If a S.W.A.G.'d guess, then it appears you may have gotten lucky there, even though you were led to believe you received WS2812

    Did anyone else observe the inconsistency?

    From image in #4 the output as explained is from right to left: (reversed here)

    Green : Red : Blue : Yellowish White : Bright White : RGB White

    Spec sheet SK6812 shows RGBW   which can't possibly be

    as we have #4:

    [50,0,0,0, 0,50,0,0, 0,0,50,0, 0,0,0,50, 50,50,50,50, 50,50,50,0]
       G R B W   G R B W   G R B W   G R B W­   

    Can't be these either ref: RGB WS2811 or BGR APA102


    So, do we have yet another mis-represented Asian knockoff, or a spec sheet that is incorrect and we now need to search for yet another variant to contend with?

  • The commonly used neopixels are async ones with only 4 function pins: GND, 5V, data_in and data_out. Then there are these sync one with 6 function pins: GND, 5V, clock_in, clock_out, data_in and data_out... and with that a totally different protocol. First is time critical because it derives the 0 and 1 from the time differences when the signal changes 'within the bit',. the second one does clock for latching. and is less to not at all time critical...

  • @Gordon I think checking for 3 or 4 byte length, and throwing an error if the array length doesn't match the expectation is a valid. I guess 99% it's a programming error. Ran into it myself when messing with these LEDs. :)
    Getting a clear error (IMO) is way better than debugging or blaming LEDs / the library / sample code.

    @Robin Well, there are four colors per chip, so trying 4 bytes per pixel felt a good guess. Add some trial and error, and got them working.

    (Edit: I was wrong, same behavior on the STM32) Regarding RGB / GRB: There is something that looks strange in the NRF driver

    typedef struct
        uint8_t   green; // Brightness of green (0 to 255)
        uint8_t   red;   // Brightness of red   (0 to 255)
        uint8_t   blue;  // Brightness of blue  (0 to 255)
    } rgb_led_t;

    The first color in the struct is green, that might be the reason for the strange color order.

    I will try it with an STM Espruino tomorrow.

    Or simply it's banggood, the item and description is not expected to match perfectly...
    Sometimes they list half a dozen part numbers in the name, and drop in the words like "replacement" or "upgraded"...
    Watched some youtube videos about RGB and RGBW strips, and they mentioned that the color order may change between manufacturers and batches. They might be RGB, GRB, or RGBW, GRBW, etc. So if you plan on creating a long strip, better buy it together...

    @allObjects Yes, mine are async ones. 4 pins on the LEDs, and the strips have 3 wires: GND, VCC, and Data in. Data out on the other end, and no clock signal.

  • Sat 2019.02.09

    While I would have someone with more compiler level skills answer this (I'm an end user like yourself) in detail, I am able to suggest the following:

    'Sometimes they list half a dozen part numbers in the name'

    Yes, annoying isn't it. Their description of WS2812b is an error as you found out.

    'The first color in the struct is green, that might be the reason for the strange color order'

    The beauty of C/CPP is the ability to use pointers to access items. The structure above allows for the definition of the three color items, and as you were on the right track, just needed to get to the usage part to see how that structure is implemented. Those three items therefore, can be used in any order as can be seen by:

    Using the link you provided NRFDriver in #13 above, but use the i2s_ws2812b_drive.c file


    and now my understanding of 'C' is now in question as from line L75 those colors are bit shifted.
    uint32_t rgb_data = (p_led->green << 16) | (p_led->red << 8 ) | p_led->blue;

    Am I getting Javascript and C/CPP/C# muddled here, as I always believed the order of a structure definition didn't set the order of the data. Anyone able to clarify here?

    As you can see, the above module is for the nRF devices using I2S

    The following is for STM using I2C  hardware SPI

    @Gordon passed along this link some time ago for the Neopixel source:



    but the only reference searching GitHub turned up


    L51 unsigned char rgb[] = {(unsigned char)g,(unsigned char)r,(unsigned char)b};

    which does perform a byte reorder, but why is this in the WioLTE file?    Neopixel !== GPS

    'The Seeed Wio LTE board is an open source gateway which enable faster IoT GPS solutions'

    Is it possible there is a suitable Neopixel plug that is to fit into the I2C pin connector on that board? e.g. This board has multiple other uses than that shown?

    I was unsuccessful at locating the source file that contains how the byte order appears for

    My understanding is that to keep the data ordered, it is assumed that it will be RGB to keep the mental model accurate, and left up to the implementer (us) to provide the byte oder to the setup array for require("neopixel").write()

  • Visualizing the neopixel timing specifications... and comparing different providers and the SPIX.write4(... option:

    • Top half -BLUE - shows 0 bit timing.
    • Middle - Brown, in between - shows the SPIX.write4(... 0 and 1 bit timing.
    • Bottom half - ORANGE - shows 1 bit timing.

    Times are to scale. Numbers are times in [us]. The protocol is quite smart and self-reconditioning takes place between the pixels (by the built-in circuitry).

    The fat blue and fat orange lines show the exact specified values. The respective fine lines are combinations of minim and maximum allowed values - tolerances - cumulated/cascaded:

    • The shortest / fastest times with all values at their allowed minimum get a bit done in 0.85[us]... still way in the range of 0.65[us]..1.25[us].
    • The longest / slowest with all values at their allowed maximum get a bit done in 1.6[us], still within the range of 1.25[us]..1.85[us].

    SPIX.write4(... w/ 3.2MHz baud rate and writing of 0b0001 and ob0011 for the actual 0 and 1 bit come darn close to spec using only 1/3 and 2/3 of the tolerance...

    2 Attachments

    • neopixelTimings.png
    • timingsComparison.png
  • @Robin Of course I was wrong about the wrong order in the struct. Same behavior (GRB) with STM32.

  • I think the mention of r/g/b in the struct for nRF52 is a red herring. It just takes sets of 3 bytes and pushes them out in order. Depending on what pixels you use red may not actually contain the bytes for red.

    It's another reason why it'd be nice to create just a simple, single bit of code for creating neopixel bit patterns that got shared across all devices.

  • Just a note: all the "pixels" I got recently work flawlessly with 3.3v controllers. No diode to drop the supply voltage, no nothing
    Tried running these with MDBT42Q module and ESPs. Powered the LEDs from USB -> 4.9V at the output of the LEDs. And a full strip with a proper 5V power supply that outputs ~5.0-5.1V, all worked without any problems.

    And all of them are GRB or GRBW.
    Maybe someone on the far east created a "compatible" chip that works reliably with 3.3v?

    8x on a board, single leds, GRB strip, GRBW strip

  • Wow, thanks for letting us know. That's really interesting - makes sense that they'd have made something though!

  • Just a note: all the "pixels" I got recently work flawlessly with 3.3v controllers. No diode to drop the supply voltage, no nothing

    Can confirm this for btf lighting products too

  • Fri 2019.03.22

    continuation of #11 above

    A month ago, I put together a table of datasheets reference to help answer the color byte order of this family of multi-color LEDs

    REFERENCE table of RGB Led datasheets 3528 5050 WS2811 WS2812 SK6812 APA102 NeoPixel

    Again we have a web page indicating (incorrectly) the chip used in their strip offering as in GRBW from #18 above. The images appear correct, as the yellow tinge phosphor is present, but that then means this strip can not be a WS2812, as there isn't the 'W' component for the byte array of a WS2812 as there isn't the yellow phosphor marking either. (web page offering title is incorrect) when making a purchase, caveat emptor

    @AkosLukacs did you by chance locate a datasheet for this GRBW SK6812 variant?

  • Yes, saw that, but didnt't want to spam that thread, since I have no datasheet.
    No marking visible on the LED chips themselves either. I can try to desolder one, but I doubt that there would be any usable part number on the chips...

  • @Robin, world has become fluid... over time... unfortunately... and specs are often not as concise as we like, nor do images always match text and vice-versa... and more so reality... (If I'd have ordered RGBW as catalog / image(s) show and receive RGB only or worse, it is return on cost of merchant. Ambiguous catalog entries w/o free return just do not turn into order entries). In @AkosLukacs ' referenced item though, description, image, and text in merchant's context imply RGBW and 32 bits to send to make it right!

  • Mon 2019.03.25

    'merchant's context imply RGBW and 32 bits to send to make it right!'

    Ahhhh @allObjects, I thought you were with us here. Please re-read #1, #18, and my #21

    @AkosLukacs points out GRBW as does the output #1 shows this also. I agree with that and thus point out the advertiser WS2812B error as there isn't the white component in that device. 24 bit. So is a 32 bit SK6812 variant, not WS2812B

    'I can try to desolder one'

    No need, unlikely to result in part number.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

RGBW neopixel leds

Posted by Avatar for AkosLukacs @AkosLukacs