The Direct Answer: Why You Need a Logic-Level MOSFET

To control a 12V DC fan with a 5V Arduino, you cannot connect the fan directly to the microcontroller's I/O pins. An Arduino Uno R3 pin can only safely source or sink about 20mA, while a standard 120mm cooling fan draws between 100mA and 300mA. Connecting it directly will permanently fry the ATmega328P chip. The direct answer: use a logic-level N-channel MOSFET (like the IRLZ44N) as a low-side switch, driven by an Arduino PWM pin, and always include a flyback diode across the fan terminals to protect against inductive voltage spikes.

Many beginner kits include the IRF520 MOSFET, but this is a trap. The IRF520 is not a true logic-level MOSFET; at 5V gate drive, it barely turns on, leading to massive voltage drops and overheating. The IRLZ44N, however, has a low gate threshold and an $R_{DS(on)}$ of roughly 0.022Ω at 5V. If your fan draws 1A, the power dissipated by the MOSFET is $P = I^2 \times R = 1^2 \times 0.022 = 22mW$. It will run completely cool without a heatsink.

Project Spec Sheet & Parts List

This build assumes you are using an Arduino Uno R3 (ATmega328P) and a standard 2-pin or 3-pin 12V brushless DC fan. If you are using a 4-pin PWM PC fan, see the FAQ at the bottom for a simplified wiring approach.

Component Exact Variant / Part Number Purpose Est. Cost
Microcontroller Arduino Uno R3 (Rev3, ATmega328P) Generates 5V PWM signal $25.00
MOSFET IRLZ44N (Logic-Level, TO-220) Switches 12V ground path $1.50
Cooling Fan 12V 120mm DC Fan (e.g., Delta FFB1212VH) The load being controlled $12.00
Flyback Diode 1N4007 Rectifier Diode Clamps inductive back-EMF spikes $0.10
Pull-down Resistor 10kΩ 1/4W Carbon Film Keeps gate LOW during boot-up $0.05
Power Supply 12V 2A DC Wall Adapter (5.5x2.1mm barrel) Powers the fan independently $8.00

Pin Mapping & Step-by-Step Wiring

Safety Callout: Always disconnect the 12V power supply and the Arduino USB cable before making or altering physical connections. A short between the 12V line and the Arduino's 5V rail will instantly destroy the voltage regulator and the main IC.

Arduino / Source Destination Notes
Arduino Pin 9 (PWM) MOSFET Gate (Middle Pin) Pin 9 defaults to ~490Hz PWM
Arduino GND MOSFET Source (Right Pin) & 12V PSU GND Common ground is mandatory
MOSFET Gate 10kΩ Resistor to MOSFET Source (GND) Prevents floating gate on startup
12V PSU VCC (+) Fan Positive (Red/Yellow Wire) Do not connect to Arduino 5V
Fan Negative (Black) MOSFET Drain (Left Pin) Switched ground path
1N4007 Cathode (Stripe) 12V PSU VCC (+) Points towards positive voltage
1N4007 Anode MOSFET Drain / Fan Negative Clamps negative voltage spikes
  1. Establish Common Ground: Connect the 12V power supply's ground wire to the Arduino's GND pin and the MOSFET's Source pin. Without a shared ground, the Arduino's 5V PWM signal has no reference point to switch the MOSFET.
  2. Wire the Gate: Connect Arduino Pin 9 to the MOSFET Gate. Solder or breadboard the 10kΩ resistor between the Gate and Source. This ensures the fan stays off when the Arduino is resetting or booting up.
  3. Wire the Load: Connect the 12V positive line to the fan. Connect the fan's ground wire to the MOSFET Drain.
  4. Install the Flyback Diode: Place the 1N4007 diode in parallel with the fan. The silver stripe (cathode) must face the 12V positive side. Never skip this step; brushless fan motors generate reverse voltage spikes when switched off that can punch through the MOSFET and reset your microcontroller.

The Code: Serial PWM Control with Bounds Checking

The following C++ code targets the Arduino Uno R3 (AVR architecture). It listens for serial input from the Serial Monitor and adjusts the PWM duty cycle (0-255). It includes explicit error handling to catch out-of-bounds values.

// Pin Definitions
const int FAN_PIN = 9; // Must be a PWM-capable pin on Uno R3

