CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-luma--led-matrix

A Python library to drive MAX7219 LED matrices, WS2812 NeoPixels, and APA102 DotStar LEDs on Raspberry Pi

Pending
Overview
Eval results
Files

neopixel.mddocs/

NeoPixel RGB LEDs

RGB LED strip and matrix driver supporting WS281x chips (WS2812, WS2812B, WS2811, etc.) with DMA interface for smooth animations and full-color control. NeoPixels are individually addressable RGB LEDs that can display millions of colors.

Capabilities

Device Initialization

Creates a NeoPixel device instance with configurable dimensions, rotation, and pixel mapping for various LED arrangements.

class neopixel:
    def __init__(
        self,
        dma_interface=None,
        width=8,
        height=4,
        cascaded=None,
        rotate=0,
        mapping=None
    ):
        """
        Initialize NeoPixel (WS281x) RGB LED device.
        
        Parameters:
        - dma_interface: WS2812 DMA interface (optional, auto-detected if not specified)
        - width: Number of pixels horizontally (default: 8)
        - height: Number of pixels vertically (default: 4)
        - cascaded: Total number of pixels in strip (overrides width/height if specified)
        - rotate: Rotation angle (0, 1, 2, 3 for 0°, 90°, 180°, 270°)
        - mapping: Array of pixel-to-physical offset mappings for non-standard layouts
        """

# ws2812 is an alias for neopixel
ws2812 = neopixel

Display Control

Controls the RGB LED output including color display, brightness adjustment, and cleanup operations.

def display(self, image):
    """
    Display a 24-bit RGB PIL image on the NeoPixel LEDs.
    
    Parameters:
    - image: PIL Image object in mode 'RGB' (24-bit color)
    """

def contrast(self, value):
    """
    Set LED intensity/brightness for all pixels.
    
    Parameters:
    - value: Brightness level (0-255, where 0 is off and 255 is full brightness)
    """

def show(self):
    """
    Restore contrast to previous level.
    Used after hide() to bring LEDs back to normal brightness.
    """

def hide(self):
    """
    Set contrast to zero (simulated off state).
    LEDs appear off but device remains active.
    """

def cleanup(self):
    """
    Reset device and free hardware resources.
    Should be called when finished using the device.
    """

Usage Examples

Basic LED Strip

from luma.led_matrix.device import neopixel
from luma.core.render import canvas

# Create 30-pixel LED strip
device = neopixel(cascaded=30)

# Set individual pixel colors
with canvas(device) as draw:
    draw.point((0, 0), fill="red")
    draw.point((1, 0), fill="green") 
    draw.point((2, 0), fill="blue")
    draw.point((3, 0), fill=(255, 128, 0))  # Orange

8x8 LED Matrix

from luma.led_matrix.device import neopixel
from luma.core.render import canvas

# Create 8x8 NeoPixel matrix
device = neopixel(width=8, height=8)

# Draw colorful patterns
with canvas(device) as draw:
    # Rainbow diagonal
    for i in range(8):
        hue = i / 8.0
        import colorsys
        rgb = colorsys.hsv_to_rgb(hue, 1.0, 1.0)
        color = tuple(int(c * 255) for c in rgb)
        draw.point((i, i), fill=color)

Unicorn HAT Layout

from luma.led_matrix.device import neopixel, UNICORN_HAT
from luma.core.render import canvas

# Create 8x8 matrix with Unicorn HAT snake-like mapping
device = neopixel(width=8, height=8, mapping=UNICORN_HAT)

# Draw normally - mapping handles physical layout
with canvas(device) as draw:
    draw.rectangle((0, 0, 7, 7), outline="white")

Animated Effects

import time
import math
from luma.led_matrix.device import neopixel
from luma.core.render import canvas

device = neopixel(width=8, height=4)

# Brightness control
device.contrast(128)  # 50% brightness

# Animated rainbow wave
for step in range(100):
    with canvas(device) as draw:
        for x in range(device.width):
            for y in range(device.height):
                hue = (x + y + step * 0.1) % 1.0
                import colorsys
                rgb = colorsys.hsv_to_rgb(hue, 1.0, 1.0)
                color = tuple(int(c * 255) for c in rgb)
                draw.point((x, y), fill=color)
    time.sleep(0.05)

# Cleanup when done
device.cleanup()

Custom Pixel Mapping

from luma.led_matrix.device import neopixel

# Custom mapping for non-standard LED arrangements
# Maps logical positions to physical LED indices
custom_mapping = [
    15, 14, 13, 12,  # Top row (right to left)
    8,  9,  10, 11,  # Second row (left to right)
    7,  6,  5,  4,   # Third row (right to left)
    0,  1,  2,  3    # Bottom row (left to right)
]

device = neopixel(width=4, height=4, mapping=custom_mapping)

Hardware Constants

Unicorn HAT Mapping

UNICORN_HAT: list[int]

Translation mapping for 8x8 Unicorn HAT converting snake-like physical layout to scan-like logical layout. This 64-element list maps logical pixel positions to physical LED indices.

UNICORN_HAT = [
    7,  6,  5,  4,  3,  2,  1,  0,
    8,  9,  10, 11, 12, 13, 14, 15,
    23, 22, 21, 20, 19, 18, 17, 16,
    24, 25, 26, 27, 28, 29, 30, 31,
    39, 38, 37, 36, 35, 34, 33, 32,
    40, 41, 42, 43, 44, 45, 46, 47,
    55, 54, 53, 52, 51, 50, 49, 48,
    56, 57, 58, 59, 60, 61, 62, 63
]

Hardware Requirements

  • Platform: Raspberry Pi or compatible Linux SBC with PWM/DMA support
  • Interface: PWM + DMA (via rpi_ws281x library)
  • Connections:
    • Data: GPIO 18 (PWM0) or GPIO 12 (PWM0 Alt) or GPIO 13 (PWM1)
    • Power: 5V supply (adequate current capacity required)
    • Ground: Common ground connection
  • Power: External 5V supply recommended for multiple LEDs
  • Current: ~60mA per LED at full white brightness

Error Handling

The device may raise the following exceptions:

  • RuntimeError: WS281x initialization failures, DMA setup issues, or hardware communication errors
  • luma.core.error.DeviceDisplayModeError: Invalid display dimensions or unsupported image mode
  • AssertionError: Invalid parameter values (brightness out of range, invalid dimensions)
  • OverflowError: Too many pixels specified for available memory/hardware limits

Performance Notes

  • Uses DMA for efficient data transfer without CPU blocking
  • Supports up to 1000+ LEDs depending on available memory
  • Update rates of 60+ FPS possible for smooth animations
  • Color depth: 24-bit RGB (16.7 million colors) with 8-bit brightness control

Install with Tessl CLI

npx tessl i tessl/pypi-luma--led-matrix

docs

apa102.md

constants.md

index.md

max7219.md

neopixel.md

sevensegment.md

unicornhathd.md

tile.json