A very simple threaded and thread-safe class to control a string of ws2812 LED strips using SPI interfaces on Raspberry Pi/Orange Pi/etc. single board computers (SBCs) running Linux.
- The
numpypackage to work around the limited capabilities of a low-CPU-power computer. Python is quite expensive to do maths in, as well as move data around but this package, along with the Python packagespidevandnumpyuse the buffer protocol to massively improve this (https://docs.python.org/3/c-api/buffer.html).- Try to precompute the colors you need in memory in an
numpy.array(... , dtype=uint8)and then use a loop to write them with a slicefoo[5:50]as this prevents Python allocating memory for, and converting every single byte into auint8, every time it updates the LED string. - If not using
numpyarrays use simple Pythonlistinstead as this will be 1000x faster than iterating through adictorset. (Leverage Python buffer protocol usingnumpy.arrayorlistto transfer content by reference tospidev.writebytes2().
- Try to precompute the colors you need in memory in an
- An activated SPI port on your particular SBC using device overlays so the file
/dev/spidevX.Y(typically/dev/spidev0.0) appears on your SBC.- SPI on a Rasberry Pi: https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md.
- An example on Armbian (typically /boot/armbianEnv.txt) the OrangePi: https://unix.stackexchange.com/questions/496070/how-to-enable-spi-on-orange-pi-pc-in-armbian.
- User access to the SPI device node in
/dev.- An example
udevrule is provided,99-spidev.rules, which can be copied into/etc/udev/rules.d. (It will not take effect untiludevis reloaded or your SBC rebooted.) - The example
udevrule makes the/dev/spidevX.Ynodes available to members of the groupspidev- this may not be present on your system so you can create it withsudo addgroup spidev. Remember to add the user to this new group withsudo adduser username spidev.
- An example
Please note that an OrangePi Zero (32 bit ARM w. 512MB of RAM) can drive a string of >100 consistently with 1ms updates @5% CPU using a precomputed lookup table to generate the bytes sent out of the SPI bus. A normal SBC cannot power many LEDs - remember to use a separate high current DC supply if using 10+!). Start with just 3-4 if you are powering it from the SBC to test it out, when it is working you can increase the numbers to find out the limits of your particular SPI driver, CPU, RAM combination. If you do not use a separate supply you could possibly damage your SBC.
- Import as a library.
- Initialize an instance for each SPI port with WS2812 LEDs attached.
- use
.initorinit_from_dictSPIws2812.init( (bus: int, cs: int). num_leds:int )e.g.SPIws2812( (1,0), 15) )SPIws2812.init_from_dict(dict)e.g.SPIws2812.init_from_dict({"spidev": Path("/dev/spidev0.0"), "num_leds": 15})
- Start threads and open port with
spi.start() - Start animations with these functions:
spi.breathe()spi.chase()- ...
- Stop library, releasing spidev, & stopping threads:
spi.stop()
Simply install with pip from the repository with pip install https://...../ - it will install necessary pre-reqs.
This is already designed and built to be used as a library inside your own python code.
On an Ubuntu or Debian system:
sudo dash -c "apt update; apt dist-upgrade -y; apt install -y python3-pip python3-setuptools python3-dev python3-numpy"
git clone https://github.com/mattaw/ws2812-spi-python.git
cd ws2812-spi-python
python3 -m venv --system-site-packages .venv
source .venv/bin/activate
pip install -U pip setuptools pip-tools
pip-sync requirements.txt
If you wish to modify the code, or develop it further install the development packages with:
pip-sync dev-requirements.txt
Copyright 2021 Dr. Matthew Swabey Copyright 2021 Purdue University
License Apache 2.0, see the LICENSE file for full details.