RGBW and RGB NeoPixels in series connection

Daisy chain RGBW+RGB NeoPixels

Disclaimer: I am not an expert in electronics or programming. That's the way I did it, and that's not necessarily the correct way to do it. Some driver information in this article may be out of date.

For the bottom scanner array, I plan to use a RGBW NeoPixel stick. I had also ordered single RGB NeoPixel buttons to use for the Alpha-to-Delta lights and maybe replace some other LEDs. RGBW and RGB pixels have different shift register lengths. I was curious if it is possible to connect the different pixel types in series with a long shift register, similar to what I did with the TLC5947 and DotStar matrix boards.

NeoPixel driver installation

To use the CircuitPython NeoPixel Library on the RaspberryPi you have to install the adafruit_blinka library first. I already had Blinka installed when I tested the TLC5947 LED board, so I skipped this step. Last thing to do was running this in the command line:

sudo pip3 install adafruit-circuitpython-neopixel

More details about powering, usage and script examples are available in the NeoPixel Überguide.

RGBW and RGB NeoPixel in series

According to the documentation “On the Raspberry Pi, NeoPixels must be connected to GPIO10, GPIO12, GPIO18 or GPIO21 to work!”. In my setup GPIO 10 (SPI0 MOSI) is already used for the TFT display and GPIO 21 (SPI1 SCLK) is used for the TLC5947 and DotStar LEDs. I decided to use GPIO 12 for DIN, connected one GND line to the Raspi and +5V and the second GND line to the PowerBoost module. The button pixels are attached in series, always DOUT to DIN.

Note: It is recommended to use a logic level shifter like 74AHCT125 to boost Raspi's 3.3V GPIO signals to 5V. I didn't use it, but I should have (it worked without, but not reliably). Use a logic level shifter!

Wiring example
Daisy Chain RGBW and RGB NeoPixel LEDs
Wiring example
Daisy Chain RGBW and RGB NeoPixel LEDs

Adjustments in the existing driver

Adafruit's open source driver for the NeoPixel LEDs is available on GitHub. Parameters and functions are described in comments directly in the Python file.

This driver file is used for all types of NeoPixels. Usually you define the order of the pixel colors (RGB/GBR/RGBW/GBRW) at the beginning of your script during the NeoPixel initialization, like in this example.

# The order of the pixel colors - RGB or GRB.
# Some NeoPixels have red and green reversed!
# For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW.
ORDER = neopixel.RGBW

To be able to combine RGB and RGBW pixels I duplicated the driver file and modified them:

Modified RGB driver file

adafruit_neopixel_custom_rgb.py

  • Commented out digitalio and neopixel_write stuff
  • Changed the class name to NeoPixel_RGB()
  • Modified the __init__ and deinit function (commented out digitalio stuff)
  • Modified the _transmit function (return buffer instead of writing to the pin)

Note: I worked on this in Oct/Nov. 2020. The current NeoPixel driver on GitHub may have changed.

# The MIT License (MIT)
#
# Copyright (c) 2016 Damien P. George
# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
# Copyright (c) 2019 Carter Nelson
# Copyright (c) 2019 Roy Hooper
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

"""
`neopixel` - NeoPixel strip driver
====================================================

* Author(s): Damien P. George, Scott Shawcroft, Carter Nelson, Roy Hooper
"""

# pylint: disable=ungrouped-imports
import sys
# import digitalio
# from neopixel_write import neopixel_write

if sys.implementation.version[0] < 5:
    import adafruit_pypixelbuf as _pixelbuf
else:
    try:
        import _pixelbuf
    except ImportError:
        import adafruit_pypixelbuf as _pixelbuf

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"

# Pixel color order constants
RGB = "RGB"
"""Red Green Blue"""
GRB = "GRB"
"""Green Red Blue"""
RGBW = "RGBW"
"""Red Green Blue White"""
GRBW = "GRBW"
"""Green Red Blue White"""

