Peculiarity with multiple LEDC outputs

I wonder if anyone else has seen this.

I am using 4 LEDC configs to do PWM. I’m not controlling LEDs. I’m controlling the speed of PC case fans (the 4-wire kind with PWM control). When I tested with a single fan to get things going, everything worked as expected. When I tested with multiple fans, things got weird.

PWM case fans want a frequency of 25000 but will typically tolerate anything in the 20s. 25kHz is not a challenge for an ESP32 and probably gives at least 2000 steps of duty cycle resolution.

My ESPHome config for this boils down to: when I press the button on the ESP32 dev board, the PWM duty cycle steps up 0%, 20%, 40%, etc. The difference in speed at each step is visible by eyeball and audible to, uh, earball. I also have ways to trigger stepping back down, and also stepping up or down by a single step. Randomly, some of the fans will actually slow down quite a bit at a step; at the next step they might go back to the expected speed. Naturally, I suspected a flaw in my circuit or config, but which fans show the slowdown and at which PWM duty cycle step varies quite a bit. About a third of the time, everything works as designed. For about another third of the time, one of the fans will misbehave. And for another third of the time, two or more fans will misbehave. (I’ve done lots of trials where I leave the circuit unplugged for a while, plugged in for a while before testing, waiting between test iterations, swapping fan cables around, etc.)

I finally resolved it, but I haven’t found definitive documentation for why the resolution works. Originally, I was letting ESPHome allocate the ESP32 LEDC channels. It starts at channel 0 and goes up by one for each LEDC configured. I thought there might be some funny business with shared clocks, so I explicitly configured the channels in ESPHome config, making sure I did not use 2 adjacent channels. No change. I eventually switched to use exclusively low frequency channels, and that seems to have resolved the problem.

The ESP32 has 16 channels for LEDC. Channels 0-7 are high frequency; channels 8-15 are low frequency. Here is the config that works for me:

output:
  - {platform: ledc, id: f1_pwm, pin: {number: '${F1_PWM}'}, frequency: 25000Hz, channel:  8}
  - {platform: ledc, id: f2_pwm, pin: {number: '${F2_PWM}'}, frequency: 25000Hz, channel:  9}
  - {platform: ledc, id: f3_pwm, pin: {number: '${F3_PWM}'}, frequency: 25000Hz, channel: 10}
  - {platform: ledc, id: f4_pwm, pin: {number: '${F4_PWM}'}, frequency: 25000Hz, channel: 11}
1 Like

Hi Bill!!
You made my day! I was almost desperate with a similar issue controlling a servo and a buzzer.
thanks a lot for sharing!

Gotta read the documentation. It specifically talks about problems that arise with automatic channel selection.
Screenshot from 2024-01-28 17-45-42