PWM Fan Controller

@Stu1811 I do not think the GPIO pin will survive 12v for very long. The tachometer is an open collector and is pulled down to the ground on pulse and floating otherwise, hence the required pullup at GPIO side.
With 3.3v, the internal pullup is a lot safer.

I’m building this myself and curious to understand your comment about the 12v a bit more. Are you referring to the voltage the Tach is sending in pulses?

I just tried to test this and never saw anything over a couple of hundred millivolts, although I’m not 100% sure my testing was correct.

I cant quite get the RPM sensor working as well which is confusing me.

My recommendation about the project though would be to strip out any automation from the controller. I move all my automation into NodeRed via HA. I have complete control that way and the programs need little tweaking if ever.

Tried the multi sensor doing lots of things and found it unreliable and full of bugs. Simple is best!

I’m about to build this and was a bit baffled by your comment. Could you explain it further for those of us on the learning curve.

I would be especialy interested in a proposed solution if there is a problem,.

Thanks for any help offered

1 Like

Why is there a 10k resistor between the tacho and 12V?

Uummm…I just can’t get over this. someone made this and it has the documentation, configuration , instructions and whatever else but you can’t get it working. You then make a public service announcement that you aren’t sure why this sensor wasn’t working , but I Checked whatever this here PWM pin thing is and my meter… ya, it ain’t working right now, it’s showing a couple milivolts but, I’m not sure what I’m measuring anyway. So clearly this is because of esphome, I’m gonna quit so should everyone else and let’s go to Node Red and rebuild it from scratch!
I’m sorry man it just cracked me up. I can’t stress this enough! You need to look at data sheets (aka the instruction manual). You would have know that sensor wasn’t going to work untill you added the reccomend pullup resistor ( pullup/down resistors they don’t have anything to do with voltage or reducing voltage. They limit how much current (a) can pass through it. All of this was in that data sheet, it even tells you how to calibrate the sensors and speeds, it tells you the fan logic is inverted, so if you wanted fan speed at HIGH(100%) the gpio (inverted)needs to be OFF(0.0v) so it explains what PWM is and how it changes the speed all that fun stuff to. Read those data sheets, .man. When you understand how something works or if there’s specific details you need to be aware of , I promise it will change your whole game and cut your troubleshooting times and irritation factor way down.

I think my comment maybe slightly unclear/incomplete so I will try to do better.

ESPHome is working great for me. In this instance I used what @Stu1811 has created as a good base (Thanks again for that!) and modified it to fit my needs/wants. I had a few questions going into it though and I was looking for some help to understand some weirdness I was seeing. My testing wasn’t that in-depth and felt understanding the comments about the voltages, pull up/down resistors etc may help me to see what and how I should testing.

Now I still get unusual readings for RPM with only two exceptions. 100% and 0%. They read correctly as per the fans documented speeds but anywhere in between I get readings higher than 100% or that don’t register at all when they should be. For what its worth its a small problem and I rarely run the fan at anything less than 100% anyway.

My suggestion with NodeRed is to remove only the automation from the device. Let ESPHome read sensors and control things when told to and allow NodeRed/HA to control when to do things based on those sensors. Minimizes code and means you can edit parameters without re-programming it each time you want to change it.

With regards to this project I refer to the section that says when temperature is above X turn fan on, and when below X turn fan off. Wouldn’t it be good to be able to edit those temperature limits from the same place you can monitor the fan from? Tis merely a suggestion. Each to their own. My preference is to let the software built for automation do the automation.

Thanks again for your comment and to @Stu1811 for putting in the work to share their hard work :slight_smile:

Sharing what your using, a link to the project, your fan config, how your getting RPM, is it a sensor or is somehow calculated from somewhere else? Your question was a little confusing but that’s not unusual. Posting actual data, links, config, etc that’s how confusion is minimized and someone can actually help. No details then people are just going to take guesses or ask you for the information that should have been attached to the initial post.

I’m not picking on you or anything, I’m just saying for future reference. Adding one or a couple of these things, pictures, a config, a link and then a to the point description of the problem would have been more helpful than a 3 or 4 paragraph thing. All that extra stuff over multiple paragraphs, it makes it more confusing a lot of the time. I really mean no offense but, you put some time and a few minutes into that post and it’s obvious you meant well and you tried but, it’s all mostly not important, not useful and now confusing.

Would you be talking about a server rack ran controller with rpm sensor?

Thanks for this code, it’s just what i need, but…i’d like it to work with a dallas sensor instead. I’ve tried but just cannot get it to work. Would anyone be so kind as to post up the code, but for a dallas sensor instead of a dht ?

Thank you in advance
Lee

Go look at the documentation , it explains how to do it. You gotta be a big boy and make an effort.

I already done it. I’m sorry but I forgot to post up to say so.
Thank you so much for your reply, it means the world to me

This is ace.
Am going to do this.
I have three NF-F12 Industrial 3000RPM fans.
If I were to extend this circuit for controlling the three fans individually, I assume:

  • Add PWM & RPM for Fan 2 to D3 and D4
  • Add PWM & RPM for Fan 3 to D5 and D6
  • Would need 2 extra 10k Resistors
  • would keep the single DHT11

Rather old thread but I still like to add, that based on what I read here and elsewhere I also did my fan controller to upgrade my deye inverter (remove the noise). You can find my code here: GitHub - sker65/esphome-fan-controller: Yet another esphome based fan controller. Can be controlled either manually or by temperature sensor.

From my point of view the code is cleaner (simple linear temperatur characteristics), simple switch between manual and temp controlled, optional MOSFET to turn the fans off. See some more comments on the githubwiring

1 Like

Just clarifying it a little bit about what @fr8tra1n said about the 12V:

The OP said he was using a 10KΩ resistor from the 12V to the fan tachometer pin. This pin is also connected to the ESP8266, which he assumed, correctly, won’t survive to be exposed to 12V very long.

Quick clarification: the tachometer is not “sending pulses”. The line is always UP (12V), and the tachometer connects it to ground (GND) 2 times per revolution. Yeah, it’s “sending pulses” in the sense that the line is always at 12V (pulled up by the pull-up 10KΩ resistor) and those “pulses” are 0V (GND).

The tachometer may not work correctly with a lower voltage, let’s say, 3.3V, because, as the OP said before, the RPM readings were not accurate.

I’ve seen people trying to use a voltage divider (other 2 resistors) to bring the 12V line down to 3.3V, a voltage that the ESP8266 can stand, before reaching the ESP8266 pin. I didn’t test it yet but, in principle, it should work. These voltage dividers can be configured in many ways and there are many calculators on the web that you can use for helping with that. For example:

Voltage Divider Conversion Calculator | DigiKey

You can use, let’s say, a 27KΩ resistor for R1 and a 10KΩ resistor for R2, bringing the 12V input to 3.2V.

The formula is simple:
Vin / (R1 + R2) * R2 or, in our case, 12V / (27KΩ + 10KΩ) * 10KΩ which gives us 3.24V

Notice that Ohm’s Law (I = V / R) units are still obeyed in this formula. So, when we divide V / (R1 + R2), we have the current (I). But then we multiply it by R2, and I * R = V, so having our result in volts (V) is correct.

1 Like

Then someone have try to use two resistors? Do you have exact value and schematic?
I am newbie

Is right this schematic, vin as output of tachimeter fan, and vout to D1 mini ?

Thank you for the great code. It was extremely helpful, not only for managing my fan but also for clarifying many things in ESPhome.

In my system it spins almost at a maximum speed of 1700 rpm, whereas the specification is 1800 rpm. I’m using an Arctic 120mm PWM fan with a 560R resistor at 3.3v.

This is the way was realized in Arduino and I directly used it in ESPhome."

Hi,
i have a problem with the Fan control. If i start the ESP8266, the Controller won’t work. The only thing who works is the function, when i turnend on and off the overridet function.

Can anyone help me?

  - platform: bmp280
    temperature:
      name: "Temperature"
      id: rack_fan_temperature
      oversampling: 16x
      accuracy_decimals: 1
      on_value_range:
        - above: 40.0
          then:
            if:
              condition:
                fan.is_off: rack_fan_toggle
              then:
              - logger.log: "Set fan level 100 over 40C"
              - output.set_level:
                  id: rack_fan_speed
                  level: 100%
        - above: 30.0
          then:
            if:
              condition:
                fan.is_off: rack_fan_toggle
              then:
              - logger.log: "Set fan level 66 over 30C"
              - output.set_level:
                  id: rack_fan_speed
                  level: 66%
        - above: 20.0
          then:
            if:
              condition:
                fan.is_off: rack_fan_toggle
              then:
              - logger.log: "Set fan level 33 over 20C"
              - output.set_level:
                  id: rack_fan_speed
                  level: 33%
        - below: 20.0
          then:
            if:
              condition:
                fan.is_off: rack_fan_toggle
              then:
              - logger.log: "Set fan level 15 under 20C"
              - output.set_level:
                  id: rack_fan_speed
                  level: 15%

And when the temperature decreases. E.g. from 30 to 25 °C, the fan doesn’t reduce the speed in accordance with the given % values.

I found this thread (and many others) very helpful, so I wanted to share my current solution for a 4-Pin PWM Fan controller with speed monitoring and a temperature sensor. This is to go into a cupboard where I want to put a NAS and mini-server but need to increase the airflow for cooling.

ESPHome YAML Code
esphome:
  name: fancontroller01
  friendly_name: fancontroller01

esp8266:
  board: esp01_1m

dallas:
  - pin: GPIO5 #D1
    update_interval: 10s #Low Interval for DEBUGGING

# Enable logging
logger:
  
# Enable Home Assistant API
api:
  encryption:
    key: "VeryLongAndVeryRandomisedMagicEncryptionKey="

ota:
  password: "SuperSecureHighlySecretPassword1"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  # Static IP
  manual_ip:
    static_ip: 192.168.0.11
    gateway: 192.168.0.1
    subnet: 255.255.255.0

captive_portal:

# Notes on Pins
# FanPin1 | "Black" | Gnd                      | 
# FanPin2 | "Red"   | +12v                     | 
# FanPin3 | "Green" | RPM Signal/Sense/Tach    | Pin D7 = GPIO13
# FanPin4 | "Blue"  | PWM Control Signal (+5v) | Pin D6 = GPIO12

sensor:
  # Send WiFi signal strength & uptime to HA                                                                                                                                                                                             
  - platform: wifi_signal
    name: WiFi Strength
    update_interval: 10s #Low Interval for DEBUGGING

  # RPM Signal from Fan                                                                                                                                                                                                                  
  - platform: pulse_counter
    pin: GPIO13 #D7
    name: RPM Signal
    id: fan_RPM_pulse
    unit_of_measurement: 'RPM'
    filters:
      - multiply: 0.5
    count_mode:
      rising_edge: INCREMENT
      falling_edge: DISABLE
    update_interval: 10s #Low Interval for DEBUGGING

  - platform: dallas
    address: 0x9400000000000000
    name: Temp01

output:
  - platform: esp8266_pwm
    id: fan_speed
    pin: GPIO12 #D6
    frequency: "25000 Hz"
    min_power: 10%
    max_power: 100%

fan:
  - platform: speed
    output: fan_speed
    speed_count: 10
    name: fan speed control
    id: fan_speed_toggle


The 2nd fan piggy-backs off the first with an included daisy-chain cable and I don’t need independent control of them.

I used a power module like this (Similar AliExpress Link) so I could pull both 12v and 3.3V/5V off a single power supply.

I still have a few things I want to do to it before installing:

  • Add 2nd temperature sensor (2 shelves/zones)
  • Code temp>speed (need to get in place and monitor to work out the right levels first) rather than HA Manual Control
  • Add code to send data into InfluxDB

Hi,

You might like to look at the post I wrote at 4-pin fan with d1mini and esphome: how to read current rpm of the fan? - #18 by MrFusion

I go over the spec for 4-wire fans and how to connect an ESP.

The Tacho output of the fan is (according to the spec meant to be) open collector/open drain. This means that the output is switched between being tied to ground and floating - which in turn means that you then need a pull-up resistor in order to reliably read the output (ie Tacho out ↔ GPIO input has a resistor to a positive supply).

Unfortunately, tying this to 12v can be problematic. Espressif’s official position is never feed any pin with more than 3.3V (see, for instance this post by ESP_Sprite).

The only reason that tying it to 12V hasn’t fried your ESP is generally more down to good luck than good planning. You’re actually relying on the ESP’s built-in ESD protection diodes (plus any other parasitic loads on the pin in questions) to carry the load whenever the Tacho output is ‘high’ (ie output floats so power going to the GPIO pin is coming via the pull-up resistor). This is generally not a great idea as the protection diodes generally can only carry a very small current, plus you don’t really know or have any control of what protection is in place per GPIO (and with ESPs there’s sometimes less than you would like on some pins…).

The way it works in this case (assuming a 10k pull-up) is that, when output is high:

  • Power flows from 12V rail through the pull-up resistor to the GPIO pin
  • Internally the voltage is seen by the input as well as the anode of the protection diode which then shunts the angry pixies through to the ESP’s internal positive supply rail
  • This looks like 12V → 10kOhm → junction of chip input and >diode> → 3.3v
  • Chip input is ‘high-Z’ (unless you’ve set internal pull-up or pull-down)
  • Forward bias voltage of the diode is approximately 0.7V

So

  • the voltage at the junction of chip input and diode is approximately 3.3-0.7 = 2.6V
  • therefore the voltage drop across the pull-up resistor is 12 - 2.6V = 9.4V
  • therefore the current flowing through the resistor & diode is 9.4V / 10,000 Ohms = is about 9.4mA… let’s call it 10mA

And 10mA is right at the limit of what many on-die ESD diodes can carry for any sustained period of time.

These numbers are just approximate but easy enough to be more precise - measure with a multimeter:

  • Power up the ESP & fan, and then stall the fan at a point where the Tacho output is high (or you could just connect the resistor directly between 12v and GPIO and leave the fan out of it - but I recommend involving the fan as well because you then have a chance to discover how well the fan actually implements the spec, or if it maybe has it’s own pull-up resistor, etc, etc)
  • Measure the voltage present at the ESP GPIO pin (guesstimate is 2.6V but could be quite a bit higher or lower)
  • Measure the pull-up resistor’s actual resistance
  • Re-do the calcs

Suggestions:

  • The ‘best’ (and recommended by Espressif as well as, tangentially, by Intel) - simply power the 10k pull-up resistor via the 3.3V line instead of 12V. Downsides - for many & varied reasons (usually related to the fan tacho’s implementation) the ESP may not see a clear enough signal & this might require a scope to diagnose & resolve
  • Alternative ‘best’ - feed direct from Tacho to GPIO (with no other components) and set GPIO mode to INPUT_PULLUP
  • Second ‘best’ - implement additional components at the GPIO input to guarantee voltage never goes above 3.3V (along with the 10k pull-up resistor, a 3V zener to ground & a schottky to positive should do it)
  • Third ‘best’ - increase the pull-up resistor value. Try, for instance, 100k or more to bring the current through the built-in ESD diode right down

Hope this all makes sense & that someone finds it helpful!

Hi,

I would like to recreate this. The temperature and humidity are good and when I connect a Cooler Master fan the control is perfect.

But I need a bigger fan. I have an Arctic F12 PWN. But if I want to control this fan, I can’t do that. The fan is always on.

Can someone help me?

Thanks