CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-luma-oled

Display drivers for SSD1306/SSD1309/SSD1322/SSD1325/SSD1327/SSD1331/SSD1351/SSD1362/SH1106/SH1107/WS0010 OLED matrix displays

Pending
Overview
Eval results
Files

interfaces.mddocs/

Communication Interfaces

Serial communication interfaces provided by luma.core for connecting to OLED displays via I2C, SPI, and parallel protocols. These interfaces handle low-level communication while providing a consistent API across different hardware connections.

Capabilities

I2C Interface

Two-wire serial communication interface commonly used for OLED displays, requiring only clock and data lines plus power.

class i2c:
    def __init__(self, port=1, address=0x3C, **kwargs):
        """
        Initialize I2C serial interface.

        Parameters:
        - port: I2C bus number (default: 1)
        - address: I2C device address (default: 0x3C)
        - **kwargs: Additional interface options
        """

    def command(self, cmd, *args):
        """Send command byte(s) to the device."""

    def data(self, values):
        """Send data byte(s) to the device."""

Common I2C Addresses:

  • 0x3C (60) - Most common for OLED displays
  • 0x3D (61) - Alternative address when multiple displays

Usage example:

from luma.core.interface.serial import i2c
from luma.oled.device import ssd1306

# Standard I2C configuration
serial = i2c(port=1, address=0x3C)
device = ssd1306(serial)

# For multiple displays or address conflicts
serial2 = i2c(port=1, address=0x3D)
device2 = ssd1306(serial2)

# Using different I2C bus
serial3 = i2c(port=0, address=0x3C)  # Bus 0 instead of 1

SPI Interface

Four-wire serial peripheral interface providing faster communication speeds, commonly used for color and high-resolution displays.

class spi:
    def __init__(self, port=0, device=0, bus_speed_hz=8000000, **kwargs):
        """
        Initialize SPI serial interface.

        Parameters:
        - port: SPI bus number (default: 0)
        - device: SPI device number (default: 0)
        - bus_speed_hz: SPI bus speed in Hz (default: 8MHz)
        - **kwargs: Additional SPI options (CS_ACTIVE_LOW, etc.)
        """

    def command(self, cmd, *args):
        """Send command byte(s) to the device."""

    def data(self, values):
        """Send data byte(s) to the device."""

Typical SPI Connections:

  • SCLK/SCK: Serial clock
  • MOSI/SDA: Master Out Slave In (data)
  • CS/SS: Chip Select (device selection)
  • DC/RS: Data/Command selection
  • RST: Reset (optional)

Usage example:

from luma.core.interface.serial import spi
from luma.oled.device import ssd1351, ssd1322

# Standard SPI configuration for color displays
serial = spi(port=0, device=0, bus_speed_hz=8000000)
device = ssd1351(serial)

# Higher speed for large greyscale displays
serial_fast = spi(port=0, device=0, bus_speed_hz=16000000)
device_large = ssd1322(serial_fast, width=256, height=64)

# Multiple SPI devices
serial1 = spi(port=0, device=0)  # CS0
serial2 = spi(port=0, device=1)  # CS1
device1 = ssd1351(serial1)
device2 = ssd1351(serial2)

Parallel Interface

Multi-wire parallel interface used primarily for character displays and some specialized OLED controllers.

class parallel:
    def __init__(self, RS=7, E=8, PINS=[25, 24, 23, 18], **kwargs):
        """
        Initialize parallel serial interface.

        Parameters:
        - RS: Register Select pin number (default: 7)
        - E: Enable pin number (default: 8)
        - PINS: Data pin numbers list (default: [25, 24, 23, 18])
        - **kwargs: Additional parallel options
        """

    def command(self, cmd, *args):
        """Send command byte(s) to the device."""

    def data(self, values):
        """Send data byte(s) to the device."""

Pin Functions:

  • RS (Register Select): Command (0) or Data (1) mode
  • E (Enable): Strobe signal for data transfer
  • D0-D7: 8-bit data bus (or D4-D7 for 4-bit mode)

Usage example:

from luma.core.interface.serial import parallel
from luma.oled.device import ws0010, winstar_weh

# 4-bit parallel mode (most common)
serial = parallel(
    RS=7,                    # Register Select
    E=8,                     # Enable  
    PINS=[25, 24, 23, 18]   # D4, D5, D6, D7
)
device = ws0010(serial)

# 8-bit parallel mode (if supported)
serial_8bit = parallel(
    RS=7, E=8,
    PINS=[25, 24, 23, 18, 17, 16, 15, 14]  # D0-D7
)