void setup() {
  pinMode(FAN_PIN, OUTPUT);
  digitalWrite(FAN_PIN, LOW); // Ensure fan is off at boot
  Serial.begin(115200);
  Serial.println("Fan Control Ready. Enter PWM value (0-255):");
}

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n');
    input.trim(); // Remove hidden carriage returns
    
    // Parse integer and validate
    int pwmVal = input.toInt();
    
    // Check if input was actually a number and within 0-255 bounds
    if (input == String(pwmVal) && pwmVal >= 0 && pwmVal <= 255) {
      analogWrite(FAN_PIN, pwmVal);
      Serial.print("Success: Fan PWM set to ");
      Serial.println(pwmVal);
    } else {
      // Exact error string for serial debugging
      Serial.println("ERROR: PWM_VALUE_OUT_OF_BOUNDS");
      Serial.println("Please enter an integer between 0 and 255.");
    }
  }
}

Troubleshooting: First Three Things to Check

When the circuit fails, use this ranked decision path to isolate the fault.

  1. Symptom: Fan runs at 100% speed and ignores Arduino code.
    Cause: The MOSFET gate is floating, or the 12V line is backfeeding into the gate.
    Fix: Verify the 10kΩ pull-down resistor is physically connected between Gate and Source. Check your breadboard continuity; cheap breadboards often have broken internal clips on the power rails.
  2. Symptom: Fan stutters, clicks, or fails to start at low PWM values (e.g., below 80).
    Cause: Brushless DC fans have a minimum starting voltage/duty cycle. Furthermore, if you attempted to change the PWM frequency using AVR timer registers on an Uno R4, you will get the compile error 'TCCR2B' was not declared in this scope because the R4 uses a Renesas ARM chip, not an AVR.
    Fix: Stick to standard analogWrite() for cross-compatibility. In software, implement a 'kickstart' routine: write 255 for 100ms to overcome static friction, then drop to your target PWM value.
  3. Symptom: Arduino randomly resets or disconnects from USB when the fan spins down.
    Cause: Inductive back-EMF spike collapsing the 5V rail.
    Fix: Ensure the 1N4007 diode is oriented correctly (stripe to 12V). If the issue persists, your 12V power supply might be sharing too much noise with the Arduino. Power the Arduino via a separate USB connection or add a 100μF decoupling capacitor across the 12V supply rails.

Scaling the Build: Simplify or Extend

Depending on your end goal, you can alter the complexity of this build.

  • To Simplify (The Relay Route): If you only need ON/OFF control and don't care about speed, ditch the MOSFET and use a 5V Relay Module (like the SRD-05VDC-SL-C). Wire the Arduino pin to the relay IN, and switch the 12V positive line through the relay's NO (Normally Open) and COM terminals. It requires zero code math, but you lose speed control and the relay will click audibly.
  • To Extend (Closed-Loop Thermal Control): Add a 10k NTC Thermistor in a voltage divider to Analog Pin A0. Read the temperature using the Steinhart-Hart equation, map the temperature range (e.g., 30°C to 60°C) to PWM values (0 to 255) using the map() function, and write a proportional control loop to automatically adjust fan speed based on real-time heat.

Frequently Asked Questions

Can I control a 4-pin PWM PC fan directly with an Arduino?

Yes. A standard 4-pin ATX PC fan has a dedicated PWM input wire (usually blue or yellow) that expects a 5V logic signal. You can connect the fan's 12V and GND pins directly to a 12V power supply, and wire the fan's PWM pin directly to Arduino Pin 9. You do not need a MOSFET for the PWM signal wire, though you still cannot power the 12V rail from the Arduino. Note that 4-pin fans require a 25kHz PWM frequency for silent operation; the default Arduino 490Hz will cause the fan motor to whine audibly.

Why does my fan make a high-pitched whining noise at low speeds?

This is caused by the default PWM frequency of Pin 9 on the Arduino Uno, which is approximately 490Hz. This frequency falls squarely in the human hearing range, and the coils inside the fan's motor vibrate at this frequency. To fix this, you can increase the PWM frequency to ultrasonic levels (above 20kHz) by modifying the AVR Timer 1 prescaler registers in your setup() block, or simply use a 4-pin fan driven by a dedicated 25kHz hardware timer library like PWM.h.

Do I need a heatsink for the IRLZ44N MOSFET?

For standard PC cooling fans drawing under 1.5A, no. As calculated in the introduction, the power dissipation at 1A is roughly 22mW. The TO-220 package can safely dissipate up to 2W in free air without a heatsink. However, if you are controlling a high-amperage industrial blower fan or a 12V Peltier cooler drawing 5A+, you will need to bolt a small aluminum heatsink to the tab and re-calculate your thermal limits based on the ambient temperature of your enclosure.