-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
beta-3 Auto Brightness Limiter issue #3264
Comments
Please reduce the limiter from 2000mA to 1000mA and report if the brightness varies again. |
I have a similar issue - maybe the same, I'm not sure if it is appropriate to add here or start a new issue. |
@blazoncek the behaviour could be related to our change from NeoPixelBrightnessBus to NeoPixelBusLg, as there is a subtle difference in behaviour of setBrightness() Old
New
Our brightness limiter will run just before busses.show(), and it calls SetLuminance() to modify brightness before sending out pixels to the LEDs. With the old object "All current pixels will be modified", but with LG it "does not affect all previous pixel values". I understand that SetLuminance() will not touch pixels already stored with SetPixelColor() but not shown yet. The new luminance will only affect future SetPixelColor() operations. @Makuna is this correct? As consequence, our brightness limiter would always be "one frame behind". So the first frame above brightness limit would show at full brightness (brownout, magic smoke). Then the next frame will use the modified brightness intended for the previous frame, etc (rhythmic dim-bright). |
Maybe this method of NeoPixelBusLg will help, but looks like luma and gamma could be applied twice which is not good either:shrug: ...
|
Exactly the behaviour I am seeing. |
@softhack007 this was a good catch! ❤️ Solving this is going to be a tough call as setBrightness() is used in many places.. Another option I was thinking about yesterday (solving #3265) is to dump global brightness altogether and rely on segment opacity only. That was also on @Aircoookie 's mind some time ago but it will be a huge change for endusers. Possibly breaking everything if not implemented properly. |
Agreed! Just using segment opacity will also still not solve the issue that we need to have set all LEDs in a given frame in order to determine the max. allowed brightness for that frame. |
I checked the code and UDP/realtime is setting bus brightness directly as is "i" from JSON. Other instances of setBrightness() seem to be cool and in line with the possibility to So, perhaps it is ok to just add |
Sound good to me 👍. The docs from makuna say
So unless we use NPB gamma correction, the function will adjust brightness as we want it. .... and as a bonus, if WLED does not set brightness before "painting" but only after drawing, we could use max possible color resolution on strips that support more than 8 bit per color. |
ApplyPostAdjustments is meant for the case where you call Pixels() and manipulate the buffer directly. It is not meant to be called if you use SetPixelColor. All it does is get each pixel (by calling GetPixelColor which does not revert any previous brightness nor gamma correction already applied unlike the old brightness bus) and then apply the luminance and gamma correction before setting the color back. The key here is, SetPixelColor will apply Luminance and Gamma, then calling ApplyPostAdjustements will apply them again to those already modified values. Not what you want. The "correct" way is to set Luminance, then draw all pixels, then call show in that order. The reason is math. The old brightness bus, when you call change brightness, it would need to take the current value that is already fully rendered (brightness and gamma applied), try to reverse these with all the lost resolution and thus isn't the original value set, then reapply the new brightness and gamma. It is a flawed model that was never meant to be used the way brightness bus was being used. This is why I deprecated it. If you need to call GetPixelColor, modify, and then SetPixelColor for a visual effect (not gamma or luminance but specific effect you do), then you should be using a DIB (device independent buffer class from the library with similiar API to a NPB) and do that to it, then Render that into the NeoPixelBus using the luminance/gamma shader exposed as strip.Shader member. I want to add one technical detail that gets missed easily and glossed over. |
@Makuna thanks for explaining, makes perfect sense :-) I think our way forward could be A) hotfix for beta-3, based on the proposal from @blazoncek and @Aircoookie to use ApplyPostadjustments(). We are only using NeoGammaNullMethod, so the behaviour might be similar to the old BrightnessBus - maybe with reduced color quality B) investigate how to integrate the DIB object into our code, as it seems this is the proper way of doing it. @Makuna would the DIB increase memory needs, compared to NeoPixelBusLg? |
As I understand, DIB is a secondary buffer to enable lossless getPixelColor() and brightness adjustments. It would need |
Aircookie is correct, RgbColor DIB is Count * 3, RgbwColor DIB is Count * 4. Of course the Rgb48Color and Rgbw64Color are double those if you even want to use them. Another feature of the DIB double buffer model, is that when you render into a 16 bit per element Bus, it still has benefits even if you only use an 8-bit per element DIB source as the render will up translate before doing the math for the final 16 bit per element bus. |
We already have global LED buffer, which is (ATM) |
KingSuperNerds> This is exactly the problem that occurs on full white as well!! And if you look at your red board light, it's probably doing it to! |
Lowering Brightness to around 75% alleviated the issue. But due to safety implications with my power draw without the limiter, I reverted back until I can get an actual psu and wiring to handle the full load. |
Is there a difference between the three temp fixes above? i tried the first one last night with success, didn't know if I should revert to the latest ones. |
There's only one fix. |
Confirmed :-) the "other two" are the same fix, just merge into the MoonModules fork (needed to do it twice). Github is a bit stupid about this, whenever some does cherry-picking from upstream, it gets listed as "pushed a commit". So there is only one hotfix, and two copies of it in the other fork. |
Hi, (Sorry for bad video conversion) |
It looks like what I was experiencing. the temporary code fix worked for me, but they have converted it to a pull request that is in review processes. I would say you are seeing the same thing though. |
@Makuna a bit of help needed. I changed our code (in leds.SetBrightness(bri);
if (buffered) {
for (i=0; i<leds.length(); i++) leds.SetPixelColor(i, c);
} else {
leds.ApplyPostAdjustments();
}
leds.show(); If I added Do you have any idea why would such thing happen? My initial thought was:
|
@blazoncek How are the colors set in your psuedo code example for !buffered? With NeoPixelBusLg, GetPixelColor will return what is the internal buffer, usually fully modified with luminance and gamma; not what you called SetPixelColor with. In the case you directly modify it using the pointer returned from |
Thank you for explanation @Makuna |
When you write into the buffer, are you also calling Calling |
No, we never write directly into the NeoPixelBus buffer. We always use
|
so, with this paint pixels using SetPixelColor(), set luminance, apply post adjustments, do Show() You really should first set luminance to 255, then paint pixels using SetPixelColor(), set luminance to real value it should be, apply post adjustments, do Show(). An advanced way to do this that bypasses the built int shader is...
|
That was exactly my idea, but to make it simpler to maintain, I moved SetLuminance(255) immediately after Show() so it is ready for next frame. Yet somehow GetPixelColor() was returning "inappropriate" values every other Show(). 😄 Advanced method would be too complicated using our flexible bus infrastructure. |
Do you know which frames it is showing "inappropriate" values? Ones only when use one specific method of the two you supplied? |
When using our buffer (and retrieving color information from it) our brightness limiting routine works as expected. But when using:
It doesn't. It is "pulsing" every other frame. So using only NeoPixelBusLg, the every other frame we retrieve "inappropriate" values from GetPixelColor() if using SetLuminance(255) immediately after (every) Show() even though all pixels are painted with SetPixelColor() before we fetch them with GetPixelColor(). If I reiterate our workflow in a flawed case in a slightly different way:
NOTE * GetPixelValue() undergoes color restoration process which does (c*255+brightness)/(brightness+1) I am testing with static full white color only (FPS is about 3-4, but I could reduce it to 1 for testing). I will add some code, to display actual GetPixelColor() values but it may take some time as I have some IRL stuff to do. |
Thinking of it, there is no need to restore brightness of modified pixels we only need to do it for unmodified ones (if not every pixel was touched). |
@blazoncek that is true, but would require us to keep track of which pixels were modified in the current frame, which could be complex and memory intensive. At that point, true double buffering or just repainting the entire bus to the new brightness seems preferable. @Makuna thank you for your help, I highly appreciate it! One small clarification question, I always assumed it'd be unsafe to call |
@Makuna thank you also from my side for help and clarifications. The problem was entirely on our side and has now been mitigated. |
It is safe to call SetPixelColor and even call Pixels() to get the pointer to buffer to modify it while CanShow() is still returning false. Assuming a single thread calls SetPixelColor and Show (or you have appropriate blocking in place). |
What happened?
Upon update to the new B3 firmware on an ESP32, I noticed a rhythmic bright-dim blink while my lights (sk6812 rgbw with accurate setting for white) were set to solid white. Upon further inspection, it seemed they were trying to pull maximum power even with Limiter set at 2000 ma. It was evident by the dimming of the ESP32 red led when it would blink. My USB power block also heated up quickly.
To Reproduce Bug
Run B3 on ESP32. Set brightness Limiter to 2000 ma. Using 5v sk6812 rgbw 144leds/m and a 2.4 amp USB block, run a 1 meter strip on white using accurate white calculation in settings and then turn the brightness to max on color page.
Expected Behavior
Not for it to try to burn up my power supply with the brightness limiter set to 400 ma below it's capacity(Yes, I know I should have it fused and need a way bigger power supply for the full potential of these lights. I just have to get back around to this particular project and get the stuff ordered.)
Install Method
Binary from WLED.me
What version of WLED?
WLED 0.14.0-b3
Which microcontroller/board are you seeing the problem on?
ESP32
Relevant log/trace output
No response
Anything else?
Just a note, I rolled back to b1 and all is working as it should again. If you need more info, I can try to gather it at your request. Thanks for all you do for this project because WLED is pretty cool!!
Code of Conduct
The text was updated successfully, but these errors were encountered: