Skip to content

Support Global Brightness on a per-pixel basis #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mcscope opened this issue May 14, 2018 · 23 comments
Closed

Support Global Brightness on a per-pixel basis #16

mcscope opened this issue May 14, 2018 · 23 comments

Comments

@mcscope
Copy link
Contributor

mcscope commented May 14, 2018

APA102 allows each pixel to have a 5 bit global brightness value in addition to the 8 bit RGB values for each pixel. This library doesn't allow that to be set - see this comment

        # Each pixel starts with 0xFF, then red/green/blue. Although the data
        # sheet suggests using a global brightness in the first byte, we don't
        # do that because it causes further issues with persistence of vision
        # projects.

I've used the global brightness a lot on other projects, and it's really a nice feature. I think we should allow people to use it and just note in the documentation that if you use it for persistence of vision applications you may get flickering. By preventing people from using the brightness bit, we're stopped them from accessing a decent range of what these leds can do.

(The brightness works by PWMing the entire output of the LED, and it's at a much slower pulse than the leds themselves do, so it can be flickery for persistence of vision)
I'll maintain the default behavior of max brightness if brightness is unspecified so as to not modify existing projects

@ladyada
Copy link
Member

ladyada commented May 14, 2018

@PaintYourDragon (who wrote the originial library for arduino) has Thoughts about the global brightness, we purposefully never used it, because its not that great :/

@RedAnon
Copy link

RedAnon commented May 14, 2018

@ladyada But is the reason behind not using the built in brightness simply the fact that when you do use it the frequency drops?
If so shouldn't people be able to choose depending on what kind of a project they want to do?

@ladyada
Copy link
Member

ladyada commented May 14, 2018

yah, people didnt like the frequency submodulation - so we have a floating point brightness property, and that seems to work well for people, having two ways to adjust brightness could be confusing

@RedAnon
Copy link

RedAnon commented May 14, 2018

@ladyada
What if we made two variables? One would be let's say "brightness_internal" and the other "brightness_external"? With the internal one having priority over the external one maybe? And with proper documentation. Would such a solution get merged?

@mcscope
Copy link
Contributor Author

mcscope commented May 14, 2018

The way this library is currently written - (always setting maximum global brightness, relying on R,G,B to control pixel brightness) limits the minimum brightness of the LEDs to a miniumum that is way above what they're capable of.
You really want dim leds for low-light applications. I use dotstars for lighting my room, and I dim them down to their minimum brightness at night. I wouldn't be able to do that with this library.

Also, the brightness value as currently implemented is per-strip, not per-pixel, which bugs me as well.

@ladyada
Copy link
Member

ladyada commented May 14, 2018

i would hesitate to merge - it breaks the cross-compatibility we were aiming for with neopixel.py

@tannewt
Copy link
Member

tannewt commented May 14, 2018

@ladyada Has anyone tested the brightness byte on the new dimmer DotStars?

@ladyada
Copy link
Member

ladyada commented May 14, 2018

nope, we use the same code where we send 0xFF

@RedAnon
Copy link

RedAnon commented May 14, 2018

@mcscope To be honest I'm extremely interested in your use case as it's very close to what we need as well. Is your code public? Could we test it? And perhaps contribute to it?
I mean I understand @ladyada concerns and while I would like to push as much code to upstream as possible maybe a separate library is a better way to go? Maybe even as a part of the Adafruit_CircuitPython_ codebase?

(And I'm sorry if I sound dumb or appear to not understand how this whole FOSS contributing/merging/planning stuff works but I've never done it before so please be patient with me. 😊)

@mcscope
Copy link
Contributor Author

mcscope commented May 14, 2018

@RedAnon here's my repository, I'm running it on a raspberry pi instead of using circuitpython. It probably wouldn't be hard to port to circuitpython.

https://github.com/mcscope/liteup/blame/master/liteup/APA102/apa102.py
It's a fork of the tinue apa102_pi project - https://github.com/tinue/APA102_Pi/blob/master/apa102.py

@mcscope
Copy link
Contributor Author

mcscope commented May 14, 2018

maybe one of these could become an optional circuitpython advanced_dotstar library that lets you use the global illumination bit and do brightness per-pixel instead of stripwide. If it was a separate library we wouldn't be pinned to matching the NeoPixel API

@RedAnon
Copy link

RedAnon commented May 14, 2018

@mcscope I completely agree. A separate library like for example Adafruit_CircuitPython_Advanced_DotStar would be awesome. No idea how this works Adafruit-wise and if they would be interested in having it under their wing. Maybe @ladyada can shed some light into it?
Nevertheless I will forward the code to our developer and ask him to port the code from @mcscope to CircuitPython. 😊

@ladyada
Copy link
Member

ladyada commented May 14, 2018

hiya if you make a new library we can fork it and/or point people to it! :)

