Source code for bibliopixel.drivers.PiWS281X

# Original code by msurguy:
# https://github.com/ManiacalLabs/BiblioPixel/issues/51#issuecomment-228662943

import os, sys
from . channel_order import ChannelOrder
from . driver_base import DriverBase
from .. util import log
from .. colors import gamma

WS_ERROR = """
PiWS281X Requires the rpi_ws281x C extension.

Install rpi_ws281x with the following shell commands:

    git clone https://github.com/jgarff/rpi_ws281x.git
    cd rpi_ws281x

    sudo apt-get install python-dev swig scons
    sudo scons

    cd python
    # If using default system python3
    sudo python3 setup.py build install
    # If using virtualenv, enter env then run
    python setup.py build install
"""

SUDO_ERROR = """
The PiWS281X driver needs to be run as sudo.  Rerun it with sudo, like this:
    sudo {command}
"""

try:
    from neopixel import Adafruit_NeoPixel, Color as NeoColor
except:
    NeoColor = None


PIN_CHANNEL = {
    12: 0,
    18: 0,
    40: 0,
    52: 0,
    13: 1,
    19: 1,
    41: 1,
    45: 1,
    53: 1,
    10: 0,  # Technically SPI
}

STRIP_TYPES = {
    3: 0x00100800,
    4: 0x18100800,
}


# Including follow as comment as URLs in docstrings don't play well with
# sphinx
# Discussion re: running as sudo
# https://groups.google.com/d/msg/maniacal-labs-users/6hV-2_-Xmqc/wmWJK709AQAJ
# https://github.com/jgarff/rpi_ws281x/blob/master/python/neopixel.py#L106


[docs]class PiWS281X(DriverBase): """ Driver for controlling WS281X LEDs via the rpi_ws281x C-extension. Only supported on the Raspberry Pi 2, 3, and Zero This driver needs to be run as sudo and requires the rpi_ws281x C extension. Install rpi_ws281x with the following shell commands: git clone https://github.com/jgarff/rpi_ws281x.git cd rpi_ws281x sudo apt-get install python-dev swig scons sudo scons cd python # If using default system python3 sudo python3 setup.py build install # If using virtualenv, enter env then run python setup.py build install Provides the same parameters of :py:class:`.driver_base.DriverBase` as well as those below: :param int gpio: GPIO pin to output to. Typically 18 or 13 :param int ledFreqHz: WS2812B base data frequency in Hz. Only change to 400000 if using very old WS218B LEDs :param int ledDma: DMA channel to use for generating signal (between 1 and 14) :param bool ledInvert: True to invert the signal (when using NPN transistor level shift) """ def __init__( self, num, gamma=gamma.NEOPIXEL, c_order="RGB", gpio=18, ledFreqHz=800000, ledDma=5, ledInvert=False, color_channels=3, brightness=255, **kwds): if not NeoColor: raise ValueError(WS_ERROR) super().__init__(num, c_order=c_order, gamma=gamma, **kwds) self.gamma = gamma if gpio not in PIN_CHANNEL.keys(): raise ValueError('{} is not a valid gpio option!') try: strip_type = STRIP_TYPES[color_channels] except: raise ValueError('In PiWS281X, color_channels can only be 3 or 4') self._strip = Adafruit_NeoPixel( num, gpio, ledFreqHz, ledDma, ledInvert, brightness, PIN_CHANNEL[gpio], strip_type) # Intialize the library (must be called once before other functions). try: self._strip.begin() except RuntimeError as e: if os.geteuid(): if os.path.basename(sys.argv[0]) in ('bp', 'bibliopixel'): command = ['bp'] + sys.argv[1:] else: command = ['python'] + sys.argv error = SUDO_ERROR.format(command=' '.join(command)) e.args = (error,) + e.args raise
[docs] def set_brightness(self, brightness): self._strip.setBrightness(brightness) return True
def _compute_packet(self): self._render() data = self._buf self._packet = [tuple(data[(p * 3):(p * 3) + 3]) for p in range(len(data) // 3)] def _send_packet(self): for i, p in enumerate(self._packet): self._strip.setPixelColor(i, NeoColor(*p)) self._strip.show()