#class NeoPixel(_pixelbuf.PixelBuf):
class NeoPixel_RGB(_pixelbuf.PixelBuf):

    """
    A sequence of neopixels.

    :param ~microcontroller.Pin pin: The pin to output neopixel data on.
    :param int n: The number of neopixels in the chain
    :param int bpp: Bytes per pixel. 3 for RGB and 4 for RGBW pixels.
    :param float brightness: Brightness of the pixels between 0.0 and 1.0 where 1.0 is full
      brightness
    :param bool auto_write: True if the neopixels should immediately change when set. If False,
      `show` must be called explicitly.
    :param str: Set the pixel color channel order. GRBW is set by default.

    Example for Circuit Playground Express:

    .. code-block:: python

        import neopixel
        from board import *

        RED = 0x100000 # (0x10, 0, 0) also works

        pixels = neopixel.NeoPixel(NEOPIXEL, 10)
        for i in range(len(pixels)):
            pixels[i] = RED

    Example for Circuit Playground Express setting every other pixel red using a slice:

    .. code-block:: python

        import neopixel
        from board import *
        import time

        RED = 0x100000 # (0x10, 0, 0) also works

        # Using ``with`` ensures pixels are cleared after we're done.
        with neopixel.NeoPixel(NEOPIXEL, 10) as pixels:
            pixels[::2] = [RED] * (len(pixels) // 2)
            time.sleep(2)

    .. py:method:: NeoPixel.show()

        Shows the new colors on the pixels themselves if they haven't already
        been autowritten.

        The colors may or may not be showing after this function returns because
        it may be done asynchronously.

    .. py:method:: NeoPixel.fill(color)

        Colors all pixels the given ***color***.

    .. py:attribute:: brightness

        Overall brightness of the pixel (0 to 1.0)

    """

    def __init__(
        self,
#        pin,
        n,
        *,
        bpp=3,
        brightness=1.0,
        auto_write=True,
        pixel_order=None
    ):
    
        if not pixel_order:
            pixel_order = GRB if bpp == 3 else GRBW
        else:
            if isinstance(pixel_order, tuple):
                order_list = [RGBW[order] for order in pixel_order]
                pixel_order = "".join(order_list)

        super().__init__(
            n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write
        )

#        self.pin = digitalio.DigitalInOut(pin)
#        self.pin.direction = digitalio.Direction.OUTPUT

    def deinit(self):
        """Blank out the NeoPixels and release the pin."""
        self.fill(0)
        self.show()
#        self.pin.deinit()

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, traceback):
        self.deinit()

    def __repr__(self):
        return "[" + ", ".join([str(x) for x in self]) + "]"

    @property
    def n(self):
        """
        The number of neopixels in the chain (read-only)
        """
        return len(self)

    def write(self):
        """.. deprecated: 1.0.0

             Use ``show`` instead. It matches Micro:Bit and Arduino APIs."""
        self.show()

    def _transmit(self, buffer):
        # Return result instead of writing it to the pin
        return buffer
#        neopixel_write(self.pin, buffer)

Modified RGBW driver file

adafruit_neopixel_custom_rgbw.py

  • Commented out digitalio and neopixel_write stuff
  • Changed the class name to NeoPixel_RGBW()
  • Modified the __init__ and deinit function (commented out digitalio stuff)
  • Modified the _transmit function (return buffer instead of writing to the pin)

Note: I worked on this in Oct/Nov. 2020. The current NeoPixel driver on GitHub may have changed.

# The MIT License (MIT)
#
# Copyright (c) 2016 Damien P. George
# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
# Copyright (c) 2019 Carter Nelson
# Copyright (c) 2019 Roy Hooper
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

"""
`neopixel` - NeoPixel strip driver
====================================================

* Author(s): Damien P. George, Scott Shawcroft, Carter Nelson, Roy Hooper
"""

# pylint: disable=ungrouped-imports
import sys
# import digitalio
# from neopixel_write import neopixel_write

if sys.implementation.version[0] < 5:
    import adafruit_pypixelbuf as _pixelbuf
else:
    try:
        import _pixelbuf
    except ImportError:
        import adafruit_pypixelbuf as _pixelbuf


__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"

# Pixel color order constants
RGB = "RGB"
"""Red Green Blue"""
GRB = "GRB"
"""Green Red Blue"""
RGBW = "RGBW"
"""Red Green Blue White"""
GRBW = "GRBW"
"""Green Red Blue White"""

