Skip to content

briefnotion/Pi5-SpiLED-Engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 

Repository files navigation

Pi5-SpiLED-Engine

A stability-focused LED controller designed for the Raspberry Pi 5. This engine uses unrolled bit-packing and a supplemental threaded rendering class to ensure smooth, non-blocking animations. Optimized to handle the specific SPI clock characteristics of the Pi 5 to prevent color shifting and data corruption.

By leveraging the hardware SPI bus (spidev), this engine offloads the strict timing requirements of addressable LEDs to the hardware, eliminating the flicker and color shifting common with software-based bit-banging.

Key Stability Features

Leading/Trailing Padding: Injects 1KB of zero-byte "silence" to ensure a clean Reset signal for every frame.

Single-Shot Transfers: Sends the entire frame in one ioctl call to prevent timing gaps between LED data.

Unrolled Bit Packing: Optimized loops ensure maximum timing consistency and CPU efficiency.

DMA Alignment: Utilizes posix_memalign and mlock for page-aligned memory, ensuring the Pi 5's I/O controller can access the buffer without interruption.

Hardware Setup

LED Type: WS2811 / WS2812 / WS2812B (Addressable RGB)

Data Pin (DIN): Connect to Pin 19 (GPIO 10 / MOSI)

Ground: Ensure the LED strip and the Raspberry Pi share a common ground.

Power: Always power high-density LED strips with an external power supply; do not rely on the Pi's 5V rail for large arrays.

Software Configuration

  1. Enable SPI The Raspberry Pi's SPI interface must be enabled via the configuration tool:

Bash
sudo raspi-config

Navigate to Interface Options > SPI > Yes. Reboot if prompted.

  1. Increase SPI Buffer Size Standard Linux SPI buffers are often limited to 4KB. If you are driving more than ~170 LEDs, you must increase the buffer size.

Edit the boot configuration:

Bash
sudo nano /boot/firmware/cmdline.txt

Add the following to the end of the existing line (do not create a new line):

Plaintext
spidev.bufsiz=65536

Verify after reboot:

Bash
cat /sys/module/spidev/parameters/bufsiz
Should output: 65536

How To: Getting Started

Since the core logic is contained within WS2812Spi, getting your first animation running is straightforward.

  1. Create a simple main.cpp

C++ #include "render_leds.h" #include

int main() { int num_leds = 60; // Set your LED count WS2812Spi strip(num_leds, "/dev/spidev0.0");

// Optional: Enable Real-Time Priority (requires sudo)
strip.setRealTimePriority();

// Create a color buffer (RRGGBB)
std::vector<uint32_t> colors(num_leds);

while (true) {
    for (int i = 0; i < num_leds; i++) {
        // Fill with a simple color (e.g., Red)
        colors[i] = 0xFF0000; 
        strip.show(colors);
        usleep(50000); // 50ms delay
        
        // Clear for next frame
        colors[i] = 0x000000;
    }
}
return 0;

}

  1. Compilation Compile your project using g++. Ensure you include the helper files and link the pthread library for timing and threading support.

Bash

g++ -O3 main.cpp render_leds.cpp render_leds_helper.cpp -o led_engine -lpthread

  1. Running the Engine Because the engine uses mlock for memory stability and sets SCHED_FIFO for real-time priority, it must be run with root privileges:

Bash

sudo ./led_engine

Project Structure

render_leds.h / .cpp: The core WS2812Spi driver.

render_leds_helper.h / .cpp: Supplemental classes for high-precision timing (FLED_TIME), color management (CRGB), and frame-rate limiting (TIMED_IS_READY).

RENDER_LEDS_CLASS: (Supplemental) A threaded wrapper for non-blocking rendering. Useful for complex applications where LED updates should not stall the main logic.

Non AI Generated Note

I haven't tested the included example. I just wanted to put the code out there for anyone interested. The example 'stress_test.cpp' in the source folder should work though. Although, it does have a bug in it. wheel_cycle(uint8_t pos) function may work as well.

The WS2812Spi class is all that is needed to run LED light strips and it is included in the render_leds.h and the render_leds.cpp files.

To get the lights running in a tread, you will need to use the RENDER_LEDS_CLASS. I havent finished self containing it, but the meat of the code is there, as well as most of the function calls included in the render_leds_helper. If i get any demand for it I can zip it up to run. If you don't want to wait, im sure any AI chat box can help you get it working out of the box.

The code isn't perfect. There is plenty of things in there that can be refined, cleaned, dropped, and changed. The thing is, I ran it for a good 8hrs in a harsh enviornment and it worked without issuse. I'm a bit afraid of changing it. If its not broke, right?

However, there is plenty of fat that can be trimmed out. Enjoy.

If you mod, fork, dupe, and/or improve this code, send me a message. I can either just use your code, or pull the changes into mine.

About

A stability-focused (WS2811 / WS2812 / WS2812B) LED controller, via Pin 19, designed for the Raspberry Pi 5. Engine uses unrolled bit-packing and a supplemental threaded rendering class to ensure smooth, non-blocking animations. Optimized to handle the specific SPI clock characteristics of the Pi 5 to prevent color shifting and data corruption.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages