adafruit / Adafruit_CircuitPython_Pypixelbuf

Pure python implementation of _pixelbuf for smaller boards
Other
4 stars 11 forks source link

RGBW LEDs are unable to utilize the White pixel component when all RGB components equal 0 #22

Closed PitchBright closed 4 years ago

PitchBright commented 4 years ago

When attempting to control an individual neopixel's White component using:

pixels.fill((0,0,0,255))

the White pixel didn't light up. However, using:

pixels.fill((1,0,0,255))

did allow the White pixel to shine at full brightness.

cater on the Discord server #help-with-circuitpython channel attributed it to this line in the code:

https://github.com/adafruit/Adafruit_CircuitPython_Pypixelbuf/blob/1c3111135748ba20057923b8f299a9a99e34dc4e/adafruit_pypixelbuf.py#L256

s-light commented 4 years ago

speaking of RGBW neopixels here :-)

the conversation on discord: start: https://discord.com/channels/327254708534116352/537365702651150357/728350052224991242 end: https://discord.com/channels/327254708534116352/537365702651150357/728430692106764328

PitchBright commented 4 years ago

Further details: RPi 4 with NeoPixel RGBW LEDs w/ Integrated Driver Chip - Natural White - ~4500K

s-light commented 4 years ago

as a start for testing the various cases:

# minimal test for NeoPixels on Raspberry Pi
import time
import board
import neopixel

num_pixels = 2

pixels = neopixel.NeoPixel(
    board.D18,
    num_pixels,
    brightness=1.0,
    auto_write=False,
    pixel_order=neopixel.RGBW)

while True:
    print('red')
    pixels.fill((255, 0, 0, 0))
    pixels.show()
    time.sleep(2)

    print('green')
    pixels.fill((0, 255, 0, 0))
    pixels.show()
    time.sleep(2)

    print('blue')
    pixels.fill((0, 0, 255, 0))
    pixels.show()
    time.sleep(2)

    print('white')
    pixels.fill((0, 0, 0, 255))
    pixels.show()
    time.sleep(2)

    print('rgb full')
    pixels.fill((255, 255, 255, 0))
    pixels.show()
    time.sleep(2)

    print('rgbw 10')
    pixels.fill((10, 10, 10, 10))
    pixels.show()
    time.sleep(2)

    print('rgb 1, w 100')
    pixels.fill((1, 1, 1, 100))
    pixels.show()
    time.sleep(2)

    print('rgb 1, w 255')
    pixels.fill((1, 1, 1, 255))
    pixels.show()
    time.sleep(2)

    print('b 1, w 100')
    pixels.fill((0, 0, 1, 100))
    pixels.show()
    time.sleep(2)
ladyada commented 4 years ago

we wrapper https://github.com/jgarff/rpi_ws281x - please try that library, if it doesnt work there either, you'll want to move the issue there

caternuson commented 4 years ago

I think the basic neopixel driving is working OK. The issue is with the logic in pypixelbuf for the RGBW case, where it switches to using the W channel when R=G=B. And in that cases, it uses the R value for W, regardless of what was actually set for W. So if you set W=255 but then R=G=B=0, you end up with nothing.

PitchBright commented 4 years ago

Not specifically the R value, but any of the RGB values. In order to use the W component directly... the RGB values cannot all be 0. If any one of them is >0, then you can use the W value.

PitchBright commented 4 years ago

To add to that, conversely... if all the RGB values are >0 AND the same... then they override the W value.

These two uses produce the same resultant dim white light:


    print('rgb 1, w 100')
    pixels.fill((1, 1, 1, 100))
    pixels.show()
    time.sleep(2)

    print('rgb 1, w 255')
    pixels.fill((1, 1, 1, 255))
    pixels.show()
    time.sleep(2)```
PitchBright commented 4 years ago

Testing the script s-light provided yields these results: https://imgur.com/a/B1xNV5q

dunkmann00 commented 4 years ago

I also just realized this yesterday. The last commit I made introduced this bug, sorry! I'll create a pull request for this tonight.

dunkmann00 commented 4 years ago

@PitchBright The linked pull request should fix this, if you want to give it a go and test it out that would be great!