PWM Output Duty Cycle Question

Trying to control PWM fan using ESP8266, it works but the duty cycle output does not correspond to the requested duty cycles. Example: Send 50%, ESP receives 50%, fan turns slowly, however looking at the output on oscilloscope the duty cycle is about 10% , fan returns 300 rpm. Has anyone seen this before?

Code:

sensor:
  - platform: pulse_counter
    pin: 
      number: D6
      inverted: false
      mode: INPUT
    name: "Pulse Counter"
    filters:
      - multiply: 0.5
    update_interval: 1s
    accuracy_decimals: 0
    unit_of_measurement: 'RPM'
output:
  - platform: esp8266_pwm
    pin: D5
    frequency: 25000 hz 
    id: pwm_output
light:
  - platform: monochromatic
    output: pwm_output
    name: "PWM Fan"

PWM set to 50%, Fan says 300 rpm and output on oscilloscope:

What kind of motor is it? Can you reduce the frequency down to something like 100Hz?

That was my first thought: what kind of twisted mind tries to PWM a fan at 25kHz?!

Then I read the Intel fan control spec:

The ESP8266 defaults to 1kHz PWM frequency, and is all done in software so higher frequencies will be less reliable.

Try running at 1kHz and see if it works for you.

its a Arctic F9 PWM PC fan. However even with the fan disconnected that wave is the same.

dropping the frequency down to 100hz has the same effect, 50% is not 50% duty cycle. Oddly the fan can still be controlled at 100hz, so much for the 21-28khz spec.

And how are you setting the duty cycle? Can you show the code that is running the output.set_level command?

What ESP8266 board is this — what GPIO pin is D5?

Probably not the reason, but the ESPHome docs all show the frequency setting in “Hz” rather than the incorrect “hz” you’re using.

GPIO14, setting the output using HA light control, i can see the value “50%” come through using verbose logging.

The frequency is being see correctly according to my oscilloscope

Maybe light: - platform: monochromatic isn’t linear.

1 Like

using Arduino IDE simple PWM sketch:

const int PwmPin = 14; 

void setup() {
  
}

void loop() {

    analogWrite(PwmPin, 500);
}

I get a perfect 50 - 50 duty cycle.

I think this may be it, although I believe it applies to all lights. After trawling the ESPHome source, I think you may need to include gamma_correct: 1.0 in your light section.

As far as I can see, the default 2.8 value is being applied to your 50% as an exponent, giving 14% duty cycle. The relevant function is currently line 74 of this file. ESPHome reference is here.

1 Like

:partying_face: :partying_face:

Thanks… gamma_correct 1.0 fixed it, perfect duty cycle.