I want to read the rpm and control the speed of a 12V - four wire fan through Arduino. There are many articles describing the procedure, yet I have some questions.

Read Speed:

So, 12V and Gnd are connected to the who wires of the fan, and the third wire is connected to the Arduino's input pin through a pull-up resistor (internal or external), in order to read the pulses, thus the speed of the fan. I guess that it works like in the schematic below:


simulate this circuit – Schematic created using CircuitLab

If so, how much is the voltage that the input pin reads when the sensor switch is closed, 5V ορ 12V? I believe that it is 12V, but that would damage the board, right? Should I put something like an optocoupler between fan and input pin, in order to isolate them?

Control Speed

Just about the same question for controlling the speed. Can I stick the fourth wire of the fan to a PWM pin? Is it true that the PWM pole of the fan accepts max.5.0V? Just to be on the safe side, should I use a motor driver IC, like L293D?

Thank you

  • 1
    \$\begingroup\$ The Arduino line would not be connected to a ground connection as you are showing. To receive a better answer you should show the schematic of the whole fan circuit or provide a link to the spec sheet. \$\endgroup\$
    – Nedd
    Feb 12, 2015 at 9:39
  • 1
    \$\begingroup\$ Your schematic is wrong. You have the input pin directly connected to ground: it will always read zero. \$\endgroup\$
    – DoxyLover
    Feb 13, 2015 at 17:36

3 Answers 3


If this is the type of fan you are using: http://www.formfactors.org/developer/specs/REV1_2_Public.pdf

-then the output sensor claims it is an open collector or open drain. (Meaning it only pulls down.) It also says "Motherboard will have a pull up to 12V, maximum 13.2V". Written this way I would take this as a recommendation. If the output is truly just an open collector/drain then you should be able to add your own pull-up resistor as needed. For the Arduino input you would have the resistor pulled up to +5 only. (You could add the 5k resistor as shown, or if you know how to enable the internal pull-up on the Arduino port pin use that, in which case you would not need the 5k resistor shown.) With a resistor in place the fan sensor pulls down (to 0v) then releases the pin, so it then climbs back up to what ever voltage the pull-up is connected too.

The hook up should look like this:


simulate this circuit – Schematic created using CircuitLab

But just as a precaution, before connecting the Arduino Speed input pin to Sense, you should measure the voltage on the Sense fan pin while the fan is slowly rotating (with 12v on the fan power input).

The spec lists the Fan's Control input to be a 5v PWM signal. So coming from the Arduino no extra driver circuit is needed.

Also the spec says the pulses from the Sense pin is 2 per revolution, so measure the pulses per second then divide by 2.

  • 1
    \$\begingroup\$ Apologies for my poor schematic. Yes, the output sensor is open collector. I connected a 10kOhm pull-up resistor and it worked fine. Thank you. \$\endgroup\$ Feb 13, 2015 at 9:17
  • 1
    \$\begingroup\$ 4-pin computer fans normally want the PWM signal to have a frequency of 25 KHz (acceptable range: 21 to 28 KHz) - folk.uio.no/kyrrens/diverse/viftekontroller/… Arduino's built-in PWM uses no more than 1 KHz (depending on the model) - arduino.cc/reference/en/language/functions/analog-io/… It's possible, though, to directly set up the microcontroller's timer to generate a 25 KHz signal - create.arduino.cc/projecthub/tylerpeppy/… \$\endgroup\$ Aug 3, 2020 at 10:32
  • \$\begingroup\$ The +5V pull-up for the fan connector's tach (sense) should work, although motherboards use +12V then step it down to an appropriate voltage with a voltage divider. This way if the fan's cable gets pinched and the power wire gets shorted to the tach (sense) wire, the motherboard's digital input will still see 3.3V (5V or 3.3V for Arduino, depending on the model) and not burn out \$\endgroup\$ Aug 3, 2020 at 10:44
  • \$\begingroup\$ I've had some noise issues reading the tach signal while using PWM. More details in my comments in Michael Karas' answer. \$\endgroup\$ Aug 3, 2020 at 10:45

Here is the recommended way to connect up a typical four wire fan. I have used this design multiple times with good success.

