patrickcollins12/esphome-fan-controller

make fan stop spinning at zero

sobrarbe opened this issue · 71 comments

Hello, I just installed a Corsair ML120 fan as you say and it works well except for the one when it reaches the stop temperature and it keeps turning at 1400 RPM. Could you help me create a stop or what parameters can I change to make it stop? the adjustments that you had at 13% the stop changed it to 0% but it continues turning. could you help me?? thank you.

B1199 commented

same here

i tested it myself for fun. a 5 year old Corsair ML120 stops, but the one from November 22 keeps running.
Seems that Corsair has changed something.

you would have to buy fans with 0DB mode, the Corsair doesn't have that.

hello. and could you put an IRF520 MOSFET inserted or is it not recommended? And if it could be put, what would the yaml code look like? Thank you so much

I'll update the instructions to include a mosfet and an off switch. A lot of people seem to need this.

thank you. if you are so kind when i update it i commented here to see how to do it.

B1199 commented

i tested it myself for fun. a 5 year old Corsair ML120 stops, but the one from November 22 keeps running. Seems that Corsair has changed something.

you would have to buy fans with 0DB mode, the Corsair doesn't have that.

Thanks for your testing. Can you possibly recommend a 0DB or 0rpm fan that might work. My Corsair fan still makes too many revolutions on the smallest setting.

Arctic P12 PST 0dB

B1199 commented

I did a new test with same new Corsair ML120 (Model: 31-005165), but now with an ESP8266 board. Now it runs as expected and the fan goes off below 13%.
There seems to be a difference between ESP32 (platform: ledc) and ESP8266 (platform: esp8266_pwm).

Corsair ML120 (Model: 31-005165) Datasheet: Speed: 400 - 2400 RPM

I have ordered a Artico fan with a stop from 0 to 2000 RPM. If it doesn't work, I'll do it as you say with an 8266. I also wanted to know if anyone could help me get the yaml to add an RGB light to this same project that includes the fan I bought. I wanted that depending on the temperature detected by the temperature sensor, the RGB of the fan would turn on.
Red 40 to 50 °C
Yellow 30 to 40 °C
Blue 20 to 30 °C.
Thus, by looking at the RGB light of the fan, I will know the temperature of the cabinet. Thank you so much.

i think you mean the Arctic 0DB. the fan has a 3 pin connector for the LED lighting. these are 5v, GND and the data line.

unfortunately, i do not know which protocol is needed. In the simplest case it is WS2812b LEDs. then it is easy and enough examples can be found in the net. you could try that first. Otherwise ask Arctic.

Thank you, I see that with the fan it will be complicated by the protocol you mention. He still did what you say with a WS2812b led strip. I'm new to ESP32 and I'm looking online to create the yaml and I'm not clear on how to add it to the yaml of this project with the WS2812b leds controlled by the temperature sensor that activates the fan. Do you know of any tutorial that explains it well? thank you.

I just found this documentation that can also be used for the fan with RGB light. What do you think? https://esphome.io/components/light/fastled.html

@kaesebrot1199 Hello. You could pass the yaml configuration of this project to the Esp8266. I'm trying and my Artic fan doesn't work and I don't know why. Thank you.

B1199 commented

@kaesebrot1199 Hello. You could pass the yaml configuration of this project to the Esp8266. I'm trying and my Artic fan doesn't work and I don't know why. Thank you.

My yaml with comments:
esp8266.yaml.txt

@kaesebrot1199 Thank you very much for sharing your yaml. I just tried it but my fan still with 8266 board does not stop completely and I will have to integrate a MOSFET. But it's not clear to me how to add it

B1199 commented

@kaesebrot1199 Thank you very much for sharing your yaml. I just tried it but my fan still with 8266 board does not stop completely and I will have to integrate a MOSFET. But it's not clear to me how to add it

I advise you to use a layout without MOSFET and find the right fan, which switches off at low PWM. You can see this in the datasheet of the fan.
Here for example the diagram of my Be Quiet fan: https://www.bequiet.com/admin/ImageServer.php?ID=ba45ba43151@be-quiet.net&.jpg
In the diagram you can see that the fan only turns on at 20% PWM. Not all PWM fans have this behavior. Maybe your Artic Fan cannot do that.

