Reading fan tacho signal frequency?

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
Empusas
Posts: 3
Joined: Sun Oct 06, 2019 3:30 pm

Reading fan tacho signal frequency?

Post by Empusas » Tue Oct 08, 2019 10:08 am

Hi,

I want to use my ESP32 also to control the fan speed of my PC water cooling system. I am using LoBo´s precompiled micropython as I need the SSH client for another task in the system.
I think I have everything I need, except I don't know how to read the fan speed.

I will use an analog in to read the current water temperature with a sensor in the system. The ADC module will be used for that.
So the fans I am using are 4 pin PWM controlled fans. You supply 12 volts to the fans and can directly attach the fan PWM control to the ESP32. So I will be using the PWM module to control the fan speed with a 25KHz PWM signal.
But each fan has also a tacho signal to check the current speed and if it is working. From some arduino examples I know that GPIO18/V_SPI_CLK is used for that.

Is there only GPIO18 that can be used for that? And how to use it in micropython?

OutoftheBOTS_
Posts: 780
Joined: Mon Nov 20, 2017 10:18 am

Re: Reading fan tacho signal frequency?

Post by OutoftheBOTS_ » Tue Oct 08, 2019 10:49 am

A bit of googling shows the tacho pin (yellow wire) is a 5v signal that gets 1 high - low signal per revolution. You will need to add a voltage divider to connect to a ESP32 as they are not 5v tolerant and need voltages below 3.6v.

I do remember on another thread on this forum a discussion of a peripheral the ESP32 has that is designed for counting tach pulses just like this but it hadn't yet been implemented in Micro-python. It would be possible to use software to count the pulses alothough less efficient. I believe most fans are in the vicinity of 25KHz

Empusas
Posts: 3
Joined: Sun Oct 06, 2019 3:30 pm

Re: Reading fan tacho signal frequency?

Post by Empusas » Tue Oct 08, 2019 4:33 pm

Well, the tacho signal is an open drain output, that does introduce any voltage in the system.
You can use a 10KΩ pull up resistor to 3.3Vcc and a 3.3V z-diode connected to ground as voltage divider to limit the tacho signal voltage to 3.3V max.

Noctua provides a white paper on more details about the PWM and the tacho signal:

https://noctua.at/media/wysiwyg/Noctua_ ... _paper.pdf

And the frequency is proportional to the rpm. The 25KHz is not the tacho signal frequency, just the recommended PWM frequency because of noise canceling reasons.
You get 2 pulses from the hall sensor per rotation of the fan. The max RPM of the NF-F12 I use is 1500RPM which translates into 50Hz.
fan speed [rpm] = frequency [Hz] × 60 ÷ 2
1500 rpm = 50 Hz *60 ÷ 2

I would image that it is not that hard to implement an input that can measure up to 50Hz, but I am not the expert on that.

The PWM signal on the other hand might require some verification of the voltage. As the fan usually has a pull up resistor to 5V inside.
But Intel recommended already in 2004 in their specification to rather use a pull up to 3.3V instead. Noctua is not 100% clear in their documentation as it shows 5V everywhere, but in one sport hey say "External pull-up is not necessary as the signal is pulled up to 3,3V/5V inside the fan." But this problem could be also solved, if it really is 5V. And this could be verified with a simple multimeter.

User avatar
Roberthh
Posts: 2000
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Reading fan tacho signal frequency?

Post by Roberthh » Tue Oct 08, 2019 7:44 pm

If the output is open drain, then you can use a pull-up to 3.3V. 50 Hz aka 20ms is also not an issue. You can use a PIN IRQ, which triggers on every falling edge, and take the time between transitions using utime.ticks_us(). The pin IRQ on ESP32 has a substantial jitter, so you should average or lowpass the result. A first order lowpass is easier, because you only have to remember a single value, which is also the result.

pidou46
Posts: 68
Joined: Sat May 28, 2016 7:01 pm

Re: Reading fan tacho signal frequency?

Post by pidou46 » Tue Oct 15, 2019 1:58 pm

what I have understand is that esp are not very good at counting pulses.
I have an idea, but my knoledge in electronic design is very low, so please tell me if it's pratical:
wiring the pulse output to a capacitor and a resistor, so the pulse will fill the capacitor and resistor will burn this energy at slow rate. This way we can sense the voltage with ADC input of the ESP and convert it to RPM.
Is there a chance to get this work?
How to choose the capacitor and resistor value ?
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

