4-pin fan with d1mini and esphome: how to read current rpm of the fan?

Hi,

4 Pin PC fans vary in their implementation for many reasons, including some variation in the motherboard spec (p9) that they’re meant to adhere to. Some implementations will fry the GPIO pin on your ESP outputting the PWM signal unless you implement protection…

The spec calls for:

  • Tacho output from Fan → PC
    • Two pulses per revolution
    • Open collector / open drain
      • collector/drain relates to the type of transistor (BJT or FET) sending the signal
      • basically means that the pin that you’re measuring is either connected to ground or left ‘floating’ (or ‘high Z’)
      • the sensing device should provide the active pull-up
    • Pull-up resistor to be such value that the BJT/FET sees 12v, max 12.6v when it is floating
      • Depending on the fan implementation, you may possibly experience some issues if the pull-up voltage is significantly less (ie 3.3v) - YMMV but generally it works ok (especially for newer fans)
      • You can simply set your GPIO pin to input / pull-up & it will generally work ok
      • A good way to test without oscilloscope but with volt meter -
        • setup and connect your ESP input GPIO to the fan’s Tacho output
        • connect multimeter, V measure, between ground and Tacho output
        • block the fan from rotating & then turn on the fan
        • rotate the fan slowly by hand and you should see a) measured voltage switch clearly between ~3.2v and 0v twice per rotation, and b) ESP should report the transitions

Now for the tricky bit…

  • PWM input from PC → Fan
    • The spec assumes that the device providing the PWM signal is also operating in open collector / open drain mode. Therefore it calls for a pull-up resistor within the fan - such pull-up to be no more than 5.25v (which can fry an ESP)
      • The spec does note, however, that it strongly encourages new fan designs to implement a max 3.3v pull-up specifically to avoid this kind of issue (ESP not being the only device that can get fried)
    • So, best thing to do before connecting the ESP PWM output to the fan - power up the fan and measure the voltage present at the fan’s PWM input pin.
      • If it’s above 3.3v then you’re gonna need protection
      • if it’s ~3.3v or below (but above about 1v) you are good to go — simply set the GPIO output mode to OUTPUT_OPEN_DRAIN, connect directly to the fan’s PWM input, and start sending that sweet 25kHz PWM signal :slight_smile:
      • If it’s zero volts then there’s a chance that the fan is not providing the pull-up & you’re going to have to do that yourself.
        • You can simply add a resistor (1k - 10k should be fine) from ESP 3.3v to the join of Fan PWM input and ESP PWM output (to provide the pull-up), and again set GPIO output mode to OUTPUT_OPEN_DRAIN
        • You could also potentially just drive it directly with push-pull mode (simply OUTPUT mode & only connect the GPIO to the PWM input) — but there is some risk that this may damage the ESP if the fan draws too much current when the ESP output is HIGH. A small current limiting resistor should be sufficient to protect the ESP - but you’ve then also got to check that when the ESP is LOW that the voltage on the fan’s PWM input pin falls below the zero threshold voltage (according to spec this is 0.8v). So you’ll need to tweak the resistor such that HIGH output is less current than the ESP can drive, and so that LOW output results in a sufficiently low voltage that the fan sees it as a logic state transition

If you need protection because the fan’s pull-up voltage is > 3.3v, then a simple transistor should be sufficient (plus small current limiting resistor from GPIO to transistor’s base, and maybe a pull-up resistor on the PWM input if necessary). Don’t forget to invert the ESP output if necessary.

Who would have thought that something so simple could be made so difficult huh? :rofl:

4 Likes