FAB_LED - WS2812B, SK6812, APA104, APA106 addressable LED library


I'm looking for a few folks to test my new LED library on different hardware.
Here's some types of tests I'd look for:

  • Arduino boards at different frequencies (I've tested 16MHz quite a bit)
  • ARM Arduino boards
  • ARM/AVR controllers chips programmed directly without bootloader
  • Different LED strips with possibly different timings ws2812/APA104
  • Multiple LED strips connected on different ports
  • Long LED strips (100's or thousands of LEDs)
  • Code scrutiny to crowd-source enhancements to the code

Currently the library supports WS2812B/APA104 LEDs, with only a data pin.
It does not support APA102, SPI based strips, which have both a clock and a data pin.

The library has code examples, and testing can be as simple as running the examples and verifying they work.

I am looking for validation that the basic functionality works on most hardware thrown at it, before listening to ideas and requests for enhancements. Until then, it is too soon for folks to play with it.

Link to library


I know FastLED and Adafruit's libraries are quite popular and readily used. However with this library I'm tackling what I feel are limitations of those libraries.

  • They use a display buffer that eat memory
  • They require you to draw in it, THEN call a display routine

FAB_LED does not use a buffer. It displays directly the array you are manipulating.

FA_LED supports arrays with a wide range of pixel formats, from uint16_t to uint32_t, and also supports color palettes. With a palette, pixel formats can shrink to 1 bit to 8 bit per pixel. The current software limit is 64K pixel arrays per strip.

FAB_LED supports calling the display routine multiple times to repeat a pattern on your LED strip. You're only limited by the refresh cycle you desire for super long LED strips. You don't need to draw that pattern in memory multiple times, and can service an infinitely long LED strip.

FAB_LED will also provide some primitives to support 2D displays, with pixel remapping and basic sprite support.

Overall my goal is to allow even a low end Arduino board to drive LED strips of any size.


This demos a relatively long LED strip of 170+ LEDs, using 16 bytes to store the pixel patterns.

Video demo

This is my first test at 2D support (not yet ready to beta):

Very good indeed !! (although I havent tested it yet)

I have a very simple chunk of assembler that I use in my projects that rattles out the NRZ code to WS, I just pass a pointer to where in memory I want to the asm to start reading and a number of bytes to spew, and off it goes. It is cycle perfect to 800Khz, and doesnt require any pre-math or copying of buffers

I have also added a brightness control (3 cycle) chunk of asm so that red, blue and green can be balanced OR an overall brightness given to the show

I hope to be posting my 'very simple' code soon


The issue with an ASM solution is that it is hardly portable. In this library I implement the bitbanging using C constructs. You do have some time to push the bits to the LED strips which allows for some manipulations, provided you respect the high-level timings. If brightness modulation was an important feature to add, I could consider doing that.

The goal here is to make a production quality library, at least to the Arduino community standards.

The goal here is to make a production quality library, at least to the Arduino community standards.

Absolutely, you are right.

With my application the code has to be hand-created for minimal timing inside the loop with no pre or post calculations, also minimal code space is required so that I can get all the other feature I need into the software. There is a little bit of manipulation I can do, but essentially we are at different ends of the scale :slight_smile:

I often take a pre-written library and take out only the parts I need, and try and simply to fit my application

I don't think we are:
You have to understand what a compiler does. Anything that you don't use is optimized out. The way I wrote my library is to take advantage of that as much as possible and in fact eliminate as much as possible code overhead.
So now a library can offer a bunch of features and what's not used is just zero cost.

An experiment would be for you to light some LEDs in a very simple manner, with your ASM solution,
and try with this library, and compare the compiled size. To be fair, the comparison has to be with your code using setup() and loop().

I wonder how many bytes your coding would save.

@mcnobby: I did a verification:

FAB_LED uses 250 bytes of FLASH memory if you use 2 functions (one to clear the LED strip and one to display your pixel array to the LED strip). It's 146B of FLASH if I only use the display routine.

How much bloat do I have in my library vs an optimized ASM solution? I feel I have something pretty small footprint :stuck_out_tongue: I need to compare to adafruit and FastLED sometimes.

What is the cost to abstract the LED strip and the pixels so the code becomes portable? Note, I've also added support to mix LED strips that have different properties: SK6812, APA106, APA104, ws2812... I'm waiting for some APA102s to implement LED support for SPI protocol too.

That seems pretty good !!

I havent actually done a complete stand-alone asm test as yet, but I will

I dont think my code is at all portable, it relies on 16MHz AVRs, as the timing is cycle-counted rather than timed

Also mine only supports WS281x at the moment (but I think that also works with TM180x)
SK6812 are very similar to WS2812, although I have seem they can use a 4th channel for white, the applications I use do not care about R, G and B order.. I just use the incoming DMX/artnet/sACN/TMP2net data and port it straight to the LEDs (channel for channel), the driving application controls the order of RGB and any other byte stuff that may be needed

oh! If you have a spec for the DMX communications, I might be interested in adding that to the LED library. I haven't really looked into it, but I know some folks who use DMX hardware.

Otherwise someone must have a DMX library to decode the addresses and data.

My current code change is in a branch until I have some folks validating it:


Converting DMX or Ethernet-based comms (ArtNet/sACN etc) into these LEDS is absolutely HUGE these days.
Lots of free software for driving it and some big communities talking about it

I have done several projects involving all of the above

If you are looking at serving a large amount of LEDs, then ethernet is the way to go !!

Am I right in saying that your software uses a palette-style approach for passing data to the LEDs ?

Palettes is ONE of the modes.

I have not yet fully finalized how it's going to work, because I want lso to support multi dimensional displays (2D and maybe by extension, 3D), and I want all of it to fit together somehow.

today, for palettes you just call the sendPixels() method with the palette array and the pixel array. The pixel array just references a color index, and the palette defines it. I support 1, 2, 4 and 8 bit palettes, aka 2, 4, 16 and 256 simultaneous colors.

The main thing I got now is a nice way to handle standard 3 byte and 4 byte pixel data types (aka non palette).

If I find the means at some point, I will want to demonstrate a large LCD display, controlled by an AtTiny85.

I just updated the readmes etc. I actually measured the Adafruit's compiled code is 2848 bytes, versus 736 bytes for the FAB_LED library to do the same simple display of a few pixels.

Lukas K. demonstrated soldering two types of LEDs, and addressing them with FAB_LED on youtube.
WS2812B are GRB, and SK6812 are RGBW LEDs.

The code is relatively simple, based off example A.

Sorry for reviving an old thread but I believe this is best kept here. Is there any way to get this code to run on the Mega? It works fine on my Uno but I cannot get the same code to run when I load it to my Mega.