Overview

NeoPixels are really great in terms of pin use. They only require three pins, and two of those are power and ground. They only need one pin for data which is used for all the NeoPixels attached. Amazing.

However, this comes at the cost of requiring the data signal maintain a very specific timing requirement. See here for some details from the excellent NeoPixel Uberguide.

The NeoPixel SPI Hack

This is a pretty cool hack. The key enabling feature is the much faster relative speed of the SPI bus compared to the NeoPixel data signals. The NeoPixel data signal runs at 800kHz = 0.8MHz with some older ones running even slower at 400kHz = 0.4MHz. A SPI bus can be clocked in the 10s of MHz - orders of magnitude faster than NeoPixel!

This hack takes advantage of that faster speed to "synthesize" the NeoPixel data signal on the SPI's MOSI pin. In its most simple form, the hack turns every bit of NeoPixel data into a specific byte in the SPI data. There only two bytes that matter - one that represents a NeoPixel 0 bit, and one that represents a NeoPixel 1 bit.

Once the desired NeoPixel data has been translated into SPI data, it is simply clocked out on the SPI bus. The SPI bus frequency is set such that the data comes out at the expected NeoPixel timing. Then, by wiring the SPI MOSI pin to the NeoPixel data in pin, you can drive NeoPixels using the SPI bus. From the NeoPixel's point of view, it just sees the specific data signal it expects and you get happy blinky NeoPixels.

SPI Support in CircuitPython NeoPixel Library

All this work has been done for you via a new NeoPixel_SPI class that has been added to the CircuitPython NeoPixel library. When driving NeoPixels via a SPI port, you simply use this class. After the initial setup, you can then use the NeoPixels as normal.

Let's see some examples.

This guide was first published on Oct 14, 2019. It was last updated on Oct 14, 2019. This page (Overview) was last updated on Nov 15, 2019.