User avatar
Roberthh
Posts: 2000
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Reading fan tacho signal frequency?

Post by Roberthh » Tue Oct 15, 2019 2:03 pm

That would most likely be worse than just measuring the pulse duration with an IRQ, which gives you an error of < 1%. You never told how precise it has to be. Obviously, when you assume a RC element, then the response time is not critical. So you can use filtering for the time measurement to increase precision.

OutoftheBOTS_
Posts: 780
Joined: Mon Nov 20, 2017 10:18 am

Re: Reading fan tacho signal frequency?

Post by OutoftheBOTS_ » Tue Oct 15, 2019 8:47 pm

AS Roberthh has said you can use interrupts then count with software and you will achieve a good results.

The ESP32 does have a hardware peripheral designed to do exactly this which doesn't use any CPU load. see https://docs.espressif.com/projects/esp ... /pcnt.html then you can use a timer interrupt that calculates the RPM bases upon how many ticks counted between each timer interrupt. This would be very low CPU load and very high accuracy. The down side is that this peripheral has been implemented in micropython yet so you will have to just wrap up the needed fuction from the IDF so they can be called from Micropython.

User avatar
MostlyHarmless
Posts: 147
Joined: Thu Nov 21, 2019 6:25 pm
Location: Pennsylvania, USA

Re: Reading fan tacho signal frequency?

Post by MostlyHarmless » Fri Nov 22, 2019 2:30 am

That link currently leads to a 404.

Here is one that probably works ATM: https://docs.espressif.com/projects/esp ... /pcnt.html

Strik3r
Posts: 14
Joined: Thu Nov 28, 2019 7:36 pm
Location: Saratov, Russia

Re: Reading fan tacho signal frequency?

Post by Strik3r » Wed Jan 22, 2020 6:08 pm

Empusas wrote:
Tue Oct 08, 2019 10:08 am
I want to use my ESP32 also to control the fan speed of my PC water cooling system. I am using LoBo´s precompiled micropython as I need the SSH client for another task in the system.
I think I have everything I need, except I don't know how to read the fan speed.
I have same problem. Today i made this code, and it works fine for frequencies under 450Hz (if i understand all right - tachosignal must be less than 150Hz):

Code: Select all

def msr():
    global freq
    old_freq = ''
    while True:
        if freq != old_freq:
            pwm = PWM(Pin(12), freq=freq, duty=50, timer=3)
            measure = Pin(14, Pin.IN, Pin.PULL_DOWN)
            frequency, count = 0, 0
            old_value = 0
            while count < 1000:
                measurement = measure.value()
                if measurement:
                    if not old_value:
                        frequency += 1
                        old_value = measurement
                    elif old_value:
                        old_value = measurement
                else:
                    old_value = measurement
                utime.sleep_us(1000)
                count += 1
            freq_rounded1 = round(frequency*0.92/10)*10
            freq_rounded2 = round(frequency*0.92)
            pwm.deinit()
            print('Generator freq: {0}, Measured rounded freq: {1} (Original measured: {3}, Rounding to ten : {2})'.format(pwm.freq(), freq_rounded2, freq_rounded1, frequency))
        old_freq = freq
        utime.sleep(1)
the result of it you can see on picture (RPM measurements for Deepcool UF120, witch have 500/1500rpm min/max in pasport, so, its seems to work well).
freq_measure.jpg
freq_measure.jpg (271.33 KiB) Viewed 471 times
uf120_measure3.jpg
uf120_measure3.jpg (162.01 KiB) Viewed 463 times
IMG_01552.jpg
IMG_01552.jpg (232.04 KiB) Viewed 463 times
but i don't mind to find a better solution.
Roberthh wrote:
Tue Oct 08, 2019 7:44 pm
You can use a PIN IRQ, which triggers on every falling edge, and take the time between transitions using utime.ticks_us().
Can yon give any examples, how it must looks like?
I tried few constructions with IRQ triggers like:

Code: Select all

p = Pin(14, Pin.IN, Pin.PULL_DOWN, handler=handlr(), trigger=Pin.IRQ_HILEVEL)
but it dont work. Maybe its so on lobo rom?

Here is Pin page of lobo:
https://github.com/loboris/MicroPython_ ... o/wiki/pin
What it means:
Warning: if the level interrupt is selected, the interrupt will be disabled before the interrupt function is executed and must be explicitly enabled in interrupt function if needed
and where i can find interrupt function?

Post Reply