@Mikefila I believe the example you had kindly provided is meant to control a fan controlled by Home Assistant, right? In my project the fan is meant to be controlled primarily by the ESP32. I think I cobbled together code that works but I am unsure on how ideal it is…
I tried using 4 wire PWM fans but then remembered that those fans do not turn off at very low duty cycles, they actually speed up probably as a safety measure. The result would be that my fan would always run even when not needed, and that I would have to change the duty cycle between 30% and 100% to vary the speed.
I moved back to a MOSFET powering regular 12V fans and can now easily go from 0% to 100%. Or at least I think it is 100%… the signal going to the mosfet is not level shifted. I eliminated the level shifter as I was having issues (both incredible noise on the signal and it going on/off recursively). Turns out that the noise it the fan’s fault (if I power the fan down the noise on the PWM square wave goes away) and the on/off was caused by me always turning on the PWM output before setting the duty cycle. The documentation says you need to turn it on but I removed it completely and it still works so something else must be taking care of that…
Based on LEDC docs it would appear that I need to lower my PWM frequency in order to be able to vary the PWM down to 5% steps. This may be unnecessary but I don’t want the changes to be distinguishable audibly so on the low end I start slow 0%, 5%, 10% and may need to tweak it further once I pick the fans and test it in the cabinet.
If 100 is 100 steps (8 bits good enough), and 100.X is 1000 steps (12 bits good enaough), then 100.XX is 10,000 steps which would require me to lower the PWM to 4882Hz to get 14 bits (16384 steps). Is that how I calculate it?
esphome:
name: rack-fan-controller
esp32:
board: esp-wrover-kit
#board: nodemcu-32s
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: "xxxxx"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Rack-Fan-Controller"
password: "xxxxx"
captive_portal:
#AMR: Enabling I2C on port 21 (I2C SDA) and 22 (I2C SCL)
i2c:
- id: bus_b
sda: 32
scl: 33
scan: true
output:
- platform: ledc
pin: GPIO14
frequency: 25000 Hz
id: fan_pwm
fan:
- platform: speed
output: fan_pwm
name: "Network Rack Exhaust Fan Speed"
sensor:
- platform: bmp280
i2c_id: bus_b
address: 0x77
temperature:
name: "Network Rack Temperature"
id: rack_temp
oversampling: 16x
on_value:
then:
lambda: |-
if (id(rack_temp).state < 23.0) {
id(fan_pwm).set_level(0.00);
ESP_LOGD("PWM", "PWM: 0%");
}
else if ((id(rack_temp).state >= 23.0) and (id(rack_temp).state <= 24.0)) {
id(fan_pwm).set_level(0.05);
ESP_LOGD("PWM", "PWM: 5%");
}
else if ((id(rack_temp).state > 24.0) and (id(rack_temp).state <= 25.0)) {
id(fan_pwm).set_level(0.1);
ESP_LOGD("PWM", "PWM: 10%");
}
else if ((id(rack_temp).state > 25.0) and (id(rack_temp).state <= 26.0)) {
id(fan_pwm).set_level(0.2);
ESP_LOGD("PWM", "PWM: 20%");
}
else if ((id(rack_temp).state > 26.0) and (id(rack_temp).state <= 27.0)) {
id(fan_pwm).set_level(0.3);
ESP_LOGD("PWM", "PWM: 30%");
}
else if ((id(rack_temp).state > 27.0) and (id(rack_temp).state <= 28.0)) {
id(fan_pwm).set_level(0.4);
ESP_LOGD("PWM", "PWM: 40%");
}
else if ((id(rack_temp).state > 28.0) and (id(rack_temp).state <= 29.0)) {
id(fan_pwm).set_level(0.5);
ESP_LOGD("PWM", "PWM: 50%");
}
else if ((id(rack_temp).state > 29.0) and (id(rack_temp).state <= 30.0)) {
id(fan_pwm).set_level(0.6);
ESP_LOGD("PWM", "PWM: 60%");
}
else if ((id(rack_temp).state > 30.0) and (id(rack_temp).state <= 32.0)) {
id(fan_pwm).set_level(0.7);
ESP_LOGD("PWM", "PWM: 70%");
}
else if ((id(rack_temp).state > 32.0) and (id(rack_temp).state <= 35.0)) {
id(fan_pwm).set_level(0.8);
ESP_LOGD("PWM", "PWM: 80%");
}
else {
id(fan_pwm).set_level(1.0);
ESP_LOGD("ALERT", "OVER 35C! Setting fan to 100%");
}
update_interval: 2s
Next steps:
- how do I pass the fan speed (PWM) back to Home Assistant only when it changes to reduce the frequency (not every 2s)?
- How do I disable the fan from Home Assistant so that I can turn it off when the media room is in use?
Not asking you to do the work for me Just a mental note of my next steps. …and who knows, this may help others.
EDIT: The debugging log entry I make has a hardcoded PWM percentage as when I tried to pass the fan_pwm value using id(fan_pwm).state
or without the id function it either did not work or all I got was a fixed 1.6xxxx value. It would make more sense for me to have that log entry somewhere else in the loop and without hardcoding the % so I can simply have 1 call to ESP_LOGD.
EDIT2: Nevermind… the lowest I could go was 19531 for the PWM frequency otherwise I get a terrible whine from the fans.