circuitpython-serial-neopixel


Namecircuitpython-serial-neopixel JSON
Version 1.0.0 PyPI version JSON
download
home_pageNone
SummaryA CircuitPython library for managing segments of NeoPixel strips as independent addressable units (works on CircuitPython and Raspberry Pi)
upload_time2025-11-02 02:49:37
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseMIT
keywords circuitpython neopixel led rgb adafruit raspberry-pi ws2812
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # CircuitPython Serial NeoPixel

A CircuitPython library that provides a `SerialNeoPixel` class for managing segments of NeoPixel LED strips as independent addressable units.

## Overview

`SerialNeoPixel` acts as a wrapper around the standard Adafruit CircuitPython NeoPixel library, allowing you to treat a contiguous subset of pixels in a strip as a separate, independently addressable unit. This is particularly useful for projects where you want to logically divide a single physical strip into multiple sections without manually managing global pixel indices.

### Key Features

- **Segment-based addressing**: Create multiple segments on a single strip, each with its own 0-based indexing
- **Full sequence protocol support**: Supports indexing, slicing, negative indices, and `len()`
- **Pythonic interface**: Feels like working with a native NeoPixel object
- **No copying overhead**: Direct pass-through to parent strip (no pixel data duplication)
- **Brightness control**: Access parent strip's brightness property (affects entire strip)

## Installation

### From PyPI (when published)

```bash
pip install circuitpython-serial-neopixel
```

### Manual Installation

Copy `serial_neo.py` to your CircuitPython device's `lib` folder or your project directory.

## Requirements

### For CircuitPython (microcontrollers)
- CircuitPython 7.0 or higher
- `adafruit-circuitpython-neopixel` library

### For Raspberry Pi (standard Python)
- Python 3.7 or higher
- `adafruit-circuitpython-neopixel` library
- SPI enabled (via `raspi-config` or `/boot/config.txt`)
- NeoPixel DIN connected to GPIO10 (physical pin 19)

## Quick Start

### CircuitPython Example

```python
import board
import neopixel
from serial_neo import SerialNeoPixel

# Create a NeoPixel strip with 30 LEDs
strip = neopixel.NeoPixel(board.D18, 30, brightness=0.3, auto_write=False)

# Create three segments on the same strip
segment1 = SerialNeoPixel(strip, 0, 10)   # Pixels 0-9
segment2 = SerialNeoPixel(strip, 10, 10)  # Pixels 10-19
segment3 = SerialNeoPixel(strip, 20, 10)  # Pixels 20-29

# Each segment has independent 0-based indexing
segment1[0] = (255, 0, 0)    # Red - affects strip pixel 0
segment2[0] = (0, 255, 0)    # Green - affects strip pixel 10
segment3[0] = (0, 0, 255)    # Blue - affects strip pixel 20

# Update the physical strip
segment1.show()  # Any segment can call show() (affects entire strip)
```

### Raspberry Pi Example (Standard Python)

```python
import board
import neopixel
from serial_neo import SerialNeoPixel

# Create a NeoPixel strip with 30 LEDs on GPIO10 (physical pin 19)
# Note: Requires SPI enabled and sudo-less access configured
strip = neopixel.NeoPixel(board.D10, 30, brightness=0.3, auto_write=False)

# Create segments exactly the same way as CircuitPython
segment1 = SerialNeoPixel(strip, 0, 10)
segment2 = SerialNeoPixel(strip, 10, 10)
segment3 = SerialNeoPixel(strip, 20, 10)

# Same API works on both platforms
segment1[0] = (255, 0, 0)
segment2[0] = (0, 255, 0)
segment3[0] = (0, 0, 255)
segment1.show()
```

## Usage Examples

### Basic Indexing

```python
# Set individual pixels
segment[0] = (255, 0, 0)      # First pixel
segment[5] = (0, 255, 0)      # Sixth pixel
segment[-1] = (0, 0, 255)     # Last pixel (negative indexing)

# Get pixel colors
color = segment[0]            # Returns (R, G, B) or (R, G, B, W) tuple
last_color = segment[-1]      # Get last pixel
```

