WLED
WLED copied to clipboard
Higher PWM resolution for analog LEDs with ESP32
The default PWM resolution for ESP32 is set to 8 bits (ledcSetup, line 352 in bus_manager.h). However ESP32 supports much more than 8 bits resolution. Actually the default PWM frequency that WLED uses for ESP32 (-> 19531 hz) is the highest possible PWM frequency for 12 bit PWM resolution. So it would be possible to increase the PWM resolution to 12 bits without changing the currently used PWM frequency, so it wouldn't have a downside.
This would result in 4096 (with 12 bit) vs. 256 (with 8 bit) brightness steps. That on the other hand would allow for better brightness adjustment and smoother brightness change fades, especially in lower brightness, whereas today brightness fades under 10% look choppy.
Additionally, support for other resolutions would be nice, too. So for example one could choose 10 bit over 12 bit to have a higher PWM frequency of up to 78125 hz (with 10 bit resolution).
To further improve the brightness fade, the ideas from #2767 seem promising.
That would require complete rewrite of how WLED handles color/brightness. #2252 IMO infeasible ATM or in the near future.
I can't exactly understand the amount of work to be done for such an improvement or general change in brightness handling, but I think there is a growing demand for more than 8 bits resolution, as seen in your linked #2252 in conjunction with the upcoming of more and more digital LEDs, like the mentioned UCS3903 / UCS8904 or the HD108. And there are good reasons for improvement. On the other hand, analog LEDs might have fewer possibilities (regarding effects etc.), but are usually able to produce better quality light. So the performance of analog LEDs should not be limited by software.
A more personal opinion on this topic: Light and especially light quality is the core of WLED and practically every LED project as everyone wants the best visual performance. Therefore it's more important to improve light quality than loading WLED with even more project specific features, effects and usermods.
@ProjectProcrastinator I see you referenced my issue here. I don't agree with @blazoncek that it would require complete rewrite, all we need is bump the resolution to 12bit and use a lookup table to bring it back down to 8bit. User will still have 255 steps in their brightness slider, nothing changes. I'll see if I can do a pull request of this, at least for simple white strips. RGB might behave differently, didn't make much research there.
One more issue is that ESP8266 has really atrotious pwm, so this would be only for ESP32.
I don't agree with @blazoncek that it would require complete rewrite, all we need is bump the resolution to 12bit and use a lookup table to bring it back down to 8bit.
It is always good to have a fresh perspective on the subject and I welcome your idea. 👍 Perhaps combined with logarithmic or some other non-linear response would be great.
@blazoncek I don't know if you saw the referenced issue but most viable ways to do it are mentioned there: https://github.com/Aircoookie/WLED/issues/2767
I'll see if I can do a pull request of this, at least for simple white strips. RGB might behave differently, didn't make much research there.
Any updates/progress @mcer12 ?
Any updates here? I'm seeing visual brightness steps (specially on the low brightness steps) so upping it to 10 or even 12 bit would be awesome!
Bump. Couple months later, now have a analog led strip (though FETs) working. This too so very clearly shows brightness jumps on the low levels. Can at least analog be changed to 10 or 12 bit? There should not be a technical limitation for analog, right?
Since my original request I have investigated this topic a bit more and there are a couple of technical (hardware) limitations for analog LEDs. I have written about the capabilities of the ESP32 above (max. PWM-frequency at a given PWM-resolution), but you have to consider the rise/fall times (meaning the speed of switching) of your used Mosfets and Mosfet-Drivers, too. There is an online-tool (https://calc.apps.poly.nomial.co.uk/led_pwm/) that lets you calculate the required driver speed for a given PWM-frequency/resolution. In the end, not the ESP32, but the driver (Mosfet+Mosfet-Driver) is the limiting factor.
Nonetheless I would still like the option to use a higher PWM-resolution. Not only could the user choose the best compromise of resolution/frequency for their application, but that would also be a great benefit when controlling integrated LED-Drivers, that use an external PWM-signal to then generate their own PWM and maybe combine it with analog dimming (hybrid dimming, like TPS92391) to increase LED dimming resolution and contrast.
Sadly this feature apparently is not of importance for the WLED-developers. A quicker way to "fix" the steppiness of fading from or to low brightness levels would be to adjust the fade function itself. My idea would be to dynamically adjust the fade time according to the brightness level that it fades from or to. To me it looks like the Philips Hue bulbs use this approach. If one turns them off from low brightness levels they just go off or have a significantly lower fade time, while they have a longer fade if turned off from higher brightness.
@ProjectProcrastinator, i don't think it's as extreme as you make it seem. By that i specifically mean this section:
but you have to consider the rise/fall times (meaning the speed of switching) of your used Mosfets and Mosfet-Drivers, too. There is an online-tool (https://calc.apps.poly.nomial.co.uk/led_pwm/) that lets you calculate the required driver speed for a given PWM-frequency/resolution. In the end, not the ESP32, but the driver (Mosfet+Mosfet-Driver) is the limiting factor.
Say i pick these values:
Where only the frequency (5kHz), bits(10) and fps(120) matter. That very site also indicates if you'd see perceived flickering. At those settings (frequency plays a big role there) you don't see flickering and already have a much much much higher quality dimming experience (with 10 bits, 1024 steps).
But let's look at it from a hardware point of view.
I'm using the IRLB8721 with the following rise and fall times:
So for that specific FET, and the above specific PWM requerements a single cycle for the FET is 200.00 μs + rise + fall (rise and fall together are just barely over 0.1 μs, i'd call that irrelevant). It's all neatly within the spec of the above timing image.
I don't see any values looking weird or impossible for the ESP32 either. Could you elaborate on where you see a problem? As i don't.
Heck, according to that same site 12 bit and 14 bit with the other input remaining as is would be just fine too.
I didn't meant to say that there is an issue so that you can't have much higher PWM-resolution at lower PWM-frequency. That is not a problem. But it's a problem to just increase the PWM-resolution while using the same ~20khz PWM-frequency like I suggested in the original post. According to this calculator 12 bits with 20khz would need a driver with fall/rise time of 3.05 ns. While the ESP32 is able to do it you will have big trouble to find Mosfets + Mosfet-Drivers that achieve these numbers. In my custom analog controller I use quite good Mosfet-Drivers (UCC27524) and these alone have a rise/fall time of 7 ns. If you don't use Mosfet-Drivers your Mosfets will most probably not achieve the best-case results from the datasheet. In my case I would like to stay at or above 20khz, not because of visible reasons but because of audible noise that may be generated due to the PWM. That's why I mentioned above that it would be nice to have flexible settings so that a user could use what fits the application. Commercial LED-Driver ICs mostly don't use plain PWM, but PWM with dithering or PWM in conjunction with analog dimming (hybrid dimming) to achieve very high constrast ratios (resolution) while at the same time staying at over 20khz PWM-frequency.
Are you willing to test variable 8-12bit modification? PM me on Discord and mention this issue (#2868).
That's a hesitant "yes"... My module is literally glued and soldered in place to a light fixture. Getting it loosely available to flash again is going to be a full day of work for me that i don't want. So if your flash has a risk of making my model run in a bootloop then nope, not interested.. ESP32-S3 here btw.
Can you post the code diff somewhere? Or just your github repo with the change included?
Getting it loosely available to flash again is going to be a full day of work for me that i don't want.
Then, by all means, get a spare unit for testing purposes. 😄
It is always possible to brick a device, even with a release version of software for that matter. I'll provide beta version of WLED 0.15.0 modified with variable LEDC duty resolution.
With the help of @ProjectProcrastinator we have identified that the problem does not lie in PWM duty cycle resolution but rather the 8 bit nature of global brightness (possible values of 0-255).
While you'd like this to be 10 or even 12 bits (0-1024 and 0-4096 values respectively) to achieve greater low brightness resolution I'm afraid I'll disappoint you all as this change will not happen any time soon as it has profound effect on whole codebase (including but not limited to interfacing with outside world, as I already mentioned above).
Even though @mcer12 suggested otherwise I have yet to see his implementation (while keeping compatibility across every possible aspect). IMO if you want to use lookup tables (and use those to interact with outside world to keep compatibility) you need to have global brightness with 10 (or 12) bits of depth.
That is, unless some brilliant idea comes along.
Implemented in c0beb621e26a5aea017fe20f2f501175a1e33474