# class NeoPixel(_pixelbuf.PixelBuf):
class NeoPixel_RGBW(_pixelbuf.PixelBuf):

    """
    A sequence of neopixels.

    :param ~microcontroller.Pin pin: The pin to output neopixel data on.
    :param int n: The number of neopixels in the chain
    :param int bpp: Bytes per pixel. 3 for RGB and 4 for RGBW pixels.
    :param float brightness: Brightness of the pixels between 0.0 and 1.0 where 1.0 is full
      brightness
    :param bool auto_write: True if the neopixels should immediately change when set. If False,
      `show` must be called explicitly.
    :param str: Set the pixel color channel order. GRBW is set by default.

    Example for Circuit Playground Express:

    .. code-block:: python

        import neopixel
        from board import *

        RED = 0x100000 # (0x10, 0, 0) also works

        pixels = neopixel.NeoPixel(NEOPIXEL, 10)
        for i in range(len(pixels)):
            pixels[i] = RED

    Example for Circuit Playground Express setting every other pixel red using a slice:

    .. code-block:: python

        import neopixel
        from board import *
        import time

        RED = 0x100000 # (0x10, 0, 0) also works

        # Using ``with`` ensures pixels are cleared after we're done.
        with neopixel.NeoPixel(NEOPIXEL, 10) as pixels:
            pixels[::2] = [RED] * (len(pixels) // 2)
            time.sleep(2)

    .. py:method:: NeoPixel.show()

        Shows the new colors on the pixels themselves if they haven't already
        been autowritten.

        The colors may or may not be showing after this function returns because
        it may be done asynchronously.

    .. py:method:: NeoPixel.fill(color)

        Colors all pixels the given ***color***.

    .. py:attribute:: brightness

        Overall brightness of the pixel (0 to 1.0)

    """

    def __init__(
        self,
#        pin,
        n,
        *,
        bpp=3,
        brightness=1.0,
        auto_write=True,
        pixel_order=None
    ):
    
        if not pixel_order:
            pixel_order = GRB if bpp == 3 else GRBW
        else:
            if isinstance(pixel_order, tuple):
                order_list = [RGBW[order] for order in pixel_order]
                pixel_order = "".join(order_list)

        super().__init__(
            n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write
        )

#        self.pin = digitalio.DigitalInOut(pin)
#        self.pin.direction = digitalio.Direction.OUTPUT

    def deinit(self):
        """Blank out the NeoPixels and release the pin."""
        self.fill(0)
        self.show()
#        self.pin.deinit()

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, traceback):
        self.deinit()

    def __repr__(self):
        return "[" + ", ".join([str(x) for x in self]) + "]"

    @property
    def n(self):
        """
        The number of neopixels in the chain (read-only)
        """
        return len(self)

    def write(self):
        """.. deprecated: 1.0.0

             Use ``show`` instead. It matches Micro:Bit and Arduino APIs."""
        self.show()

    def _transmit(self, buffer):
        # Return result instead of writing it to the pin
        return buffer
#        neopixel_write(self.pin, buffer)

New driver file to combine the RGBW and RGB shift registers

chain_write_neopixel.py

  • This file contains the previously disabled digitalio and neopixel_write code
  • The __init__ function declares the PIN variable for data (DIN)
  • The write function combines the RGBW and RGB shift registers and writes it out to the pin
import sys
import digitalio
from neopixel_write import neopixel_write

if sys.implementation.version[0] < 5:
    import adafruit_pypixelbuf as _pixelbuf
else:
    try:
        import _pixelbuf
    except ImportError:
        import adafruit_pypixelbuf as _pixelbuf

class chain_neopixel:

    def __init__(self, pin):
        self.pin = digitalio.DigitalInOut(pin)
        self.pin.direction = digitalio.Direction.OUTPUT

    def deinit(self):
        """Blank out the NeoPixels and release the pin."""
        self.pin.deinit()

    def write(self, shiftref_neopixel_rgbw, shiftref_neopixel_rgb):
        shiftreg_combined = shiftref_neopixel_rgbw + shiftref_neopixel_rgb
        neopixel_write(self.pin, shiftreg_combined)

Using the modified driver files