### Slice Operations

```python
# Set multiple pixels at once
segment[0:3] = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # First three pixels

# Set a range to the same color
segment[5:10] = [(128, 128, 128)] * 5  # Pixels 5-9 to gray

# Use slice with step
segment[::2] = [(255, 0, 0)] * 5  # Every other pixel to red

# Get multiple pixels
colors = segment[0:5]  # Returns list of color tuples
```

### Fill Operations

```python
# Fill entire segment with one color
segment.fill((255, 0, 0))  # Fill with red

# Clear a segment
segment.fill((0, 0, 0))  # Turn off all pixels
```

### Brightness Control

**Important**: The `brightness` property affects the **entire parent strip**, not just the individual segment.

```python
# Get current brightness
current = segment.brightness  # Returns float 0.0-1.0

# Set brightness (affects ALL segments on the same strip)
segment.brightness = 0.5  # 50% brightness for entire strip

# This also affects all other segments sharing the same parent strip
segment1.brightness = 0.3  # segment2 and segment3 are also affected
```

### Working with Multiple Segments

```python
import board
import neopixel
from serial_neo import SerialNeoPixel

# 60-pixel strip divided into 6 segments of 10 pixels each
strip = neopixel.NeoPixel(board.D18, 60, auto_write=False)
segments = [SerialNeoPixel(strip, i*10, 10) for i in range(6)]

# Animate each segment independently
for i, seg in enumerate(segments):
    seg.fill(colors[i])

strip.show()
```

### Advanced: Overlapping Segments

You can create overlapping segments if needed (though use carefully):

```python
full_strip = SerialNeoPixel(strip, 0, 30)   # All 30 pixels
left_half = SerialNeoPixel(strip, 0, 15)    # First 15 pixels
right_half = SerialNeoPixel(strip, 15, 15)  # Last 15 pixels
center = SerialNeoPixel(strip, 10, 10)      # Middle 10 pixels (overlaps both halves)
```

## API Reference

### `SerialNeoPixel(strip, pixel_start, pixel_count)`

Create a new segment wrapper.

**Parameters:**
- `strip`: Parent NeoPixel strip object
- `pixel_start`: Starting index in parent strip (0-based)
- `pixel_count`: Number of pixels in this segment

### Methods

#### `fill(color)`
Fill all pixels in the segment with the specified color.

**Parameters:**
- `color`: RGB tuple `(r, g, b)` or RGBW tuple `(r, g, b, w)` with values 0-255

#### `show()`
Update the physical LED strip to display current pixel colors. Affects the entire parent strip.

### Properties

#### `brightness`
Get or set the brightness of the parent strip (0.0 to 1.0).

**Warning**: This affects the **entire parent strip**, not just this segment. All segments sharing the same parent will be affected.

### Sequence Protocol

The class implements Python's sequence protocol:

- `len(segment)`: Returns number of pixels in segment
- `segment[i]`: Get/set pixel at index `i` (supports negative indices)
- `segment[start:stop:step]`: Get/set slice of pixels
- `repr(segment)`: String representation showing start position and count

## Platform Compatibility

This library works on both:

1. **CircuitPython microcontrollers**: Circuit Playground Express, Raspberry Pi Pico, Metro M4, etc.
2. **Raspberry Pi with standard Python**: Pi 3, Pi 4, Pi 5, Pi Zero W, etc.

The same code works on both platforms with only minor hardware pin differences (e.g., `board.D18` vs `board.D10`).

### Raspberry Pi Setup

To use NeoPixels on Raspberry Pi, you need to:

1. **Enable SPI** via `raspi-config`:
   ```bash
   sudo raspi-config
   # Navigate to: Interfacing Options -> SPI -> Enable
   ```

2. **Install the library**:
   ```bash
   pip3 install circuitpython-serial-neopixel
   ```