The input signal here is a PWM signal of about 20 KHz frequency that controls the fan speed via the duty cycle. As shown the input signal was designed for a 3.3V swing signal but would also work for 5V swing. Most fans have a lower control range at about the 30% duty cycle range where they stop operating.

The output signal here is a 3.3V swing signal that is the tachometer signal from the fan. You measure the frequency of this signal to determine the fan speed. Note that fans vary and you will find fans that output two or four pulses per revolution on this output. If you need a 5V swing output from this output adjust the values of one of the two lower resistors in the divider.

enter image description here

The fan connection wire colors are typical but you may find some variations in the colors used by various manufacturers.

This circuit does several things that are important to consider. One this is that it isolates the on-board microcontroller from the voltage range used by the fan which can be important if there are ever faults or mistakes made in the fan wiring harness or connection. Secondly it provides an isolation in the case of static discharge.

  • \$\begingroup\$ Hi Michael, thanks for the schematic. I successfully used it on a bread board. The only question I have is regarding the FAN_PWM pin.I used a 4.7K ohm as R251 and pulled to 3.3v instead of 5v. Seems to work but I don't know if it's ok before soldering... \$\endgroup\$ Feb 14, 2020 at 23:39
  • \$\begingroup\$ @MikeGleasonjrCoitirier - You need to look at the fan spec to determine proper voltage swing for the PWM input. Using a reduced voltages may change the range of duty cycle control on some cheap fans. \$\endgroup\$ Feb 14, 2020 at 23:50
  • \$\begingroup\$ What is the purpose of C228 capacitor? \$\endgroup\$ Jul 24, 2020 at 23:48
  • \$\begingroup\$ Does this do anything for the tacho output? My fan (Noctua) spec sheet mentions tacho is open collector output, pull-up Vcc: 13V. I'm guessing it's a max value. Can we pull up the tacho output to 5V instead of 12V? If yes, would the two resistors R248 and R249 still be necessary, or could they be removed or replaced with a single resistor? I have this seemingly working on a breadboard (3.3K pull-up to 5V, 10K for R248, then going to an Arduino's input). I'm counting interrupts on that pin, it works as described. If I remove R248, I'm getting only noise. \$\endgroup\$ Jul 24, 2020 at 23:54
  • 1
    \$\begingroup\$ @GenePavlovsky - C228 is a bulk power supply bypass capacitor to supply current surges that may happen when the fan starts and stops. R247, R248 and R249 are designed to allow the swing of the TACH output of the fan to be maximized around the open drain/collector output of the fan get better signal to noise isolation whilst a the same time reducing the output to a 3.3V swing for feeding into the device that monitors the TACH signal. \$\endgroup\$ Jul 25, 2020 at 3:07

Firstly the first question:

Please specify what you will be using as switch. Maybe an optical sensor with an encoder? Or maybe a transmitter and receiver infrared leds? Or even a magnetic, inductive or capacitive sensor? Assuming you already have an efficient way to count the pulses it's very important to feed the switch with 5V (the limit for arduino). Also, your resistor is misplaced. You can put it between the Arduino input and the ground or input and Vcc, but for this you will need to also move the switch to between the gnd and input. Look for your circuit, when the switch is open you will have 0V on input. When it closes, you will have 0V too, so it doesn't works. Since the switch probably is not an inductive load you will not need the optocoupler.

How to control

Except you will need also to feed another fan and need to do reversion, I will not recommend a motor driver for cost reason. If you are worried with only the speed, you can use a simple transistor to do the job. Just remember the maximum current Arduino can output is 40mA (if you are not using a modified one). Also you need to establish the maximum current you will want at the fan to verify the hfe of transistor to make sure it will have enough gain. Since it is a 12 V fan I believe it will not be a real worry.


Try to better explain your project, I really found it very confusing, but tried to answer with what you gave me.

  • \$\begingroup\$ I think the OP meant the SW1 to be the virtual "switch" (actually hall sensor, open drain/collector) inside the fan. For controlling the fan's speed, you don't need a transistor since 4-pin fans accept a digital PWM signal, the control circuitry is inside the fan \$\endgroup\$ Aug 3, 2020 at 10:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.