https://www.bequiet.com/de/casefans/3705

Here is my recommendation. It should work fine.

Buy a logic-level mosfet. I would recommend either the IRLZ44N or FQP30N06L.

The fan's power needs to connect to the Drain pin of the MOSFET. The other side of the, the Source, needs to connect to the 12v power ground.

Gate: Connect to the ESP32's GPIO (possibly through a small resistor, like 100Ω to 220Ω, for gate drive protection).
Drain: Connect to the negative (or ground) side of the fan.
Source: Connect directly to the circuit ground (0V).

Remember, the ground of the microcontroller should be connected to the same ground as the MOSFET and the fan.

Flyback Diode: It's good practice to place a diode (like the 1N4007) in parallel with the fan, but oriented in such a way that it normally doesn't conduct (anode to the fan's negative terminal and cathode to the fan's positive terminal). This diode will protect the MOSFET from voltage spikes that can occur when the fan is turned off due to inductive kickback.

Assuming you use GPIO PIN 25 for the MOSFET gate, your YAML would be as follows:


# this power supply is turned on/off when the output below
# meets the min_power.
power_supply:
  - id: mosfet_power_supply
    pin: GPIO25

output:
  # Wire this pin (13) into the PWM pin of your 12v fan
  # ledc is the name of the pwm output system on an esp32
  - platform: ledc
    id: console_fan_speed
    pin: GPIO13

    power_supply: mosfet_power_supply

    # 25KHz is standard PC fan frequency, minimises buzzing
    frequency: "25000 Hz" 

    # my fans stop working below 13% powerful.
    # also they're  powerful and loud, cap their max speed to 80%
    min_power: 13%
    max_power: 80%

Please test this and if it works, I'll add it to the documentation,

Hello @kaesebrot1199 , I am desperate with the fan that does not stop. I just bought the be Quiet pro 4 as you recommend to test if it stops below 20% and nothing. It keeps turning at low revs. I test it with ESP32 and 8266 Board and the result is the same. At the end I am going to put a MOSFET that @patrickcollins12 comments. Waiting for the MOSFETs to arrive to test the configuration that it commands.

Please confirm that your yaml also has min_power set to 0 in the ledc configuration

Yes, I have the minimum and maximum fan on and putting it from the minimum of 20% to 0% and it continues to run at 90 RPM. I'll try the setup with the MOSFET you offer and comment. I'm also thinking that it may be because of the type of ESP32 board that some manufacturer builds that does other output parameters? or that doesn't matter. Thanks for the help @patrickcollins12

Hello, today the MOSFETs have finally arrived and I put the programming that @patrickcollins12 says and it works perfectly. I wanted to know if you could help me one last time. I have the RGB fan and I just realized that with the temperature it lights up in different colors depending on the temperature. It works very well for me and it looks very nice. What I want to achieve is that at a certain time of the day, for example at night, the RGB LED turns off and that at a certain time in the morning it turns on and continues the cycle of color changes with the temperature. Could that be done? Thank you

Great project. Currently using silent wings fans.. all wires are black so a bit trial and error finding out which is which… so I may have an error here BUT the Fans work but I am not getting any readings at all everything is coming back as -0.000 and not able to control the fans
do I need to explore trying with a mosfet or have I done something daft!! I may try with some Corsair fans arriving tomorrow but any guidance gratefully received

Hello, today the MOSFETs have finally arrived and I put the programming that @patrickcollins12 says and it works perfectly. I wanted to know if you could help me one last time. I have the RGB fan and I just realized that with the temperature it lights up in different colors depending on the temperature. It works very well for me and it looks very nice. What I want to achieve is that at a certain time of the day, for example at night, the RGB LED turns off and that at a certain time in the morning it turns on and continues the cycle of color changes with the temperature. Could that be done? Thank you

Glad to hear it works!

Is there a pin to turn on off the rgb? If so you could try controlling that with another gpio pin on the esp32. I don't have experience with rgb fans.

Great project. Currently using silent wings fans.. all wires are black so a bit trial and error finding out which is which… so I may have an error here BUT the Fans work but I am not getting any readings at all everything is coming back as -0.000 and not able to control the fans