3. **Connect your NeoPixel strip**:
   - DIN (Data In) → GPIO10 (physical pin 19)
   - 5V → 5V power
   - GND → Ground

4. **Configure sudo-less access** (optional, for running without sudo):
   See [Adafruit's documentation](https://docs.circuitpython.org/projects/neopixel/en/latest/) for detailed setup.

## Limitations and Caveats

1. **Brightness is strip-wide**: The `brightness` property affects the entire parent strip, not individual segments. If multiple segments share a parent strip, changing brightness on one affects all.

2. **No bounds checking between segments**: You can create overlapping segments. The library doesn't prevent this, as it might be intentional for some use cases.

3. **`show()` updates entire strip**: Calling `show()` on any segment updates the entire physical strip, not just that segment's pixels.

4. **Requires parent strip compatibility**: The parent strip object must support the standard NeoPixel interface (`__getitem__`, `__setitem__`, `show()`, `brightness`).

5. **Auto-write behavior inherited**: If the parent strip has `auto_write=True`, changes may appear immediately. For better performance with segments, use `auto_write=False` on the parent strip and call `show()` manually.

## Performance Tips

1. **Use `auto_write=False`**: Create the parent strip with `auto_write=False` and call `show()` manually after batch updates:

```python
strip = neopixel.NeoPixel(board.D18, 30, auto_write=False)
segment = SerialNeoPixel(strip, 0, 10)

# Make multiple changes
segment[0] = (255, 0, 0)
segment[1] = (0, 255, 0)
segment[2] = (0, 0, 255)

# Update once
segment.show()
```

2. **Use `fill()` for uniform colors**: It's more efficient than setting pixels individually.

3. **Batch slice operations**: Use slice assignment instead of loops when possible:

```python
# Good
segment[0:5] = [(255, 0, 0)] * 5

# Less efficient
for i in range(5):
    segment[i] = (255, 0, 0)
```

## Examples

See the examples directory for more detailed usage examples (coming soon).

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

MIT License - see LICENSE file for details.

## Credits

Built on top of the [Adafruit CircuitPython NeoPixel](https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel) library.

## Support

For bugs and feature requests, please open an issue on GitHub.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "circuitpython-serial-neopixel",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "circuitpython, neopixel, led, rgb, adafruit, raspberry-pi, ws2812",
    "author": null,
    "author_email": "Jonathan Senkerik <jsenkerik@proton.me>",
    "download_url": "https://files.pythonhosted.org/packages/8a/a3/0a0c50f7d1c65a2b255c2963773a897c2ad393b73f099b2e2fd473c7777e/circuitpython_serial_neopixel-1.0.0.tar.gz",
    "platform": null,
    "description": "# CircuitPython Serial NeoPixel\n\nA CircuitPython library that provides a `SerialNeoPixel` class for managing segments of NeoPixel LED strips as independent addressable units.\n\n## Overview\n\n`SerialNeoPixel` acts as a wrapper around the standard Adafruit CircuitPython NeoPixel library, allowing you to treat a contiguous subset of pixels in a strip as a separate, independently addressable unit. This is particularly useful for projects where you want to logically divide a single physical strip into multiple sections without manually managing global pixel indices.\n\n### Key Features\n\n- **Segment-based addressing**: Create multiple segments on a single strip, each with its own 0-based indexing\n- **Full sequence protocol support**: Supports indexing, slicing, negative indices, and `len()`\n- **Pythonic interface**: Feels like working with a native NeoPixel object\n- **No copying overhead**: Direct pass-through to parent strip (no pixel data duplication)\n- **Brightness control**: Access parent strip's brightness property (affects entire strip)\n\n## Installation\n\n### From PyPI (when published)\n\n```bash\npip install circuitpython-serial-neopixel\n```\n\n### Manual Installation\n\nCopy `serial_neo.py` to your CircuitPython device's `lib` folder or your project directory.\n\n## Requirements\n\n### For CircuitPython (microcontrollers)\n- CircuitPython 7.0 or higher\n- `adafruit-circuitpython-neopixel` library\n\n### For Raspberry Pi (standard Python)\n- Python 3.7 or higher\n- `adafruit-circuitpython-neopixel` library\n- SPI enabled (via `raspi-config` or `/boot/config.txt`)\n- NeoPixel DIN connected to GPIO10 (physical pin 19)\n\n## Quick Start\n\n### CircuitPython Example\n\n```python\nimport board\nimport neopixel\nfrom serial_neo import SerialNeoPixel\n\n# Create a NeoPixel strip with 30 LEDs\nstrip = neopixel.NeoPixel(board.D18, 30, brightness=0.3, auto_write=False)\n\n# Create three segments on the same strip\nsegment1 = SerialNeoPixel(strip, 0, 10)   # Pixels 0-9\nsegment2 = SerialNeoPixel(strip, 10, 10)  # Pixels 10-19\nsegment3 = SerialNeoPixel(strip, 20, 10)  # Pixels 20-29\n\n# Each segment has independent 0-based indexing\nsegment1[0] = (255, 0, 0)    # Red - affects strip pixel 0\nsegment2[0] = (0, 255, 0)    # Green - affects strip pixel 10\nsegment3[0] = (0, 0, 255)    # Blue - affects strip pixel 20\n\n# Update the physical strip\nsegment1.show()  # Any segment can call show() (affects entire strip)\n```\n\n### Raspberry Pi Example (Standard Python)\n\n```python\nimport board\nimport neopixel\nfrom serial_neo import SerialNeoPixel\n\n# Create a NeoPixel strip with 30 LEDs on GPIO10 (physical pin 19)\n# Note: Requires SPI enabled and sudo-less access configured\nstrip = neopixel.NeoPixel(board.D10, 30, brightness=0.3, auto_write=False)\n\n# Create segments exactly the same way as CircuitPython\nsegment1 = SerialNeoPixel(strip, 0, 10)\nsegment2 = SerialNeoPixel(strip, 10, 10)\nsegment3 = SerialNeoPixel(strip, 20, 10)\n\n# Same API works on both platforms\nsegment1[0] = (255, 0, 0)\nsegment2[0] = (0, 255, 0)\nsegment3[0] = (0, 0, 255)\nsegment1.show()\n```\n\n## Usage Examples\n\n### Basic Indexing\n\n```python\n# Set individual pixels\nsegment[0] = (255, 0, 0)      # First pixel\nsegment[5] = (0, 255, 0)      # Sixth pixel\nsegment[-1] = (0, 0, 255)     # Last pixel (negative indexing)\n\n# Get pixel colors\ncolor = segment[0]            # Returns (R, G, B) or (R, G, B, W) tuple\nlast_color = segment[-1]      # Get last pixel\n```\n\n### Slice Operations\n\n```python\n# Set multiple pixels at once\nsegment[0:3] = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # First three pixels\n\n# Set a range to the same color\nsegment[5:10] = [(128, 128, 128)] * 5  # Pixels 5-9 to gray\n\n# Use slice with step\nsegment[::2] = [(255, 0, 0)] * 5  # Every other pixel to red\n\n# Get multiple pixels\ncolors = segment[0:5]  # Returns list of color tuples\n```\n\n### Fill Operations\n\n```python\n# Fill entire segment with one color\nsegment.fill((255, 0, 0))  # Fill with red\n\n# Clear a segment\nsegment.fill((0, 0, 0))  # Turn off all pixels\n```\n\n### Brightness Control\n\n**Important**: The `brightness` property affects the **entire parent strip**, not just the individual segment.\n\n```python\n# Get current brightness\ncurrent = segment.brightness  # Returns float 0.0-1.0\n\n# Set brightness (affects ALL segments on the same strip)\nsegment.brightness = 0.5  # 50% brightness for entire strip\n\n# This also affects all other segments sharing the same parent strip\nsegment1.brightness = 0.3  # segment2 and segment3 are also affected\n```\n\n### Working with Multiple Segments\n\n```python\nimport board\nimport neopixel\nfrom serial_neo import SerialNeoPixel\n\n# 60-pixel strip divided into 6 segments of 10 pixels each\nstrip = neopixel.NeoPixel(board.D18, 60, auto_write=False)\nsegments = [SerialNeoPixel(strip, i*10, 10) for i in range(6)]\n\n# Animate each segment independently\nfor i, seg in enumerate(segments):\n    seg.fill(colors[i])\n\nstrip.show()\n```\n\n### Advanced: Overlapping Segments\n\nYou can create overlapping segments if needed (though use carefully):\n\n```python\nfull_strip = SerialNeoPixel(strip, 0, 30)   # All 30 pixels\nleft_half = SerialNeoPixel(strip, 0, 15)    # First 15 pixels\nright_half = SerialNeoPixel(strip, 15, 15)  # Last 15 pixels\ncenter = SerialNeoPixel(strip, 10, 10)      # Middle 10 pixels (overlaps both halves)\n```\n\n## API Reference\n\n### `SerialNeoPixel(strip, pixel_start, pixel_count)`\n\nCreate a new segment wrapper.\n\n**Parameters:**\n- `strip`: Parent NeoPixel strip object\n- `pixel_start`: Starting index in parent strip (0-based)\n- `pixel_count`: Number of pixels in this segment\n\n### Methods\n\n#### `fill(color)`\nFill all pixels in the segment with the specified color.\n\n**Parameters:**\n- `color`: RGB tuple `(r, g, b)` or RGBW tuple `(r, g, b, w)` with values 0-255\n\n#### `show()`\nUpdate the physical LED strip to display current pixel colors. Affects the entire parent strip.\n\n### Properties\n\n#### `brightness`\nGet or set the brightness of the parent strip (0.0 to 1.0).\n\n**Warning**: This affects the **entire parent strip**, not just this segment. All segments sharing the same parent will be affected.\n\n### Sequence Protocol\n\nThe class implements Python's sequence protocol:\n\n- `len(segment)`: Returns number of pixels in segment\n- `segment[i]`: Get/set pixel at index `i` (supports negative indices)\n- `segment[start:stop:step]`: Get/set slice of pixels\n- `repr(segment)`: String representation showing start position and count\n\n## Platform Compatibility\n\nThis library works on both:\n\n1. **CircuitPython microcontrollers**: Circuit Playground Express, Raspberry Pi Pico, Metro M4, etc.\n2. **Raspberry Pi with standard Python**: Pi 3, Pi 4, Pi 5, Pi Zero W, etc.\n\nThe same code works on both platforms with only minor hardware pin differences (e.g., `board.D18` vs `board.D10`).\n\n### Raspberry Pi Setup\n\nTo use NeoPixels on Raspberry Pi, you need to:\n\n1. **Enable SPI** via `raspi-config`:\n   ```bash\n   sudo raspi-config\n   # Navigate to: Interfacing Options -> SPI -> Enable\n   ```\n\n2. **Install the library**:\n   ```bash\n   pip3 install circuitpython-serial-neopixel\n   ```\n\n3. **Connect your NeoPixel strip**:\n   - DIN (Data In) \u2192 GPIO10 (physical pin 19)\n   - 5V \u2192 5V power\n   - GND \u2192 Ground\n\n4. **Configure sudo-less access** (optional, for running without sudo):\n   See [Adafruit's documentation](https://docs.circuitpython.org/projects/neopixel/en/latest/) for detailed setup.\n\n## Limitations and Caveats\n\n1. **Brightness is strip-wide**: The `brightness` property affects the entire parent strip, not individual segments. If multiple segments share a parent strip, changing brightness on one affects all.\n\n2. **No bounds checking between segments**: You can create overlapping segments. The library doesn't prevent this, as it might be intentional for some use cases.\n\n3. **`show()` updates entire strip**: Calling `show()` on any segment updates the entire physical strip, not just that segment's pixels.\n\n4. **Requires parent strip compatibility**: The parent strip object must support the standard NeoPixel interface (`__getitem__`, `__setitem__`, `show()`, `brightness`).\n\n5. **Auto-write behavior inherited**: If the parent strip has `auto_write=True`, changes may appear immediately. For better performance with segments, use `auto_write=False` on the parent strip and call `show()` manually.\n\n## Performance Tips\n\n1. **Use `auto_write=False`**: Create the parent strip with `auto_write=False` and call `show()` manually after batch updates:\n\n```python\nstrip = neopixel.NeoPixel(board.D18, 30, auto_write=False)\nsegment = SerialNeoPixel(strip, 0, 10)\n\n# Make multiple changes\nsegment[0] = (255, 0, 0)\nsegment[1] = (0, 255, 0)\nsegment[2] = (0, 0, 255)\n\n# Update once\nsegment.show()\n```\n\n2. **Use `fill()` for uniform colors**: It's more efficient than setting pixels individually.\n\n3. **Batch slice operations**: Use slice assignment instead of loops when possible:\n\n```python\n# Good\nsegment[0:5] = [(255, 0, 0)] * 5\n\n# Less efficient\nfor i in range(5):\n    segment[i] = (255, 0, 0)\n```\n\n## Examples\n\nSee the examples directory for more detailed usage examples (coming soon).\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Credits\n\nBuilt on top of the [Adafruit CircuitPython NeoPixel](https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel) library.\n\n## Support\n\nFor bugs and feature requests, please open an issue on GitHub.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A CircuitPython library for managing segments of NeoPixel strips as independent addressable units (works on CircuitPython and Raspberry Pi)",
    "version": "1.0.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/josenk/serial-neo/issues",
        "Homepage": "https://github.com/josenk/serial-neo"
    },
    "split_keywords": [
        "circuitpython",
        " neopixel",
        " led",
        " rgb",
        " adafruit",
        " raspberry-pi",
        " ws2812"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "fbafb11c9442c32f0555eade24e211d8c7f0eeb7456289495c1bdf92634e1b6d",
                "md5": "467c65adbeaf3545e54ef225518b249c",
                "sha256": "5925ccd22021e771c979bc81f8f3610295e47429dd2688f37293b1b3e35e6644"
            },
            "downloads": -1,
            "filename": "circuitpython_serial_neopixel-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "467c65adbeaf3545e54ef225518b249c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 7862,
            "upload_time": "2025-11-02T02:49:35",
            "upload_time_iso_8601": "2025-11-02T02:49:35.904204Z",
            "url": "https://files.pythonhosted.org/packages/fb/af/b11c9442c32f0555eade24e211d8c7f0eeb7456289495c1bdf92634e1b6d/circuitpython_serial_neopixel-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8aa30a0c50f7d1c65a2b255c2963773a897c2ad393b73f099b2e2fd473c7777e",
                "md5": "b5d990513d1c9fc9f5db2ea8d4c32b06",
                "sha256": "a3ca7190b1ebce5aaf82575904c17d280eae2c36b7ef8709f2b7d5416ccf0447"
            },
            "downloads": -1,
            "filename": "circuitpython_serial_neopixel-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "b5d990513d1c9fc9f5db2ea8d4c32b06",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 7312,
            "upload_time": "2025-11-02T02:49:37",
            "upload_time_iso_8601": "2025-11-02T02:49:37.518592Z",
            "url": "https://files.pythonhosted.org/packages/8a/a3/0a0c50f7d1c65a2b255c2963773a897c2ad393b73f099b2e2fd473c7777e/circuitpython_serial_neopixel-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-11-02 02:49:37",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "josenk",
    "github_project": "serial-neo",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "circuitpython-serial-neopixel"
}
        
Elapsed time: 2.39846s