To use the modified drivers in your Python script, all the files should be placed in the same folder on the Pi (maybe there is a way to declare paths to the files, but I didn't care about that). In the “main” LED script (containing the LED color/power values and animation loops) you have to

  • Import the modified adafruit_­neopixel_­custom_­rgb.py driver
  • Import the modified adafruit_­neopixel_­custom_­rgbw.py driver
  • Import the new chain_­write_­neopixel.py driver and declare the used data pin
# Import and initialize RGBW NeoPixel
import adafruit_neopixel_custom_rgbw
# Number of NeoPixels:
num_pixels_rgbw = 8
# The order of the pixel colors: RGBW or GRBW
order_rgbw = adafruit_neopixel_custom_rgbw.GRBW
pixels_rgbw = adafruit_neopixel_custom_rgbw.NeoPixel_RGBW(num_pixels_rgbw, brightness=0.1, auto_write=True, pixel_order=order_rgbw)

# Import and initialize RGB NeoPixel
import adafruit_neopixel_custom_rgb
# Number of NeoPixels
num_pixels_rgb = 4
# The order of the pixel colors: RGB or GRB
order_rgb = adafruit_neopixel_custom_rgb.GRB
pixels_rgb = adafruit_neopixel_custom_rgb.NeoPixel_RGB(num_pixels_rgb, brightness=0.1, auto_write=True, pixel_order=order_rgb)

# Import and initialize Neopixel write function
import chain_write_neopixel
# GPIO for Data-In (Neopixel DIN)
pixel_pin = board.D12
pixelchain = chain_write_neopixel.chain_neopixel(pixel_pin)

Then you can write some functions to define the NeoPixel colors or animations.

To write the shift register out to the pin you have to call the pixelchain.write() function with pixels_rgbw.show() and pixels_rgb.show() as parameters. Simplified example:

# RGBW pixel No. 5 red:
pixels_rgbw[5] = (255,0,0,0)
# RGB pixel No. 2 green:
pixels_rgb[2] = (0,255,0)
# Apply changes: Write out data to pin
pixelchain.write(pixels_rgbw.show(), pixels_rgb.show())

Below is my script ledneo.py to test the setup. The 8 pixels on the stick blink from the center out with changing colors and the 4 button pixels just flash green one after the other. Here you can see that I am not a Python expert, there are probably much better ways to write the blinking functions than I did...

#!/usr/bin/python3
#!/usr/bin/env python3

# Import libraries
import board
import time # for timing control
import threading # for executing multiple functions parallel 

# Import and initialize RGBW Neopixel
import adafruit_neopixel_custom_rgbw
# Number of RGBW NeoPixel
num_pixels_rgbw = 8
# The order of the pixel colors: RGBW or GRBW
order_rgbw = adafruit_neopixel_custom_rgbw.GRBW
pixels_rgbw = adafruit_neopixel_custom_rgbw.NeoPixel_RGBW(num_pixels_rgbw, brightness=0.1, auto_write=True, pixel_order=order_rgbw)

# Import and initialize RGB Neopixel
import adafruit_neopixel_custom_rgb
# Number of RGB NeoPixel
num_pixels_rgb = 8
# The order of the pixel colors: RGB or GRB
order_rgb = adafruit_neopixel_custom_rgb.GRB
pixels_rgb = adafruit_neopixel_custom_rgb.NeoPixel_RGB(num_pixels_rgb, brightness=0.1, auto_write=True, pixel_order=order_rgb)

# Import and initialize Neopixel write function
import chain_write_neopixel
pixel_pin = board.D12 # GPIO for Data-In (Neopixel DIN)
pixelchain = chain_write_neopixel.chain_neopixel(pixel_pin)

# Helper function: Turn all LEDs off = all 0
def fn_led_neopixel_bar_off():
  pixels_rgbw.fill((0, 0, 0, 0))
  pixels_rgb.fill((0, 0, 0, 0))
  # Apply changes: Write out data to pin
  pixelchain.write(pixels_rgbw.show(), pixels_rgb.show())

# Scan pattern center-out
def fn_led_neopixel_bar_scan(arg):
  t = threading.currentThread()
  while getattr(t, "do_run", True):
    
    pixels_rgbw[0] = (0,0,0,0)
    pixels_rgbw[7] = (0,0,0,0)
    if (getattr(t, "color") == "red"):
      pixels_rgbw[3] = (255,0,0,0)
      pixels_rgbw[4] = (255,0,0,0)
    elif (getattr(t, "color") == "yellow"):
      pixels_rgbw[3] = (255,160,0,0)
      pixels_rgbw[4] = (255,160,0,0)
    elif (getattr(t, "color") == "blue"):
      pixels_rgbw[3] = (0,0,255,0)
      pixels_rgbw[4] = (0,0,255,0)
    elif (getattr(t, "color") == "white"):
      pixels_rgbw[3] = (0,0,0,130)
      pixels_rgbw[4] = (0,0,0,130)
    
    pixels_rgb[0] = (0,255,0)
    pixels_rgb[1] = (0,0,0)
    pixels_rgb[2] = (0,0,0)
    pixels_rgb[3] = (0,0,0)
    
    # Apply changes: Write out data to pin
    pixelchain.write(pixels_rgbw.show(), pixels_rgb.show())
    
    time.sleep(0.2)
    
    if (getattr(t, "do_run") == False):
      fn_led_neopixel_bar_off()
      break
    
    pixels_rgbw[3] = (0,0,0,0)
    pixels_rgbw[4] = (0,0,0,0)
    if (getattr(t, "color") == "red"):
      pixels_rgbw[2] = (255,0,0,0)
      pixels_rgbw[5] = (255,0,0,0)
    elif (getattr(t, "color") == "yellow"):
      pixels_rgbw[2] = (255,160,0,0)
      pixels_rgbw[5] = (255,160,0,0)
    elif (getattr(t, "color") == "blue"):
      pixels_rgbw[2] = (0,0,255,0)
      pixels_rgbw[5] = (0,0,255,0)
    elif (getattr(t, "color") == "white"):
      pixels_rgbw[2] = (0,0,0,130)
      pixels_rgbw[5] = (0,0,0,130)
      
    pixels_rgb[0] = (0,0,0)
    pixels_rgb[1] = (0,255,0)
    pixels_rgb[2] = (0,0,0)
    pixels_rgb[3] = (0,0,0)
    
    # Apply changes: Write out data to pin
    pixelchain.write(pixels_rgbw.show(), pixels_rgb.show())
    
    time.sleep(0.2)
    
    if (getattr(t, "do_run") == False):
      fn_led_neopixel_bar_off()
      break
    
    pixels_rgbw[2] = (0,0,0,0)
    pixels_rgbw[5] = (0,0,0,0)
    if (getattr(t, "color") == "red"):
      pixels_rgbw[1] = (255,0,0,0)
      pixels_rgbw[6] = (255,0,0,0)
    elif (getattr(t, "color") == "yellow"):
      pixels_rgbw[1] = (255,160,0,0)
      pixels_rgbw[6] = (255,160,0,0)
    elif (getattr(t, "color") == "blue"):
      pixels_rgbw[1] = (0,0,255,0)
      pixels_rgbw[6] = (0,0,255,0)
    elif (getattr(t, "color") == "white"):
      pixels_rgbw[1] = (0,0,0,130)
      pixels_rgbw[6] = (0,0,0,130)
      
    pixels_rgb[0] = (0,0,0)
    pixels_rgb[1] = (0,0,0)
    pixels_rgb[2] = (0,255,0)
    pixels_rgb[3] = (0,0,0)
    
    # Apply changes: Write out data to pin
    pixelchain.write(pixels_rgbw.show(), pixels_rgb.show())
    
    time.sleep(0.2)
    
    if (getattr(t, "do_run") == False):
      fn_led_neopixel_bar_off()
      break
    
    pixels_rgbw[1] = (0,0,0,0)
    pixels_rgbw[6] = (0,0,0,0)
    if (getattr(t, "color") == "red"):
      pixels_rgbw[0] = (255,0,0,0)
      pixels_rgbw[7] = (255,0,0,0)
    elif (getattr(t, "color") == "yellow"):
      pixels_rgbw[0] = (255,160,0,0)
      pixels_rgbw[7] = (255,160,0,0)
    elif (getattr(t, "color") == "blue"):
      pixels_rgbw[0] = (0,0,255,0)
      pixels_rgbw[7] = (0,0,255,0)
    elif (getattr(t, "color") == "white"):
      pixels_rgbw[0] = (0,0,0,130)
      pixels_rgbw[7] = (0,0,0,130)
    
    pixels_rgb[0] = (0,0,0)
    pixels_rgb[1] = (0,0,0)
    pixels_rgb[2] = (0,0,0)
    pixels_rgb[3] = (0,255,0)
    
    # Apply changes: Write out data to pin
    pixelchain.write(pixels_rgbw.show(), pixels_rgb.show())
    
    time.sleep(0.2)
    
    if (getattr(t, "do_run") == False):
      fn_led_neopixel_bar_off()
      break
 
t_led_neopixel = threading.Thread(target=fn_led_neopixel_bar_scan, args=("task",))
t_led_neopixel.do_run = True
t_led_neopixel.color = "blue"

try:
  t_led_neopixel.style = "default"
  t_led_neopixel.start()
  
  while True:
    time.sleep(3)
    t_led_neopixel.color = "red"
    time.sleep(3)
    t_led_neopixel.color = "yellow"
    time.sleep(3)
    t_led_neopixel.color = "white"
    time.sleep(3)
    t_led_neopixel.color = "blue"
    
except KeyboardInterrupt:
  if t_led_neopixel.is_alive():
    t_led_neopixel.do_run = False
    t_led_neopixel.join()
  fn_led_neopixel_bar_off()

Note: I removed some test code fragments and optimized the formatting for the blog. I'm not sure if the script still works (I haven't tested it again), but you should get the idea. In my initial test it worked:

I will probably not need this

Around the same time I was testing this series connection of RGBW and RGB NeoPixels, Adafruit had announced new RGBW NeoPixel Buttons. I had therefore put the NeoPixel tests on hold until the new NeoPixel Buttons were in stock. Thus I could do without a series connection of different NeoPixel types. But maybe this article is helpful for other projects with mixed NeoPixel types...