do I need to explore trying with a mosfet or have I done something daft!! I may try with some Corsair fans arriving tomorrow but any guidance gratefully received

To answer your question. No I don't think a mosfet will help here.

When you say you're not getting any readings, do you mean on the tachometer pin?

Is it possible you've switched the tach and pins?

You might have sent 12v into the circuit which will fry the low voltage tach/pwm pins?

Just ideas.

So I have now connected a new Corsair Fan. This time I did not cut the fan cables, but plugged into into a 4 pin connector. The connector has black, red, yellow and blue wires and so I have connected them as follows:

Ground(Black),
12v (red)
GPIO25 (yellow for Tacho )
GPIO13 (blue for PWM)

All the DHT sensors work fine, the ESP32 is working fine (and the dashboard in HA looks great).

Sadly however, the fan speed is still not showing anything but Zero. The log shows the following:

D][dht:048]: Got Temperature=27.5°C Humidity=57.0%
[D][sensor:094]: 'Temperature': Sending state 27.55905 °C with 3 decimals of accuracy
[D][sensor:094]: 'Fan Speed (PWM Voltage)': Sending state 0.00000 % with 1 decimals of accuracy
[D][climate:378]: 'cabinet-fan Thermostat' - Sending state:
[D][climate:381]: Mode: COOL
[D][climate:383]: Action: IDLE
[D][climate:401]: Current Temperature: 27.56°C
[D][climate:407]: Target Temperature: 30.00°C
[D][sensor:094]: 'cabinet-fan p term': Sending state -43.22857 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan i term': Sending state -0.00000 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan d term': Sending state -0.00000 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan output value': Sending state -43.22857 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan is in deadband': Sending state 0.00000 with 0 decimals of accuracy
[D][sensor:094]: 'cabinet-fan error value': Sending state -2.44095 with 2 decimals of accuracy
[D][sensor:094]: 'Humidity': Sending state 57.00000 % with 0 decimals of accuracy
[D][dht:048]: Got Temperature=27.5°C Humidity=57.1%
[D][sensor:094]: 'Temperature': Sending state 27.55314 °C with 3 decimals of accuracy
[D][sensor:094]: 'Fan Speed (PWM Voltage)': Sending state 0.00000 % with 1 decimals of accuracy
[D][climate:378]: 'cabinet-fan Thermostat' - Sending state:
[D][climate:381]: Mode: COOL
[D][climate:383]: Action: IDLE
[D][climate:401]: Current Temperature: 27.55°C
[D][climate:407]: Target Temperature: 30.00°C
[D][sensor:094]: 'cabinet-fan p term': Sending state -43.40572 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan i term': Sending state -0.00000 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan d term': Sending state -0.00000 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan output value': Sending state -43.40572 % with 2 decimals of accuracy
[D][sensor:094]: 'cabinet-fan is in deadband': Sending state 0.00000 with 0 decimals of accuracy
[D][sensor:094]: 'cabinet-fan error value': Sending state -2.44686 with 2 decimals of accuracy
[D][sensor:094]: 'Humidity': Sending state 57.10000 % with 0 decimals of accuracy

Any further thoughts?

Just for anyone else reading this post later, the above error was a false friend. It was working.. I took a hairdryer to the temp sensor and saw the readings come alive and the fan rpm increase. I just need to calibrate the fan speed correctly in the code

Here is my recommendation. I've not had a chance to test this, but it should work fine.

Buy a logic-level mosfet. I would recommend either the IRLZ44N or FQP30N06L.

The fan's power needs to connect to the Drain pin of the MOSFET. The other side of the, the Source, needs to connect to the 12v power ground.

Connect Fan +ve to MOSFET Drain pin Connect MOSFET Source pin to 12v Power -ve Connect the Gate pin of the MOSFET to any available GPIO pin on the ESP32.

Assuming you use GPIO PIN 25 for the MOSFET gate, your YAML would be as follows:


# this power supply is turned on/off when the output below
# meets the min_power.
power_supply:
  - id: mosfet_power_supply
    pin: GPIO25

