Here is how to give speed control to a regular 12V computer fan using an Arduino and PWM (pulse width modulation). This will work for other motors as well.
This is not intended to be a deep tutorial on the subject, but if you need more information you can check out the various links provided. This is mainly a quick write-up to show a friend how to do speed control on a fan that will eventually be hooked to a temperature sensor so that the fan can regulate the temperature inside an enclosed box.
- Arduino (can be done with a Raspberry Pi using Python)
- TIP122 (or adjusted for just about any Darlington transistor)
- 1N4001 diode
- 12V computer fan
- 12V power supply
- 270Ω resistor
The above items are not special or magical. If you don’t have a TIP122 transistor, you can probably make this work with just about any large transistor or MOSFET (large as in handling power as opposed to just physical size, though they often correspond). The same applies for the diode: as long as it is sufficiently large, it will probably work. The resistor size was chosen simply based on it being the one closest to my Arduino when I started the project.
I leaned heavily on an Instructables article for getting my wiring set up. Certainly check out his article for more details about the wiring if you need more than a schematic to figure this out.
Or, an even more detailed description of what we are doing (at least on a partial level) is the Adafruit article on motor control. They have lots of pictures and a great explanation. But what their article is lacking is how to power a motor that needs much more voltage than what the Arduino can provide. That is why you are reading this article.
Here is my schematic of the build.
The Build Logic
I find it helps to try to understand what is happening in the electrical path so that I can complete the build and adjust the hardware or the code. Let me try to logically walk you through what is happening. Check out the video below for a rough verbal description.
The two connections to the Arduino are ground and digital pin 9 which is what sends the PWM signal to the transistor. PWM signal goes out of the Arduino into a resistor. I’m not entirely sure how much resistance is needed for this build. It works with no resistor and I have seen builds that call for up to a 2.2 kΩ. I don’t know that the resistor value is super critical, but you should probably include one.
So far we have PWM → resistor.
Now you go from the resistor to the base of the Darlington transistor. I am using a TIP122 because that is what I had handy. This should work identically with a TIP120 (and probably dozens of other transistors).
When the base of the transistor gets power from the PWM signal, it will allow power to pass through from the collector to the emitter. Check out Adafruit’s explanation of transistors for more details.
When the signal on the base pin triggers the collector/emitter connection, the transistor begins passing 12V from the power supply to the fan. The signal on the base is making the transistor act like a switch to turn on and off the collector/emitter connection.
Therefore, we kinda have 2 separate halves to this project:
- The low power side (Arduino side) is PWM → resistor → base → emitter → ground.
- The high power side is 12V positive → fan positive → through the motor → fan negative → collector → emitter → ground.
Between the collector and emitter we also insert a diode. This prevents the spinning of the fan (or DC motor) from pushing power back through the transistor and blowing up the Arduino. A DC motor (which a fan is) generates electricity when spinning but does not have outside power pushing it. So when the Arduino stops sending a signal to the fan the fan will spin down and in the process create a small DC voltage. In this case it is probably not enough to matter, but it is a good habit to put a diode in place to stop the newly created voltage from traveling backwards into the Arduino. As you probably know, a diode only allows the electricity to travel one direction. We want power to travel from the Arduino to the fan but not the other direction.
Both the ground coming from the Arduino and the ground of the 12V power supply need to be tied together. You should have only 1 ground in a circuit even if you have multiple power supplies and voltages.
In my video below you also see an LED and another resistor. This is just an indicator that power is being supplied. The second resistor is 100 kΩ. Also carefully chosen because of its proximity to my workspace.
Note that the code in the video turns the fan/LED full on and full off. However, the code I provide here is full on and only about 40% off. Being able to adjust the speed of the fan using PWM is what this project is about. Therefore you can adjust the provided code to run the fan at any speed you would like.
int TIP120pin = 9; // PWM signal out to transistor on pin 9
analogWrite(TIP120pin, 255); // Run full speed (255)
delay(3000); // for 3 seconds
analogWrite(TIP120pin, 100); // Run at approximately 40% speed
delay(6000); // for 6 seconds
This sets pin 9 as the control pin. Then makes its pinMode to be an output. The loop turns on pin 9 at 100% speed (255) for 3 seconds and then drops to 40% speed (100) for 6 seconds.
And that’s it!
The ultimate project is to control the fan based on temperature. Getting temperature values from a digital or analog temperature sensor on an Arduino is fairly simple. It then becomes a matter of telling the fan PWM to raise or lower the speed based on the temperature.