If you are searching for pulsweitenmodulation arduino (the German technical term for Pulse Width Modulation, or PWM), you are likely trying to control a high-current load like a DC motor, a high-power LED array, or a heating element using a microcontroller. The Arduino’s analogWrite() function outputs a 5V square wave, but its GPIO pins can only source about 20mA to 40mA. To drive real-world loads, you must interface that PWM signal with external power electronics.

This guide provides a decision-forward framework to select the right driver, a complete wiring and code implementation for a 12V DC motor, and a debugging playbook for when your circuit fails to spin.

The Quick Decision Path: Which PWM Driver Do You Need?

Do not guess your driver topology. Use this decision tree to select the exact component for your load. For 90% of hobbyist 12V motor projects, the decision terminates at the Logic-Level N-Channel MOSFET.

Load Type & Current Required Topology Concrete Part Pick
< 200mA (Small 5V fans, indicator LEDs) Direct GPIO (No external driver) Arduino Pin directly to load
200mA to 5A, Unidirectional (12V motors, solenoids, LED strips) Logic-Level N-Channel MOSFET (Low-side switch) IRLZ44N (Default Pick)
> 5A or Bidirectional (Robotics, winches, reversing motors) H-Bridge Motor Driver IC Texas Instruments DRV8871 or L298N
AC Loads (Mains heaters, AC pumps) Solid State Relay (SSR) with Zero-Cross Omron G3NA-210B (Do NOT use standard PWM on AC)
Bench Warning: The IRF520 Trap. Many beginner kits include the IRF520 MOSFET. Do not use it for 5V Arduino PWM. The IRF520 has a gate threshold voltage (Vgs) that requires 10V to fully turn on and drop its Rds(on) resistance. At 5V, it partially conducts, overheats, and causes severe voltage drop. Always use a Logic-Level MOSFET like the IRLZ44N, which fully saturates at Vgs = 4V to 5V.

Parts List and Pin Mapping (Target: Arduino Uno R3)

This build targets the Arduino Uno R3 (ATmega328P). We use Pin 9 specifically because it is tied to Timer1 (a 16-bit timer), which allows for advanced frequency manipulation later if your motor whines at the default 490Hz.

Component Exact Variant / Value Estimated Cost (2026)
Microcontroller Arduino Uno R3 (ATmega328P DIP or SMD) $22.00 - $28.00
MOSFET Infineon IRLZ44N (TO-220 package, Logic-Level) $1.50
Flyback Diode 1N4007 (1A, 1000V) or 1N5819 (Schottky for faster switching) $0.10
Gate Resistor 220Ω (Limits inrush current into the gate capacitor) $0.02
Pull-down Resistor 10kΩ (Prevents motor twitching during Arduino boot) $0.02
Power Supply 12V DC, minimum 5A (e.g., Mean Well LRS-60-12) $18.00

Pin Mapping Table

Arduino Uno R3 Pin Destination Wire Color (Suggested)
D9 (PWM ~) 220Ω Resistor → IRLZ44N Gate (Pin 1) Orange
GND IRLZ44N Source (Pin 3) & 10kΩ Pull-down Black
A0 (ADC) 10kΩ Potentiometer Wiper (for manual speed control) Blue
5V Potentiometer VCC Red

Step-by-Step Build: Driving the 12V Motor

Safety Callout: While 12V DC is safe from shock, a stalled RS-550 motor can pull 15A+ and melt standard 22 AWG breadboard jumper wires. Use 18 AWG or thicker wire for the 12V power and ground loops, and bypass the breadboard power rails for the motor current.

  1. Prepare the Pull-Down: Connect the 10kΩ resistor between the IRLZ44N Gate (Pin 1) and Source (Pin 3). This ensures the MOSFET stays off if the Arduino resets or the gate pin floats.
  2. Wire the Gate Signal: Connect the 220Ω resistor from Arduino Pin D9 to the MOSFET Gate. This resistor protects the Arduino's ATmega328P GPIO from the initial current spike of charging the MOSFET's internal gate capacitance.
  3. Connect the Load (Low-Side Switch): Connect the 12V PSU positive terminal directly to the Motor's positive terminal. Connect the Motor's negative terminal to the MOSFET Drain (Pin 2). Connect the MOSFET Source (Pin 3) to the 12V PSU Ground and Arduino GND. Common ground is mandatory.
  4. Install the Flyback Diode: Place the 1N4007 diode in parallel with the motor. The cathode (silver stripe) must point toward the 12V positive rail, and the anode toward the MOSFET drain. This provides a path for the inductive kickback when the MOSFET switches off, preventing voltage spikes that will destroy the MOSFET.
  5. Verify with a Multimeter: Before applying 12V power, set your multimeter to continuity mode. Check for shorts between the 12V rail and Ground. Verify the diode orientation (it should only beep one way).

The Code: Compilable Sketch with Bounds Checking

This sketch reads a potentiometer on A0, maps it to an 8-bit PWM value, and includes strict bounds checking. The analogWrite() function expects a uint8_t (0-255). If an ADC mapping error results in a value like 256 or -1, it will silently overflow, causing the motor to behave erratically (e.g., jumping from 100% speed to 0%).

/*
 * Target Board: Arduino Uno R3 (ATmega328P)
 * Project: Pulsweitenmodulation (PWM) 12V Motor Control
 * Pin D9 uses Timer1 (16-bit), default frequency ~490Hz
 */

