Reading fan tacho signal frequency?
Reading fan tacho signal frequency?
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?
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?
-
- Posts: 847
- Joined: Mon Nov 20, 2017 10:18 am
Re: Reading fan tacho signal frequency?
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
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
Re: Reading fan tacho signal frequency?
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.
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.
Re: Reading fan tacho signal frequency?
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.
Re: Reading fan tacho signal frequency?
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 ?
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
micropython firmware Daily build 05/31/2016
Re: Reading fan tacho signal frequency?
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.
-
- Posts: 847
- Joined: Mon Nov 20, 2017 10:18 am
Re: Reading fan tacho signal frequency?
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.
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.
- MostlyHarmless
- Posts: 166
- Joined: Thu Nov 21, 2019 6:25 pm
- Location: Pennsylvania, USA
Re: Reading fan tacho signal frequency?
That link currently leads to a 404.
Here is one that probably works ATM: https://docs.espressif.com/projects/esp ... /pcnt.html
Here is one that probably works ATM: https://docs.espressif.com/projects/esp ... /pcnt.html
Re: Reading fan tacho signal frequency?
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):Empusas wrote: ↑Tue Oct 08, 2019 10:08 amI 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.
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)
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)
Here is Pin page of lobo:
https://github.com/loboris/MicroPython_ ... o/wiki/pin
What it means:
and where i can find interrupt function?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