4-wire PC fan control with 3.3V

I'm working on a project, and I want to include a PC fan for added cooling on some of the components. I am planning to use a 5V 4-wire Noctua fan (I am still deciding on the size) and an LM35 sensor to measure the temperature. I am using a 3.3V board, and I want to be able to make sure that the fan is turning because I need the extra cooling. I have a few questions about some of the tutorials that I have been watching with respect to the PWM. Here is the Noctua PWM specifications white paper for reference, and here is one of the tutorials that I was watching.

The tutorials that I am been watching and the Noctua paper have a pull-up resistor on the tachometer signal pin for measuring RPM. The Noctua paper says that you need a pull-up resistor that keeps the current below 5mA for 5V and 12V fans. Is there a reason to have the extra pull-up resistor, or would it make more sense to simply use the built-in pull-up resistor for the pin (i.e., INPUT_PULLUP)? Or is there a reason to use an extra pull-up resistor in the circuit?

I'm also wondering about whether a 3.3V board can control a 5V fan without adding a bunch of extra components. The Noctua paper says that the PWM control signal is 5V, but it also says that an "External pull-up is not necessary as the signal is pulled up to 3,3V/5V inside the fan." This makes me think that I can control the fan with a 3.3V signal. Looking at the RPM/tach signal, it doesn't specify that it has to be 5V, so I am wondering if I use an appropriate resistor (e.g., 10 kOhm), can I read the signal from the fan?

In case you are wondering, I'm using an Arduino Giga with a variation of the following code to get the 25 kHz signal with the Mbed OS, but I didn't ask this question in the Giga section of the forum because I figured that it is a more general question about fan control with the various 3.3V board available rather than specifically about the Giga.

#include <mbed.h>

const int thermometerInPin = A0;  // Analog input for the thermosensor
PinName fanControlPin = digitalPinToPinName(4);  // PWM pin for fan control

mbed::PwmOut fan_pwm(fanControlPin);  // Static allocation

void setup() {
    // Set the PWM frequency to 25 kHz
    fan_pwm.period(1.0 / 25000.0); 
}

void loop() {
    // Read temperature sensor (0–1023)
    int temperatureValue = analogRead(thermometerInPin);

    // Scale temperatureValue (0–1023) to PWM duty cycle (0.0–1.0)
    float fanOutputValue = temperatureValue / 1023.0;

    // Write duty cycle to PWM
    fan_pwm.write(fanOutputValue);

    delay(100);  // Optional delay to prevent excessive loop frequency
}

Yes noise. The internal pullup is a fairly high value resistor. An external resistor of 4.7K will help suppress any noise pickup. Pullup to 3.3V

I'm also wondering about whether a 3.3V board can control a 5V fan without adding a bunch of extra components.

Yes it can, no extra components needed.

1 Like

From personal experience, I highly recommend using a digital sensor DS18B20 instead of an analog sensor LM35. Also, according to the datasheet, the LM35 requires at least 4 volts to operate, while the DS18B20 requires at least 3 volts, and since you are using a 3.3 volt board, it is generally more convenient to use the digital sensor.

1 Like

Thanks for the suggestion. I hadn't come across this sensor when I was originally planning things.

A few of the sensors that I am using a 5V, so I am going to have to either use voltage dividers or potentiometers to get the voltage down to the right range from all of these sensors for the board, and I already have the LM35 here. If something happens that I need to replace the LM35 though, the DS18B20 will definitely be one that I consider.

Not necessary with the LM35

1 Like

Be careful. There have been numerious complaints on the forum about fake and non-functioning DS18B20 sensors.

1 Like

Right, I got that mixed up with other sensors that I am using. Thanks for the reminder!

Thank you for the quick and direct response!

You around the 3rd person in the past week asking about 4 wire fans.

1 Like

The sense line will have high impedance when the NPN transistor is off. I’m not comfortable relying on the Arduino’s internal pull-up resistors for lines that extend off the board. I recommend using an external pull-up resistor in the range of 1k ohms.

If you check the customer interface in the link you provided, you’ll see that they also use a pull-up resistor. The output is an NPN open-collector design, which can sink current but cannot source it. This approach makes a lot of sense and is widely considered an industry standard. Incorporating the pull-up externally avoids requiring different models for internal configurations.

Regarding flash detection, I recommend using a photo diode. The flash duration can be as short as 1/4000 of a second in certain ranges. While CDS cells are simple to use, they are far too slow for this application.

For further guidance, this link might help: Hobby Circuit - XENON Lamp Flash Detector, designed by David A. Johnson, P.E.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.