const int PWM_PIN = 9;    // Must be a PWM-capable pin (marked with ~)
const int POT_PIN = A0;   // Analog input for speed control

void setup() {
  Serial.begin(115200);
  pinMode(PWM_PIN, OUTPUT);
  
  // Explicitly set LOW to prevent motor twitch during setup()
  digitalWrite(PWM_PIN, LOW);
  
  Serial.println("PWM Motor Controller Initialized.");
}

void loop() {
  // Read 10-bit ADC value (0 to 1023)
  int rawAdc = analogRead(POT_PIN);
  
  // Map ADC range to 8-bit PWM range
  int mappedPwm = map(rawAdc, 0, 1023, 0, 255);
  
  // ERROR HANDLING: Strict bounds checking to prevent uint8_t overflow
  uint8_t safePwmValue = 0;
  if (mappedPwm < 0) {
    safePwmValue = 0;
  } else if (mappedPwm > 255) {
    safePwmValue = 255;
  } else {
    safePwmValue = (uint8_t)mappedPwm;
  }
  
  // Apply Pulsweitenmodulation signal
  analogWrite(PWM_PIN, safePwmValue);
  
  // Throttled Serial Debugging (prevents serial buffer flooding)
  static unsigned long lastPrintTime = 0;
  if (millis() - lastPrintTime >= 250) {
    Serial.print("Raw ADC: ");
    Serial.print(rawAdc);
    Serial.print(" | Safe PWM: ");
    Serial.println(safePwmValue);
    lastPrintTime = millis();
  }
  
  // Small delay for ADC stability
  delay(15);
}

Debugging Pulsweitenmodulation: First 3 Checks and Common Errors

When your motor refuses to spin or the Arduino throws a fit, do not rewrite your code immediately. Hardware and timer conflicts cause 95% of PWM failures.

The First 3 Things to Check When It Fails

  1. Is the Gate actually seeing 5V? Use your multimeter to measure DC voltage between the Arduino D9 pin and GND while the potentiometer is at max. If it reads 3.3V instead of 5V, you are either using a 3.3V board (like an ESP32 or Due) without a gate driver, or your Arduino's 5V regulator is browning out.
  2. Is the Flyback Diode backwards? If the diode is forward-biased (anode to 12V, cathode to Drain), it acts as a dead short across the power supply when the MOSFET turns on. This will trip your power supply's over-current protection or blow the diode.
  3. Are you using a true PWM pin? On the Uno R3, only pins 3, 5, 6, 9, 10, and 11 support hardware analogWrite(). If you use pin 8, the Arduino will simply output a static HIGH or LOW based on whether the value is > 127.

Exact Error Strings and Ranked Causes

Compiler Error: error: 'ledcSetup' was not declared in this scope
Cause: You copied ESP32 PWM code into an AVR (Uno) sketch. The ESP32 does not use analogWrite() for high-performance PWM; it uses the LEDC (LED Control) peripheral.
Fix: If targeting the Uno R3, replace ledcSetup() and ledcWrite() with standard analogWrite(). If targeting the ESP32, you must include the ESP32 core and use the LEDC API.
Runtime Symptom: Motor emits a high-pitched whine and stalls at low potentiometer positions.
Cause: The default PWM frequency on Uno R3 pins 9 and 10 is ~490Hz. At low duty cycles, the 490Hz pulses are too slow to overcome the motor's mechanical inertia, causing it to rapidly start and stop (stall/whine) rather than spin smoothly.
Fix: Increase the Timer1 frequency to an ultrasonic rate (e.g., 31,372 Hz) by modifying the prescaler in setup(): TCCR1B = (TCCR1B & 0xF8) | 0x01;. Note: This alters the behavior of the Servo library, which relies on Timer1.

Extending and Simplifying the Build

Depending on your project timeline and budget, you can scale this pulsweitenmodulation setup up for industrial use or down for rapid prototyping.

How to Simplify (Rapid Prototyping)

If you want to skip the breadboard wiring and flyback diode calculations, purchase a pre-assembled Pololu Basic Motor Controller or a generic DC Motor Driver Module (based on the BTS7960). These boards include the logic-level MOSFETs, optoisolators, and flyback diodes on a single PCB. You simply connect 12V, GND, and one 5V PWM signal. Expect to pay around $12 to $18 per module, which is often cheaper than buying individual TO-220 MOSFETs and heat sinks for high-current (>10A) applications.

How to Extend (Closed-Loop Control)

Open-loop PWM assumes the motor speed perfectly matches the duty cycle, which is false under varying mechanical loads. To extend this build into a professional closed-loop system:

  • Add an Encoder: Mount a magnetic quadrature encoder (e.g., RM08) to the motor shaft.
  • Implement PID: Use the Arduino PID Library. Feed the encoder's RPM calculation into the PID input, set your target RPM, and let the PID output drive the analogWrite() function.
  • Upgrade the Microcontroller: If you need 12-bit PWM resolution (0-4095) for ultra-smooth low-speed torque control, migrate the code to an ESP32-WROOM-32 using the ledc API, which natively supports high-resolution hardware PWM without tying up CPU interrupts.

By selecting the correct logic-level MOSFET, protecting your circuit with a flyback diode, and implementing bounds-checked code, your pulsweitenmodulation arduino project will transition from a fragile breadboard experiment to a reliable, deployable motor controller.