# Character display
device_char = winstar_weh(serial, width=16, height=2)

Interface Selection Guidelines

Choose I2C When:

  • Simple connections: Only 2 wires plus power needed
  • Multiple devices: Easy to chain multiple displays
  • Limited GPIO pins: Minimal pin usage
  • Monochrome displays: Adequate speed for simple graphics
# I2C - Best for simple monochrome displays
serial = i2c(port=1, address=0x3C)
device = ssd1306(serial)  # Simple setup

Choose SPI When:

  • High performance: Faster data transfer rates
  • Color displays: Large amounts of data to transfer
  • Large displays: High resolution or frequent updates
  • Dedicated connections: Each display needs separate CS line
# SPI - Best for color and large displays
serial = spi(port=0, device=0, bus_speed_hz=16000000)
device = ssd1351(serial)  # Color display with high speed

Choose Parallel When:

  • Character displays: Required for WS0010-based displays
  • Legacy compatibility: Working with older display modules
  • Specialized controllers: Some displays only support parallel
# Parallel - Required for character displays
serial = parallel(RS=7, E=8, PINS=[25, 24, 23, 18])
device = ws0010(serial)  # Character display

Hardware Configuration

Raspberry Pi GPIO

Common GPIO pin assignments for Raspberry Pi:

# I2C (uses dedicated I2C pins)
serial = i2c(port=1, address=0x3C)  # GPIO 2 (SDA), GPIO 3 (SCL)

# SPI (uses dedicated SPI pins)
serial = spi(port=0, device=0)      # GPIO 10 (MOSI), GPIO 11 (SCLK), GPIO 8 (CS0)

# Parallel (uses general GPIO pins)
serial = parallel(
    RS=7,                           # GPIO 7
    E=8,                            # GPIO 8
    PINS=[25, 24, 23, 18]          # GPIO 25, 24, 23, 18
)

Multiple Displays

# Multiple I2C displays (different addresses)
serial1 = i2c(port=1, address=0x3C)
serial2 = i2c(port=1, address=0x3D)
device1 = ssd1306(serial1)
device2 = ssd1306(serial2)

# Multiple SPI displays (different CS pins)
serial1 = spi(port=0, device=0)  # CS0
serial2 = spi(port=0, device=1)  # CS1
device1 = ssd1351(serial1)
device2 = ssd1351(serial2)

# Multiple parallel displays (different pin sets)
serial1 = parallel(RS=7, E=8, PINS=[25, 24, 23, 18])
serial2 = parallel(RS=12, E=13, PINS=[21, 20, 19, 16])
device1 = ws0010(serial1)
device2 = ws0010(serial2)

Troubleshooting

I2C Issues

# Check I2C device detection
# Run: i2cdetect -y 1

# Try different address
serial = i2c(port=1, address=0x3D)  # Instead of 0x3C

# Check I2C bus number
serial = i2c(port=0, address=0x3C)  # Try bus 0

SPI issues

# Reduce bus speed for troubleshooting
serial = spi(port=0, device=0, bus_speed_hz=1000000)  # 1MHz instead of 8MHz

# Check SPI device
serial = spi(port=0, device=1)  # Try CS1 instead of CS0

Parallel Issues

# Verify pin assignments
serial = parallel(RS=7, E=8, PINS=[25, 24, 23, 18])

# Add execution delay if needed
device = ws0010(serial, exec_time=1e-6 * 100)  # 100µs instead of 50µs

Performance Considerations

Bus Speed Optimization

# Conservative speeds (reliable)
i2c_slow = i2c(port=1, address=0x3C)           # ~100kHz (I2C standard)
spi_slow = spi(port=0, device=0, bus_speed_hz=1000000)  # 1MHz

# Optimized speeds (faster updates)
spi_fast = spi(port=0, device=0, bus_speed_hz=16000000) # 16MHz
spi_max = spi(port=0, device=0, bus_speed_hz=32000000)  # 32MHz (if supported)

Interface Comparison

InterfaceSpeedPinsMultiple DevicesBest For
I2C~400kHz2Easy (addresses)Monochrome
SPI1-32MHz4+Medium (CS pins)Color/Large
ParallelVariable6-10Hard (pin sets)Character

Install with Tessl CLI

npx tessl i tessl/pypi-luma-oled

docs

character-displays.md

color-displays.md

greyscale-displays.md

index.md

interfaces.md

monochrome-displays.md

tile.json