output:
  # Wire this pin (13) into the PWM pin of your 12v fan
  # ledc is the name of the pwm output system on an esp32
  - platform: ledc
    id: console_fan_speed
    pin: GPIO13

    power_supply: mosfet_power_supply

    # 25KHz is standard PC fan frequency, minimises buzzing
    frequency: "25000 Hz" 

    # my fans stop working below 13% powerful.
    # also they're  powerful and loud, cap their max speed to 80%
    min_power: 13%
    max_power: 80%

Please test this and if it works, I'll add it to the documentation,

Sorry to seem stupid here but I cant get it to work.

The PWM Signal from the FAn goes to the GPIO13 in your example.
The Gate of the Mosfet goes to GPIO14 in my case.

Mosfet Drain goes to V+ from the fan
Mosfet Source goes to ground from the 12V supply??
Where goes V+ from the 12V supply and where goes the Ground from the fan?

Here is my recommendation. I've not had a chance to test this, but it should work fine.

Buy a logic-level mosfet. I would recommend either the IRLZ44N or FQP30N06L.

The fan's power needs to connect to the Drain pin of the MOSFET. The other side of the, the Source, needs to connect to the 12v power ground.

Connect Fan +ve to MOSFET Drain pin Connect MOSFET Source pin to 12v Power -ve Connect the Gate pin of the MOSFET to any available GPIO pin on the ESP32.

Assuming you use GPIO PIN 25 for the MOSFET gate, your YAML would be as follows:

this power supply is turned on/off when the output below

meets the min_power.

power_supply:

  • id: mosfet_power_supply
pin: GPIO25

output:

Wire this pin (13) into the PWM pin of your 12v fan

ledc is the name of the pwm output system on an esp32

  • platform: ledc
id: console_fan_speed
pin: GPIO13
power_supply: mosfet_power_supply
# 25KHz is standard PC fan frequency, minimises buzzing
frequency: "25000 Hz" 
# my fans stop working below 13% powerful.
# also they're  powerful and loud, cap their max speed to 80%
min_power: 13%
max_power: 80%

Please test this and if it works, I'll add it to the documentation,

Sorry to seem stupid here but I cant get it to work.

The PWM Signal from the FAn goes to the GPIO13 in your example.

The Gate of the Mosfet goes to GPIO14 in my case.

Mosfet Drain goes to V+ from the fan

Mosfet Source goes to ground from the 12V supply??

Where goes V+ from the 12V supply and where goes the Ground from the fan?

@sobrarbe can you offer some advice here since you did seem to get it working?

Hello @patrickcollins12 , in the end I did it with a MOSFET and it worked perfectly. I also had the initiative to buy a PMW fan with an LED light integrated into the fan itself so that depending on the temperature it will change color and be more visual and know more or less the temperature of the closet by seeing the color of the fan. Also to the configuration I added 2 fans with LEDs, one 140mm and the other 120mm to have more air flow. If you need, I gave you my configuration for a PMW fan with LED light.

bfleg commented

Hello @patrickcollins12 , in the end I did it with a MOSFET and it worked perfectly. I also had the initiative to buy a PMW fan with an LED light integrated into the fan itself so that depending on the temperature it will change color and be more visual and know more or less the temperature of the closet by seeing the color of the fan. Also to the configuration I added 2 fans with LEDs, one 140mm and the other 120mm to have more air flow. If you need, I gave you my configuration for a PMW fan with LED light.

Thanks - I think the question that @theslash had, same as mine, is the correct wiring connections to the MOSFET... With the instructions, it doesn't seem right. To me, logically, it should be Drain to Fan -ve pin, thus circuit is +12v rail to +ve fan pin, through fan (load), fan -ve to drain on MOSFET, and when gate has +3.3v, it switches load through to -12v rail, completing the circuit??? Appreciate if you could please confirm - looks like during fiddling I may have cooked my ESP :-(

Thanks, yes -ve to drain.

More below:

Gate: Connect to the ESP32's GPIO (possibly through a small resistor, like 100Ω to 220Ω, for gate drive protection).
Drain: Connect to the negative (or ground) side of the fan.
Source: Connect directly to the circuit ground (0V).

Remember, the ground of the microcontroller should be connected to the same ground as the MOSFET and the fan.

