WLED
WLED copied to clipboard
Feature request: Change PWM frequency per channel/pin
Hi,
I'm trying to mod an Aukey desk lamp using an ESP8266 board and WLED. I've found a teardown of my exact lamp, and someone has been kind enough to document what type of signals the onboard IC that I would have to replace is putting out:
Pin 5 of U2 has a 20 kHz PWM signal on it. As the brightness changes, it cycles through 20, 60, and 100 % duty cycle. When the LED is to be off, the pin is held low.
Pins 2, 3, and 7 have a 2 kHz PWM signal, with duty cycle correlating to the following:
Pin 2: Blue PWM
Pin 3: Red PWM
Pin 7: Green PWM
Since I want to control all four channels, I need a way to set the PWM frequency differently for the white channel than for the color channels. Would this be possible? Thanks!
It would but you would need to modify source to your needs. Look into bus_manager.h, BurPwm class.
Thinking of it if these are analog LEDs they really don't care about PWM frequency. Advantage of 20kHz PWM frequency is that flickering on camera is less noticeable. You may be fine with using WLED OOB on these LEDs.
Thanks for your feedback! I guess I'll try first just like this and if not then look into the function. I agree that it shouldn't make a difference to the LEDs themselves, but I'm not sure what the surrounding circuitry is like so I'd prefer to emulate the IC I'm replacing exactly if that's possible. It does seem like ESP8266 PWM is just done in software, so theoretically different clocks on different pins should be possible, and in fact I've found documentation in the NodeMCU SDK that supports it. Seems like it's doable.
I believe with LEDC on the ESP32 lower PWM frequency results in a higher gray-scale bit-depth. 20kHz only has 4096 steps, Whereas 2.4kHz has 32768 steps. At least for ESPHome, this higher bit-depth results in much smoother dimming transitions.
Reference: https://esphome.io/components/output/ledc.html#recommended-frequencies
There is some ongoing discussion about using higher PWM frequency and improved PWM resolution: https://github.com/Aircoookie/WLED/issues/2868.
Hi, I'd also like to have the possibility to change pwn frequency because when I am sitting next to my led strips I can hear this very high peeping sound. And this is really annoying. I can imagine that it could be difficult to make this separately for all channels if the white correction math is based on that. So I would propose the compromise that the frequency can be set in a defined range (or to several predefined values) for all channels together. This would simplify the math.
You can compile your own version with modified/changed frequency. There is no need to modify source files for that. Until such thing is added to configuration.
You can compile your own version with modified/changed frequency. There is no need to modify source files for that. Until such thing is added to configuration.
Thank you for pointing that out. Apart from the option to compile a version by myself I do not yet fully agree with your argumentation. You talk about "no need". But who defines what is "needed"? Nobody "needs" WLED in the first place - although I really love it and appreciate it! Now I raise something that could be improved because there are people like my who are sensible to high audible frequencies. I partially agree that the noise is of course totally irrelevant for the main purpose of WLED to create beautiful lights. But please don't reject improvements only because they are "not needed".
Considering that PWM is generated by software I like to ask the following:
- is there a specific reason to choose exactly that PWM frequency (like resolution or so)? if yes: please describe the reason and I am immediately willing to accept that if no:
- what will be the highest possible frequency without running into trouble (like loss of resolution)?
Again, if there is a good reason for something I will definitely accept that. But if things can be improved with relatively low effort without noticeable disadvantages, why not adapting them?
Cheers
- is there a reason to choose exactly that 880 Hz as PWM frequency (like resolution or so)?
In fact, there is a reason - if you are using 8266. The chip cannot run 8bit PWM at higher frequencies than ~900hz. ESP32 on the other side defaults to 19.5Khz PWM, which is also close to the max capabilities of the chip.
Edit: The LED strip usually does not create any sound - PWM is a pure electrical thing. But some Power Supply Units will not work well with PWM - these may beep, its called "coil whining". Sometimes it helps to choose a higher quality PSU.
In fact, there is a reason - if you are using 8266. The chip cannot run 8bit PWM at higher frequencies than ~900hz. ESP32 on the other side defaults to 19.5Khz PWM, which is also close to the max capabilities of the chip
Okay, thats interesting. From other projects like tasmota or esphome I know that one can set somehow higher frequencies for soft-PWM. But anyway, maybe they they just deal with the fact that resolution gets down as a compromise. For one of my tasmota lights I set the frequency DOWN to 200 Hz which still causes some flicker if I move my eyes really fast, but now it does not peep anymore...
Edit: in fact the strip usually does not create any sound - PWM is a pure electrical thing. But some Power Supply Units will not work well with PWM - these may beep, its called "coil whining". Sometimes it helps to choose a higher quality PSU.
That is only partially true. Of course coil ringing occurs in many application, no doubt about that. Because also in these applications the coil is pulsed by some kind of signal - in many cases a PWM. But the effect to produce a sound by pulsed current is in no way limited to "coil". It might occur in any kind of conductor that has the possibility to swing (part of my daily business in power electronics R&D). I can prove the audibility of the PWM signal by at least three things:
- the noise can by located at the lamp and not the PSU (which is a few meters away).
- the noise is more or less exactly at 3520 Hz - what is basically that I would expect in an application with four channels at 880 Hz. (of course they do not just sum up - what I hear is the fourth harmonic because of overlay)
- the noise is loudest at 50% and virtually disappears at 100% (as to expect) So please lets finish the point to try to prove me wrong in what my ears hear ;) .
If we can't get higher in frequency because of loss of resolution or anything else: what about the option to go DOWN? Of course you might have to deal with flicker effects at some point. We all know this. But why not leaving this up to the user by providing this option? Then one can choose whatever fits best to the users requirements.
@Jojo-A I'm not interested to prove you wrong, especially I'm not going to argue about what you hear. If 880hz on 8266 is hurting your ears, why not simply use an esp32 ?
btw, below is the source code responsible for setting PWM frequency.
As you can see, the PWM frequency can be defined with -DWLED_PWM_FREQ=xxx
, so feel free to experiment with that.
We rely on standard analogWrite()
or ledcWrite()
for PWM output. No idea what tasmota or other software does for PWM.
If you have a clever idea on how make PWM faster, please feel free to create a PR
https://github.com/Aircoookie/WLED/blob/51b3d7cb4a47406447015ce5e6b68d668ff80a63/wled00/const.h#L433-L440
https://github.com/Aircoookie/WLED/blob/51b3d7cb4a47406447015ce5e6b68d668ff80a63/wled00/bus_manager.cpp#L390-L394
https://github.com/Aircoookie/WLED/blob/51b3d7cb4a47406447015ce5e6b68d668ff80a63/wled00/bus_manager.cpp#L291-L323
Okay perfect, thank you! I will definitely try to compile a version with modified frequency. I am currently just reading through the docs how to set up the development environment.
About PR: I will try to compare the way how PWM is generated in different projects. Lets see what I can find. But in the meantime it might be still worth to think about a way to modify the PWM frequency during runtime in WLED. If this structure exists and works it will be just a matter of ho to define the min and max thresholds for this setting. So I am basically not interested in increasing the frequency at all costs - I am more interested in being able to modify it in general :) . Cheers
👍
To get you started with using the development env (i.e. VSCode+platformIO) look into our KB
- https://kno.wled.ge/advanced/compiling-wled/
- https://github.com/Aircoookie/WLED-Docs/issues/161
Okay, I've set up a minimal platformio core environment for compiling WLED sources.
That works so far.
To be on the safe side I've added -D WLED_PWM_FREQ=250 to the compile options as well as the pre-processor macro #define WLED_PWM_FREQ 250.
To my surprise: both did not do anything -_o !
So I went into the code and change the line 296 in the file WLED/wled00/bus_manager.cpp to
_frequency = 250;
This led to the desired result to reduce PWM frequency.
This means, that the variable bc.frequency blocks the pre-processor macro for PWM to be used as long as the variable bc.frequency is != 0.
So either I have not understood the logic behind all that (what might definitely be the case ;) ) or it is a bug that prevents the WLED_PWM_FREQ macro to be used because the variable bc.frequency is != 0.
Any idea about that?
Thank you!
By the way: the really annoying peep sound has disappeared now. The flickering is fast enough that it is only noticeable when I move my eyes really fast.
Setting custom PWM frequency is already implemented in WLED but it lacks UI (only available for 2 pin digital LEDs). Just edit cfg.json and update "freq" field for chosen output to the desired PWM frequency in Hz.
Setting custom PWM frequency is already implemented in WLED but it lacks UI (only available for 2 pin digital LEDs). Just edit cfg.json and update "freq" field for chosen output to the desired PWM frequency in Hz.
Okay, that was much too easy XD ! Sorry for the irritation caused! Thanks a ton, that is perfect!
We do have PayPal links if you feel generous. 😉
Changing PWM frequency is now possible in 0.15.0 beta 1 or later. It also includes 12bit PWM duty cycle resolution improving on low brightness dimming.