A kernel module able to run as many WS2812 strips as there are GPIO pins on Raspberry Pi Zero
A kernel module able to run as many WS2812 strips as there are GPIO pins on Raspberry Pi Zero. This kernael module + library to use it will allow you to specify as many LED strips as raspberry pi have GPIO pins (27), and connect up to 1024 LEDs to each. The kernel module will recieve a frame over a char device, freeze all interrupts on the raspberry pi, basically halting the kernel. now it will bitbang out the WS2812 frames on all strips at the same time using the GPIO registers, and resume the kernel. Time of the kernel being frozen relative to the LED strip length, so I would recommend many short strips and not few long ones. If you have any comments, feel free to contact me via http://urielguy.com, or here.
This module requires a Raspberry Pi 1/1B/Zero/ZeroW/ZeroWH. It will NOT run on Raspberry Pi 2/3, and will probably cause it to crash and burn. Maybe even literally. There is a branch in the repo for my attempts to get this to run on Raspberry Pi 3. I failed. Another thing you will have to do is provide logic level transition to all of the strips - Raspberry Pis will output 3.3V while WS2812 strips require 5V inputs. I like using 74HCT245 chips for that. Adafruit have some suggestions here: https://learn.adafruit.com/neopixels-on-raspberry-pi/wiring
sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get install raspberrypi-kernel-headers -y
git clone https://github.com/UrielGuy/raspi_ws2812.git
cd raspi_ws2812/ws2812_rpi0_lkm ; make
insmod ./ws2812_rpi0_lkm.ko
dmesg
and see some messages at the botton marking success. you can also see the /dev/ws2812_frame
file on your systemThis project provides a C++ Header file containing all you need to use the project. It is in the lkm_client folder inside the repo and fairly well documented.
Here is a minimal example:
#include "raspi_ws2812.h"
// Support 100 LED strips on GPIO pins 21, 5, 6
raspi_ws2812 LEDs(100, { 21,5,6 });
int main(void) {
while (true) {
// Clear the display
LEDs.Clear();
for (uint32_t led = 0; led < LEDs.max_strip_length()-3; led++)
{
// Set pixels so that each strip has its own color and LEDs seem to move down the strip
// Note that strip index is index to the list given in the constructor (0..2) and not a GPIO pin number(5,6,21)
LEDs.SetPixel((uint8_t)(led % 3), led + (counter), RGB_t(((uint32_t)0xFF) << 8 * (led % 3)));
}
// Advance counter in a loop of 3
counter = (counter + 1) %3;
// Display the frame
LEDs.SendFrame();
}
}
There is a slightly larger example in the repo