Flyback Diode: It's good practice to place a diode (like the 1N4007) in parallel with the fan, but oriented in such a way that it normally doesn't conduct (anode to the fan's negative terminal and cathode to the fan's positive terminal). This diode will protect the MOSFET from voltage spikes that can occur when the fan is turned off due to inductive kickback.

I updated my original message as well.

bfleg commented

Hmm, looks like I may have cooked my 3rd ESP trying to get the MOSFET solution working, can't see what I'm doing wrong :-( Would have been cheaper to have bought a new fan. Only things connected in to the ESP this time were the DHT, Tach and PWM pins - left the MOSFET gate control out in case there was an issue with the MOSFET. Had previously tested the non-MOSFET version and tach/pwm working fine and also the mosfet standalone too. Can't work out how it's cooking the ESP...
(update: some multi-meter testing shows that when I have it wired through the MOSFET, getting 12v out of the tach and pwm pins - that'll explain it!)

bfleg commented

Hi All, just as an update to the above... Turns out that, I guess, due the internal circuitry of the Arctic 80mm F8 PWM PST fan I'm using (not sure about others) that when you disconnect the ground of the fan (per this N-Channel MOSFET circuit design) the PWM/TACH float up to 12v and kill the ESP. I have had to switch to a dual MOSFET "high side" (1x n-channel, 1x p-channel) circuit that based on current testing without the ESP does not have this issue. Happy to post references if anyone is interested.

Could you add a circuit diagram or describe it? I can add it to the project.

bfleg commented

Definitely...
The solution came from this thread on the Arduino Forum: Arduino Forum
Users herbschwarz and ShermanP in particular, and post 2 (LarryD) in the thread shows a range of circuits, but the final conclusion is circuit ref H1 is where I've landed. I'm pretty confident it'll not kill my ESP this time - but won't find out 'til later in the weekend.
image

(D9 is to the ESP) key point here is it needs to be HIGH SIDE config, which requires P Channel with the gate driven by an N Channel.

Thanks again for the awesome project - looking forward to getting over the finish line and switching it to humidity controlled rather than temp!

Making this mosfet work high side is very complex. Are you sure you couldn't add a simple fly back diode to prevent the float back of power to the esp32?

bfleg commented

...I agree it's very complex, probably too complex - should have just bought a different fan! The flyback won't stop the issue though. Annoyingly, the circuit and fan control is now working just fine (in the above config), but the fan has stopped reporting tach for some reason - even when put back in your original design mode. grrr, shoulda bought a different fan!

As a beginner I'm a bit lost. Is there a clear solution for this? Preferable with schema and a component list. I know I ask a lot!

Please describe your problem @BasJansen . There have been recent fixes in the yaml file which should prevent this problem

The fix you mean is "zero_means_zero: true"? That still keeps my fan spinning. So I want to stop it and need to use a MOSFET I guess. I try to follow your recommendation but got confused and even got more confused with the later responses, I know a lot of roads lead to Rome but for me I just want to get there. Also in your recommendation you wrote "The other side of the, the Source, needs to connect to the 12v power ground." I guess you talk about the fan. Also nobody confirmed it working. Anyway don't get me wrong I really like your project! Just wished I could finish it and I feel stupid.

Hi Bas, my circuit kinda ended up working but somewhere along the way, the fan stopped reporting the tach speed! Figured it was also “broken”. Which for me was a problem, then my Mother-In-Law dumped her keys on my desk and when she scooped them up, along with a handful of jumper wires, I somehow lost ANOTHER ESP!! Bought a new couple of fans that are supposed to stop on zero, but have not revisited yet. Now winter is coming, for my use case, I will in the coming weeks…
But, I can confirm the circuit I posted above DOES work from a stop / start perspective…

Thanks for the reply. Always blame your mother in law... I will use the scheme but what parts should I buy for Q22, Q23? Do you know what works? D16 is a diode and I have a few, is there something I should check with it.

OK bummer I was hoping the zeromeanszero patch would have fixed this issue... it's clearly an issue with some fans. Would be happy to accept documentation if you get it working.

Arctic P12 PST 0dB

bought one today, in the specs it has 300-2100 rpm
0rpm <5% PWW

in my config i have specified min_power: 0 and zero_means_zero.
with the switch off in HA, it still runs around 800 RPM ...

I'll buy one to replicate and come up with a solution.

I'll buy one to replicate and come up with a solution.

Great !

I found that exact fan for $12AUD

OK, so I have two fans, I unplugged one and plugged in the Arctic P12 Slim PWM PST.
It stopped spinning at 0 power for me.

Untitled.mov
image

@DeDiConsulting I suspect there might be something wrong with your circuit. Like for instance, joining the two ground lines together. The 12v and 5v lines need to be earthed together. If that's not the issue can you share your circuit with a diagram and photo?

oh oooh ... i think i forgot to join the ground of the 12V & the 5V.
i will check this tomorrow ....

i can confirm, my bad.
as i was firing up the esp8266 from usb, from other power source, i forgot to join the grounds.
Once i did this, its working fine! doh... how could i forget that ....
Many thanks to everyone who jumped in right away

I'm actually glad the solution was that simple because a lot of people have had this issue. I'm also glad that people don't have to add a mosfet because that impacts the simplicity of this project.

How can we adjust the instructions to be much clearer on this topic? Feel free to suggest or make a pull request.

I have my Corsair fan now replaced with an Arctic above and it just works. So I guess some people still need a mosfet solution but you can always buy this affordable fan.

@BasJansen any chance you can test both fans with and without the grounds connected?

I tested both fans with and without ground connected. There seems to be no difference in behavior with or without.
Corsair fan: always spins, even when the esp32 did not totally boot. In the web interface I can switch it on and can speed it up or slow it down but not stop it.
Arctic fan: stays off until I switch it on in the web interface. In the web interface I can speed it up and down.

We're all getting inconsistent results. My Corsair works fine. @DeDiConsulting arctic keeps spinning, but works when grounded properly.

664 RPM wich NXZT 140mm fan 🥴 I'll test with another fan...

550RPM with NZXT 120mm. Have to buy the mosfet. :/

Here is my recommendation. It should work fine.

Buy a logic-level mosfet. I would recommend either the IRLZ44N or FQP30N06L.

The fan's power needs to connect to the Drain pin of the MOSFET. The other side of the, the Source, needs to connect to the 12v power ground.

Gate: Connect to the ESP32's GPIO (possibly through a small resistor, like 100Ω to 220Ω, for gate drive protection). Drain: Connect to the negative (or ground) side of the fan. Source: Connect directly to the circuit ground (0V).

Remember, the ground of the microcontroller should be connected to the same ground as the MOSFET and the fan.

Flyback Diode: It's good practice to place a diode (like the 1N4007) in parallel with the fan, but oriented in such a way that it normally doesn't conduct (anode to the fan's negative terminal and cathode to the fan's positive terminal). This diode will protect the MOSFET from voltage spikes that can occur when the fan is turned off due to inductive kickback.

Assuming you use GPIO PIN 25 for the MOSFET gate, your YAML would be as follows:


# this power supply is turned on/off when the output below
# meets the min_power.
power_supply:
  - id: mosfet_power_supply
    pin: GPIO25

output:
  # Wire this pin (13) into the PWM pin of your 12v fan
  # ledc is the name of the pwm output system on an esp32
  - platform: ledc
    id: console_fan_speed
    pin: GPIO13

    power_supply: mosfet_power_supply

    # 25KHz is standard PC fan frequency, minimises buzzing
    frequency: "25000 Hz" 

    # my fans stop working below 13% powerful.
    # also they're  powerful and loud, cap their max speed to 80%
    min_power: 13%
    max_power: 80%

Please test this and if it works, I'll add it to the documentation,

adds a graphical scheme for electronics newbies :D

I don't think this works. The fan has no 12V + power and also the diode is not there.
What I understand (and I'm totally new to this so I might be totally wrong) the diode is only needed for some extra protection. When the power switches of the fan it will still spins and if a motor spins it generates power and this power shouldn't go to your esp32 board. But I also don't understand how the fan will get it's 12v power and how the Mosfet should be connected (sorry mainmind83)

Doesn't look right, nothing connecting the mosfet to 12v. I won't have a chance to build and test this got a while. I suggest someone has a go and sends back the fritzing diagram that works

Did I understand this correct?

@corgan2222 please hide wrong scheme 🙄😉

I gave up on the Mosfet approach and now use a simple relay like this guy
https://www.speaktothegeek.co.uk/2023/01/esphome-fan-v3-variable-speed-pwm-and-temperature-control/
For my usecase this works fine, because I use this fan in my cellar. But, I can imagine, that the clicking of the relay may be too loud for a living room installation.

I think I now know how it can be done. Please keep in mind I'm a noob, Don't know anything about electronics and all credits go to https://electronics.stackexchange.com/users/68839/sergiu-reznicencu for his answer in tread https://electronics.stackexchange.com/questions/521154/verifying-schematic-idea-circuit-design-for-mosfet-driven-by-esp32.

I made 2 projects. First one for a fan which stops by itself (faneasy) and one that uses a Mosfet to stop the fan (fanhard).
So check the easy project first and if the fan keeps spinning go for the mosfet solution.

Faneasy

image

It uses this code

substitutions:  
  PIN_PWM:   GPIO26    # Green          
  PIN_Tach:  GPIO25    # Blue        

esphome:
  name: faneasy

esp32:
  board: esp32dev

logger:  

api:

ota:
  platform: esphome

wifi:
  # Read the wifi/pass from secrets.yaml:
  # wifi_ssid: "My Wifi XX"
  # wifi_password: "XXXXXXX"
  ssid: !secret wifi_ssid
  password: !secret wifi_password  
  fast_connect: true
  power_save_mode: NONE

web_server:  

sensor:  
  # Read the Tacho PIN and show measured RPM as a sensor (only with 4-pin PWM fans!)
  - platform: pulse_counter
    id: fan_speed
    name: Fan Speed
    pin: 
      number: $PIN_Tach   # Connect to any input PIN on the ESP
      mode: INPUT_PULLUP    
    unit_of_measurement: 'RPM'
    update_interval: 5s         
    accuracy_decimals: 0
    filters:
      - multiply: 0.5  # Depending on how many pulses the fan sends per round - should be 0.5 or 1 - try... 

output:
  # ledc is the name of the pwm output system on an esp32
  - platform: ledc
    id: PWM_output
    pin: $PIN_PWM
    # 25KHz is standard PC fan frequency, minimises buzzing
    frequency: "25000 Hz"     
    zero_means_zero: true 

fan:
  - platform: speed
    id: fan_1
    output: PWM_output
    name: "Fan"     

Fanhard

image

ps: the original schema uses a resistor of 110 Ohm but I didn't have one so I used a 220 Ohm and it still works.

substitutions:  
  PIN_PWM:   GPIO26    # Green          
  PIN_Tach:  GPIO25    # Blue      
  PIN_ONOFF: GPIO33    # Orange

esphome:
  name: fanhard

esp32:
  board: esp32dev

logger:  

api:

ota:
  platform: esphome

wifi:  
  ssid: !secret wifi_ssid
  password: !secret wifi_password  
  fast_connect: true
  power_save_mode: NONE

web_server:  

sensor:    
  - platform: pulse_counter
    id: fan_speed
    name: Fan Speed
    pin: 
      number: $PIN_Tach   # Connect to any input PIN on the ESP
      mode: INPUT_PULLUP    
    unit_of_measurement: 'RPM'
    update_interval: 5s         
    accuracy_decimals: 0
    filters:
      - multiply: 0.5  # Depending on how many pulses the fan sends per round - should be 0.5 or 1 - try... 

output:  
  # ledc is the name of the pwm output system on an esp32
  - platform: ledc
    id: PWM_output
    pin: $PIN_PWM
    # 25KHz is standard PC fan frequency, minimises buzzing
    frequency: "25000 Hz"     
    zero_means_zero: true

  - platform: gpio
    pin: $PIN_ONOFF
    id: 'OnOffFan'  

fan:
  - platform: speed
    id: manual_fan_control
    output: PWM_output
    name: "Fan"
    on_turn_on:    
    - output.turn_on: OnOffFan
    on_turn_off:    
    - output.turn_off: OnOffFan

Please let me know if something can be improved.

I have these components, I will test it and publish it.

Did you know also with this schema you can use the mosfet as the pwm and you don't need a pwm fan. Could be helpful for people who have a 3-pin fan sitting around.