Driving WS2812 LED strips with the ESP8266

There’s a really captivating article on Tweaking4All illustrating the various effects (firelight, bouncing-balls, chasers, etc) that can be easily reproduced with the common WS2812, addressable, RGB, LED strips, available from just about every vendor out of the Middle Kingdom.  Although the article is a couple of years old and is aimed at Arduino hardware using the FastLED or NeoPixel libraries, the routines are, for the most part, directly transferable to the ESP8266 (both libraries are available for the ESP when using the Arduino framework).  When used with the ESP8266 though, there are a couple of pitfalls which you need to be aware of:-

  • 3v3 vs 5v voltage levels
  • The ESP8266 wireless housekeeping requirements

The first is something you need to pay a little bit of attention to, in order to prevent damage to the ESP GPIO pin.  It’s very easy to isolate your ESP8266 from the WS2812 5v supply voltage and provide a low impedance drive for the WS2812 bus at the same time, using a cheap, PNP transistor in emitter-follower configuration.  An emitter-follower is a non-inverting buffer, which provides a medium to high impedance on it’s input (so it doesn’t place any significant load on the GPIO pin) and presents a low impedance output (meaning it can drive more current than the ESP GPIO pin can alone).PNP Emitter Follower  Unlike the more traditional common-emitter transistor circuit, the emitter follower doesn’t amplify the input signal at all; in this circuit it is acting as a switch, but while the output from the GPIO is switching between 0v and 3v3, the output of the emitter-follower is switching between 0v and 5v.  Thus this simple circuit not only protects your ESP from damage, but also provides the correct voltage swing for the WS2812 data bus, too.  Almost any common, small-signal PNP transistor (2N3906, BC560) will work in this configuration; specific type is not too critical.

The second issue is the common watchdog-timeout issue which plagues applications which spend too much time in tight, time-critical loops without allowing the ESP8266 time to attend to its WiFi housekeeping.  The answer in this case is fairly simple …just put a couple of calls to yield() into the code in strategic places (one in the top of the loop function and another following the call to showStrip() , in whichever example code is being used, worked well for me).  Unless you’re doing something insanely complicated and insanely fast, you shouldn’t notice any visible difference to the display.  If you are running something i-comp and i-fast, you should bump the ESP8266 speed up to 160Mhz to handle it, anyway (“board_f_cpu = 160000000L” in your platformio.ini file); you don’t need to make any changes to the code to handle the faster CPU clock.

With these two issues addressed, you should be able to run any of the examples from the Tweaking4All site.  You have the choice of using either the FastLED or NeoPixel libraries and the Tweaking4All collection comes with all of the examples duplicated across two directories, one for each library.

Other Options

There’s also a second version of the FastLED library available from Cory R. King which adds DMA output for the ESP8266 for a smoother, flicker-free output.  Note that DMA hardware in the ESP8266 uses pin-3 (which is the UART RX pin) as the output …so no matter which pin you define in the display code, it will always use pin-3.

In addition to those already mentioned above, Makuna (Michael C. Miller) has also done a lot of work on optimizing WS2812 driver code specifically for the ESP8266 and ESP32 processors with his NeoPixelBus library.  It has multiple interfacing options (DMA, UART and bit-bang) available.  DMA is the default (and recommended) operating mode.  Users have reported that, for the ESP8266, the NeoPixelBus library is the most robust and reliable method for driving addressable LEDs when the WiFi must also be in use.  Although Michael’s examples are quite comprehensive, you may find yourself with some coding to do if you want to convert all of the Tweaking4All demos to run using this library.

3 thoughts on “Driving WS2812 LED strips with the ESP8266

  1. To be strictly accurate, your PNP buffer output doesn’t switch between 5V and 0V. Assuming the input drive switches between 3.3V and 0V, the output will switch between about 3.9V and 0.6V, which may be OK to drive the LEDs.


  2. I’ve only just moved over to PlatformIO from the Arduino IDE and discovered that the syntax for changing the cpu speed is now:

    board_build.f_cpu = 160000000L

    I’ve used a similar buffer in my design but without the resistor in the base circuit as it is not needed. I’ve also added a 330R resistor in series with the output to the string of WS2812B LEDs as is often recommended.

    The 1K8 resistor is a compromise between the power used by the buffer and the speed of the rising edge of the output waveform. Power is not really an issue, given that the LEDs use far more power than the buffer, but I felt a 1K5 gave me enough improvement in the rising edge that I went for that value.

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s