Optimized STM32F103 library for driving up to 16 chains of WS2812B LEDs at once.
Alternatives To Stm32f103_fastnp
Project NameStarsDownloadsRepos Using ThisPackages Using ThisMost Recent CommitTotal ReleasesLatest ReleaseOpen IssuesLicenseLanguage
20 hours ago4August 03, 2021283mitC++
Control WS2812B and many more types of digital RGB LEDs with an ESP8266 or ESP32 over WiFi!
3 days ago4mitC++
WS2812 FX Library for Arduino and ESP8266
a year ago81mitC
The ESP8266 based multi-client lighting gadget
9 months ago1August 10, 202098otherC#
Official software for blink(1) USB RGB LED by ThingM
2 years ago10gpl-3.0C
Light weight library to control WS2811/WS2812 based LEDS and LED Strings for 8-Bit AVR microcontrollers.
4 days ago16otherC++
Open source ambient lighting implementation for television sets based on the video and audio streams analysis for Windows, macOS and Linux (x86 and Raspberry Pi). Includes real-time HDR tone mapping and multi-threading for better performance.
24 months ago3November 14, 201617mitPython
Python module to drive LED Matrices & 7-segment displays (MAX7219) and RGB NeoPixels (WS2812 / APA102)
Wled Wemos Shield370
3 days agomit
Wemos D1 Mini (ESP8266) or Wemos ESP32 D1 Mini (ESP32) based universal shield for WLED firmware
3 years ago70gpl-3.0C++
ESP8266 based WiFi ArtNet to DMX, RDM and LED Pixels
Adalight Fastled260
2 years agogpl-3.0C++
Adalight with FastLED support
Alternatives To Stm32f103_fastnp
Select To Compare

Alternative Project Comparisons

fastNP for STM32F103

What is this?

fastNP is an STM32 library for refreshing multiple chains of addressable LEDs in parallel. It works with WS2812B LEDs and their clones like SK6812, etc (often called NeoPixels). Up to 16 chains of LEDs can be refreshed in parallel, without overclocking the CPU. I have developed and tested this on an STM32F103 microcontroller (on a so-called "Blue Pill" board) but it should be possible to port it to other STM32 micros as well.

This library builds on the concepts of Martin Hubáček's WS2812B DMA Library, who uses a brilliant technique for refreshing multiple LED chains using one Timer and three DMA channels. In fastNP, we try to take this a step further, by heavily optimizing the code that generates the intermediate DMA bit-buffers, which is basically the bottleneck when trying to refresh multiple channels. With a little bit of inline assembly, we can generate a bitbuffer for all sixteen channels, within the time it takes to perform one half of a DMA transfer.

How do I run the example?

  1. Grab an STM32F103 board (I'm using Blue Pill but anything similar should work).

  2. If your board uses anything other than an 8MHz HSC oscillator, modify the CubeMX project (or clock settings in main.c) so that the CPU and Timers still run at 72MHz.

  3. Connect strips of WS2812B LEDs to any pin(s) on PORTB. By default, LED data will be sent to GPIOs B0-B15.

  4. Grab the code and compile: make (assuming you're on Linux)

  5. Flash the board make flash if you have the st-flash utility on Linux, or use whatever way you prefer

  6. Watch the pretty lights scroll by. See demo_main.c for more info.

NOTE: If writing your own Makefile (or using some other build system), an optimization level of at least -O1 is required. Otherwise, GCC generates code that is too slow.

How do I use this in my project?

First, you'll want to customize ws2812_led.h for your project. If you are using fewer than 16 LED channels, set WS2812_NUM_CHANNELS to the appropriate number. In practice it's usually okay to leave this as-is (you can specify zero-length framebuffers for the unused channels) but this is more optimal.

All your LED channels must be connected to the same GPIO bank (ie, all LEDs must be on GPIOA, or on GPIOB, but you can't mix the two). If using fewer than 16 channels, you can also decide which channels map to which GPIO numbers within the GPIO bank. By default, channel 0 goes to GPIO0 (A0 or B0 or whatever bank you're using) but you can change this relationship in ws2812_led.h if necessary.

Next, you'll need to set up your channel array. This is an array of struct led_channel_info and its length must be WS2812_NUM_CHANNELS. This array contains the framebuffer pointer for each channel, as well as the length of the framebuffer for that channel. Unused channels should have their length set to 0. Note that framebuffer lengths are in bytes, rather than in terms of number of pixels. This is because some LEDs want 3 bytes (R, G, B) and other types of LEDs want 4 bytes (R, G, B, W). The library doesn't actually care what kind of LEDs you're talking to, as long as you've laid out your framebuffers in a way that your LEDs expect.

Next, you'll want to call ws2812_init(). This sets up Timer2 and all the DMA channels, but it doesn't send out any data yet.

Then, we disable interrupts, call ws2812_refresh(), passing in our channel array, and the GPIO bank we want to use. Finally, we may (optionally) re-enable interrupts.

See the following code snippet:

// Declare channel array
struct led_channel_info channels[WS2812_NUM_CHANNELS];

// Clear it out
memset(channels, 0, sizeof(channels));

channels[0].framebuffer = <pointer to some byte array>;
channels[0].length = <framebuffer length in bytes>

channels[1].framebuffer = <pointer to some other byte array>;
channels[1].length = <framebuffer length in bytes>

// Send out the image data!
ws2812_refresh(channels, GPIOB);  // If using some other GPIO bank, change it here

For more info, take a look at demo_main.c.

Written with StackEdit.

Popular Ws2812 Projects
Popular Led Projects
Popular Hardware Categories

Get A Weekly Email With Trending Projects For These Categories
No Spam. Unsubscribe easily at any time.