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

apa102.mddocs/

APA102 DotStar LEDs

APA102/DotStar LED driver supporting SPI and bitbang interfaces with individual brightness control via alpha channel. APA102 LEDs offer higher refresh rates and more precise color control compared to WS281x chips.

Capabilities

Device Initialization

Creates an APA102 device instance with configurable dimensions, interface selection, and pixel mapping.

class apa102:
    def __init__(
        self,
        serial_interface=None,
        width=8,
        height=1,
        cascaded=None,
        rotate=0,
        mapping=None
    ):
        """
        Initialize APA102 DotStar LED device.
        
        Parameters:
        - serial_interface: Serial interface (SPI or bitbang), optional (defaults to bitbang)
        - width: Number of pixels horizontally (default: 8)
        - height: Number of pixels vertically (default: 1)
        - 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
        """

Display Control

Controls the RGB LED output with support for individual pixel brightness control through the alpha channel.

def display(self, image):
    """
    Display a 32-bit RGBA PIL image on the APA102 LEDs.
    The alpha channel controls individual pixel brightness.
    
    Parameters:
    - image: PIL Image object in mode 'RGBA' (32-bit color with alpha)
             Alpha values: 0 = off, 255 = full brightness
             RGB values: Standard 0-255 color channels
    """

def contrast(self, value):
    """
    Set global LED intensity/brightness multiplier.
    
    Parameters:
    - value: Global brightness level (0-255)
             Applied as multiplier to individual pixel alpha values
    """

def show(self):
    """
    Not supported operation (no-op).
    APA102 LEDs update immediately on display() calls.
    """

def hide(self):
    """
    Not supported operation (no-op).
    Use contrast(0) or display black image to turn off LEDs.
    """

Usage Examples

Basic LED Strip

from luma.led_matrix.device import apa102
from luma.core.render import canvas
from PIL import Image

# Create 30-pixel APA102 strip with default bitbang interface
device = apa102(cascaded=30)

# Create RGBA image for brightness control
img = Image.new('RGBA', (30, 1))
pixels = img.load()

# Set colors with individual brightness
pixels[0, 0] = (255, 0, 0, 255)    # Red at full brightness
pixels[1, 0] = (0, 255, 0, 128)    # Green at 50% brightness
pixels[2, 0] = (0, 0, 255, 64)     # Blue at 25% brightness

device.display(img)

Using SPI Interface

from luma.core.interface.serial import spi, noop
from luma.led_matrix.device import apa102
from luma.core.render import canvas

# Create SPI interface for faster communication
serial = spi(port=0, device=0, gpio=noop())
device = apa102(serial_interface=serial, cascaded=50)

# Draw with canvas (auto-converts to RGBA)
with canvas(device) as draw:
    # Canvas drawing automatically sets full alpha
    draw.point((0, 0), fill="red")
    draw.point((1, 0), fill="green")
    draw.point((2, 0), fill="blue")

LED Matrix with Brightness Control

from luma.led_matrix.device import apa102
from PIL import Image
import numpy as np

# Create 8x8 LED matrix
device = apa102(width=8, height=8)

# Create gradient brightness pattern
img = Image.new('RGBA', (8, 8))
pixels = img.load()

for x in range(8):
    for y in range(8):
        # Distance-based brightness
        distance = ((x - 3.5) ** 2 + (y - 3.5) ** 2) ** 0.5
        brightness = max(0, int(255 - distance * 30))
        pixels[x, y] = (255, 255, 255, brightness)  # White with varying brightness

device.display(img)

Animated Effects with Brightness

import time
import math
from luma.led_matrix.device import apa102
from PIL import Image

device = apa102(width=16, height=1)

# Breathing effect with individual pixel brightness
for step in range(100):
    img = Image.new('RGBA', (16, 1))
    pixels = img.load()
    
    for i in range(16):
        # Sine wave brightness pattern
        brightness = int(128 + 127 * math.sin(step * 0.2 + i * 0.5))
        hue = (i + step * 0.1) % 1.0
        
        # Convert HSV to RGB
        import colorsys
        rgb = colorsys.hsv_to_rgb(hue, 1.0, 1.0)
        color = tuple(int(c * 255) for c in rgb)
        
        pixels[i, 0] = (*color, brightness)
    
    device.display(img)
    time.sleep(0.05)

Global Brightness Control

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

device = apa102(cascaded=20)

# Set global brightness to 25%
device.contrast(64)

# Draw normally - global brightness will be applied
with canvas(device) as draw:
    for i in range(20):
        draw.point((i, 0), fill="white")

# Fade out gradually
for brightness in range(64, -1, -2):
    device.contrast(brightness)
    time.sleep(0.1)

Hardware Requirements

  • Platform: Raspberry Pi or compatible Linux SBC
  • Interface Options:
    • SPI: Hardware SPI for faster communication (recommended for many LEDs)
    • Bitbang: GPIO bit-banging (default, works with any GPIO pins)
  • Connections:
    • SPI Mode:
      • Data: SPI MOSI (GPIO 10)
      • Clock: SPI SCLK (GPIO 11)
    • Bitbang Mode:
      • Data: Any GPIO pin (configurable)
      • Clock: Any GPIO pin (configurable)
    • Power: 5V supply with adequate current capacity
    • Ground: Common ground connection

Performance Advantages

  • Higher Refresh Rates: Up to 20kHz vs ~800Hz for WS281x
  • Individual Brightness: Each pixel has independent brightness control
  • Clock Signal: Separate clock allows more reliable timing
  • SPI Compatible: Can use hardware SPI for maximum speed
  • No Timing Critical: Less sensitive to timing variations than WS281x

Error Handling

The device may raise the following exceptions:

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

Alpha Channel Usage

APA102 LEDs support 5-bit brightness control (32 levels) per pixel through the alpha channel:

  • Alpha 0: LED off
  • Alpha 1-7: Very dim (mapped to hardware brightness 1)
  • Alpha 8-15: Dim (mapped to hardware brightness 2)
  • ...continuing pattern...
  • Alpha 248-255: Full brightness (mapped to hardware brightness 31)

The library automatically handles the conversion from 8-bit alpha values to 5-bit hardware brightness levels.

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