@RedAnon
Copy link

RedAnon commented May 14, 2018

Great! We will try to port the RPi library from @mcscope to CircuitPython in the upcoming week(s) and when it's done I'll ask @ladyada to fork it and that will essentially become the new upstream? Am I correct?

@ladyada
Copy link
Member

ladyada commented May 14, 2018

sure!

@tannewt
Copy link
Member

tannewt commented May 14, 2018

Fixed by #19

@tannewt tannewt closed this as completed May 14, 2018
@mcscope
Copy link
Contributor Author

mcscope commented May 14, 2018

@RedAnon Pull the latest and you should be able to use the brightness bits

@RedAnon
Copy link

RedAnon commented May 15, 2018

I can confirm it works flawlessly! Thank you so much @mcscope, you rock! 🙌

@RedAnon
Copy link

RedAnon commented May 15, 2018

Just a quick question tho @mcscope
Does the use of the 5-Bit brightness value also affect the colours A LOT on your end? When I set it the oldschool way by simply using just the brightness value the colours stay the same. But when I don't use that and use only the 5-Bit value the rendering is all over the place with different mixing as I go down. Almost as if the brightness set by this value were different for each colour inside the LED...

@mcscope
Copy link
Contributor Author

mcscope commented May 17, 2018

@RedAnon No, it just brightens and dims for me. Can you post the code that's doing that?
My understanding is that this value should cause the entire LED to pulse-width-modulate at a relatively slow speed - but it should be the same for all 3 leds on each dotstar. I wonder if it could be a software issue.

@RedAnon
Copy link

RedAnon commented May 17, 2018

It's a very simple code:

import time
import board
import adafruit_dotstar

RGB = (0, 1, 2)
RBG = (0, 2, 1)
GRB = (1, 0, 2)
GBR = (1, 2, 0)
BRG = (2, 0, 1)
BGR = (2, 1, 0)

clock_pin		= board.A1
data_pin		= board.A2
number_of_leds		= 64
level_of_brightness	= 0.50
force_update		= True

pixels = adafruit_dotstar.DotStar(clock_pin, data_pin, number_of_leds, brightness=level_of_brightness, auto_write=force_update, pixel_order=BGR)

pixels.fill((255, 128, 64))

When using just the old brightness like in the code above the colours won't shift much when I set the brightness to 0.75 or 0.5 or 0.25. But

import time
import board
import adafruit_dotstar

RGB = (0, 1, 2)
RBG = (0, 2, 1)
GRB = (1, 0, 2)
GBR = (1, 2, 0)
BRG = (2, 0, 1)
BGR = (2, 1, 0)

clock_pin		= board.A1
data_pin		= board.A2
number_of_leds		= 64
level_of_brightness	= 1.00
force_update		= True

pixels = adafruit_dotstar.DotStar(clock_pin, data_pin, number_of_leds, brightness=level_of_brightness, auto_write=force_update, pixel_order=BGR)

pixels.fill((255, 128, 64, 0.5))

when I use the per-pixel brightness like in the code above there is a quite noticeable colour difference between 0.75 or 0.5 or 0.25.

I use the Adafruit 8x8 grid for testing, controlling it from Gemma M0.

@brianfaires
Copy link

Seconding the color balance issue when using the 5-bits brightness. My implementation stores an array of 8-bit brightness values alongside my RGB values. Then I have 2 lookup tables - the first goes from 0-31 and sets the 5-bit value. The second has 32 ranges from 255-[some value], which matches up with the first matrix's values but scales down the RGB values. e.g. after lookup I may get something like 16 & 255. Meaning 5-bit brightness is 16 and RGB is not scaled. One index up in the matrices would be something like 17 & 200. Gamma correction is built into those and I get a smooth brightness gradient across 256 values with very minimal hue distortion.

However I've noticed that my white balance is way off as I dim. It seems like the red on my SK9822s drops off a lot faster, making my dim colors green/blue shifted. (This is definitely not red shift from voltage drop).

All in all I'm really happy with the implementation but a bit disheartened at the hardware limitation. I wonder if its manufacturer-specific as well. My only thought as this point is to specify 32 different color corrections to use for each value of the 5-bit brightness. Any other thoughts?

@s-light
Copy link

s-light commented Aug 22, 2023

Somehow i can not find the the extended version in the current main branch?!
the pull-request was merged - but reverted in the switch to the pixelbuf_ architecture?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants