Addressable LEDs or NeoPixels are typically used in combination with an Arduino or similar microcontroller, due to the timing critical signal required to control them. An SBC such as the Raspberry Pi is not suited for such realtime GPIO activities, as the Linux operating system runs other tasks in parallel. Or at least that was the case until Jeremy Garff found a way to use the DMA (Direct Memory Access) module to transfer bytes of memory between different parts of the processor, without using the CPU and thus not being interrupted by the Pi’s OS.
This procedure works for all Raspberry Pi models except version 2!
Jeremy Garff has written a library called “rpi_ws281x”, which can be found on his GitHub page: https://github.com/jgarff/rpi_ws281x. It makes use of the Pi’s BCM2835’s PWM module to drive the controllable WS281X LEDs found in NeoPixel strips and rings. The folks at Adafruit have created a Python wrapper for the library along with some Python example scripts, making it look and feel like the Arduino NeoPixels library. So if you’re familiar with NeoPixels on the Arduino, you should be up and running with this version in no time.
To compile and install the library, follow the steps below.
First, install the dependencies required to download and install the library:
sudo apt-get update sudo apt-get install build-essential python-dev git scons swig
Next, download the files and build the library:
git clone https://github.com/jgarff/rpi_ws281x.git cd rpi_ws281x scons
Finally, install the Python wrapper:
cd python sudo python setup.py install
As you can see, these steps are very straightforward.
Hooking up the NeoPixels to the Raspberry Pi is extremely easy, just make sure the power supply used is properly rated for the number of NeoPixels you intend to use. For testing, I used a 5V/4A power supply to power the Pi and the NeoPixels (12 and 60 LEDs).
Make sure the ground signals of the NeoPixel strip/ring and the Raspberry Pi are connected. If they are not, the LEDs won’t function properly and will light up in unpredictable patterns.
Even though the LED strip/ring operates at 5V and the Pi’s GPIO at 3.3V, it appears that it is possible to drive the LEDs without having to use logic level conversion.
I tested two components:
- an Adafruit NeoPixel ring with 12 LEDs
- an addressable WS2811 60 LED strip from eBay
Both performed as expected using the sample script (strandtest.py), which I edited to configure the correct number of LEDs:
# LED strip configuration: LED_COUNT = 60 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 5 # DMA channel to use for generating signal (try 5) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
As you can see, it is also possible to edit other parameters to match the LEDs used, but also parameters such as brightness.