When you need to control PWM motor DC loads in an embedded project, sending a logic-level signal directly from a microcontroller is never enough. A GPIO pin maxing out at 20mA to 40mA cannot drive a motor that demands amps of current. To do this safely and efficiently, you must pair the right motor topology with a dedicated MOSFET-based driver, size the components for the mechanical load, and configure your microcontroller's PWM peripherals to avoid audible noise and thermal failure.

This guide walks through the exact hardware selection, wiring topology, and failure diagnostics required to build a reliable DC motor drive system using modern boards like the ESP32 or Arduino.

DC Motor Types and PWM Control Requirements

Not all "DC motors" accept a raw PWM voltage signal. Before selecting a driver, you must match the motor type to your load profile. Stepper and servo motors are entirely different beasts—they require precise pulse-and-direction timing or closed-loop feedback protocols, not raw voltage modulation. For pure rotational drive, you are generally choosing between three topologies.

Motor Type Torque Curve Control Needs Typical Cost (Hobby/Industrial)
Brushed DC (BDC) High starting torque, drops linearly with speed. Simple 2-wire PWM via H-bridge or half-bridge. Direction requires H-bridge or DPDT relay. $3 - $25
Brushless DC (BLDC) Flat torque curve across a wide RPM range. Requires a 3-phase Electronic Speed Controller (ESC) or dedicated inverter. Cannot use simple 2-wire PWM. $15 - $80+
Coreless DC Low inertia, extremely fast transient response. High-frequency PWM (20kHz+) required to prevent cogging and audible whine. $10 - $40

Which motor fits your load? If you are driving a conveyor, a winch, or a wheeled robot chassis, a Brushed DC motor is the correct choice. It provides the high starting torque needed to overcome static friction, and you can easily control its speed using a standard PWM signal. If your application requires high RPM with low weight (like a drone or RC car), you must step up to a BLDC and an ESC, which accepts a specific 50Hz-400Hz servo-style PWM pulse rather than a raw power PWM signal.

Sizing Your DC Motor and PWM Driver (Worked Example)

The most common mistake makers make is undersizing the motor driver. The golden rule of thumb for DC motor drivers is: The driver's continuous current rating must be at least 1.5 times the motor's maximum continuous operating current, and it must survive the motor's stall current.

Worked Load Example: 12V Material Conveyor
Load Requirement: The belt requires 2.0A of continuous current at 12V to move the maximum payload at the target speed.
Motor Selected: A 12V brushed DC gearmotor. Datasheet states 2.0A nominal operating current and an 8.0A stall current.
Driver Sizing: We need a driver that can handle at least 3.0A continuous (2.0A x 1.5) and won't instantly fry if the belt jams and pulls 8.0A momentarily.

Let's evaluate common driver ICs for this 8A stall scenario:

  • L298N (BJT H-Bridge): Rated for 2A continuous, 3A peak. It uses bipolar Darlington transistors, which drop about 2V to 3V at high current. At 2A, it will dissipate over 4W of heat and require a massive heatsink. If the motor stalls at 8A, the L298N will fail catastrophically. Verdict: Reject.
  • BTS7960 (MOSFET Half-Bridge): Rated for 43A continuous. It has an incredibly low $R_{DS(on)}$, meaning almost zero voltage drop and heat generation. However, it is physically massive and overkill for a 2A load, costing around $12-$15 per module. Verdict: Safe, but oversized.
  • TI DRV8871 (MOSFET H-Bridge): Rated for 3.6A continuous. It features built-in overcurrent protection (OCP) and thermal shutdown. If the motor stalls at 8A, the DRV8871 will detect the overcurrent event and safely shut off the outputs in microseconds, protecting the silicon. At roughly $5 to $7 for a breakout board, it is the exact right fit. Verdict: Select.

For deep technical specifications on integrated motor drivers, always consult the silicon manufacturer's datasheets, such as the Texas Instruments DRV8871 documentation, which details the exact OCP trip thresholds and thermal derating curves.

Wiring, Terminals, and Microcontroller Integration

Modern MOSFET drivers simplify wiring, but mixing up logic-level and motor-level power will instantly brick your microcontroller. Here is the standard terminal identification for a typical integrated H-bridge like the DRV8871 or TB6612FNG:

  • VM (Motor Power): Connects to the main battery or power supply (e.g., 12V). This powers the motor and the internal charge pumps.
  • VCC (Logic Power): Connects to the microcontroller's 3.3V or 5V rail. This powers the internal logic gates. Never connect VM to VCC.
  • GND: Common ground. The motor power supply ground and the microcontroller ground must be tied together here, or the PWM signal will have no reference voltage.
  • IN1 / IN2 (or PWM / DIR): Logic inputs from the microcontroller. Some drivers use two PWM pins for mixed decay control; others use one PWM pin for speed and one DIR pin for direction.
  • OUT1 / OUT2: The high-current outputs connected directly to the motor terminals.

The Flyback Diode Requirement: When a brushed DC motor spins, it acts as an inductor. When the PWM signal switches off, the collapsing magnetic field generates a massive reverse voltage spike (inductive kickback). Most modern ICs (like the DRV8871) include internal clamp diodes. However, if you are building a custom discrete MOSFET H-bridge, you must place external Schottky diodes (like the SS34) across the motor terminals. Do not use standard 1N4007 rectifier diodes; their reverse recovery time is too slow for high-frequency PWM, and they will overheat.

ESP32 vs. Arduino PWM Configuration:
On an Arduino Uno, analogWrite() defaults to roughly 490Hz or 980Hz depending on the pin. On an ESP32, you should use the LEDC (LED Control) peripheral or the newer MCPWM (Motor Control PWM) peripheral via the ESP-IDF or Arduino core. For brushed DC motors, set your PWM frequency between 1,000 Hz and 5,000 Hz. This is high enough to push the audible whine out of the human hearing range, but low enough to minimize switching losses in the MOSFETs.

Failure Signatures: Hum, Overheat, and Stall

When a motor drive system fails, it rarely does so silently. Recognizing these physical signatures will save you from burning out components on the bench.

1. Audible Hum or Whine (No Movement)
If the motor hums loudly but the shaft doesn't turn, your PWM frequency is likely too low (causing magnetostriction in the motor laminations), or the motor is mechanically stalled. If the PWM frequency is correct (e.g., 2kHz) and it still hums, the mechanical load exceeds the motor's starting torque. The motor is drawing stall current, and your driver is likely getting very hot.

2. Driver Overheating and Thermal Shutdown
If the motor runs fine for 30 seconds and then stops, only to start again a minute later, your driver is entering thermal shutdown. This happens when the silicon junction temperature exceeds 150°C to 165°C. This is almost always caused by using a BJT-based driver (like the L298N) without adequate active cooling, or by running a continuous current that exceeds the MOSFET driver's rated ampacity without a heatsink. Check the Pololu brushed DC motor fundamentals guide for excellent thermal derating charts.

3. Sudden Stall and Microcontroller Reset (Brownout)
If the motor stalls and your ESP32 or Arduino instantly reboots, you have a power delivery issue. A stalled motor draws 3x to 8x its nominal current. This massive current spike causes the voltage on your shared power rail to sag (brownout), dropping below the microcontroller's minimum operating voltage (usually 3.0V for the ESP32's internal regulators). The fix: Never power the microcontroller and the motor from the same raw voltage rail without heavy decoupling. Use a dedicated buck converter (like an LM2596) for the logic side, and place a large electrolytic capacitor (e.g., 1000µF, 25V) directly across the motor driver's VM and GND terminals to absorb current spikes.

FAQ: Controlling PWM DC Motors in Embedded Projects

Can I control a PWM motor DC load directly from an Arduino or ESP32 GPIO pin?

No. Microcontroller GPIO pins are limited to 20mA (Arduino Uno) or 40mA (ESP32) absolute maximum. A small hobby DC motor typically requires 200mA to several amps just to start spinning. Connecting a motor directly to a GPIO pin will instantly destroy the microcontroller's internal silicon traces. You must always use a motor driver IC, a logic-level MOSFET, or a relay as an intermediary switch.

Why does my DC motor whine loudly when I use analogWrite() on an Arduino?

The default PWM frequency for most Arduino analogWrite() pins is roughly 490Hz, which sits squarely in the middle of the human audible range. The rapid switching of the voltage causes the motor's internal components to vibrate at that exact frequency. To fix this, you need to reconfigure the Arduino's hardware timers (e.g., Timer1) to output a 20kHz PWM signal, which is above human hearing.

How do I reverse a brushed DC motor using only a single PWM pin?

You cannot reverse a standard 2-wire brushed DC motor with a single PWM pin and a single transistor. A single MOSFET can only turn the motor on and off. To reverse the direction, you must physically swap the polarity of the voltage applied to the motor terminals. This requires an H-bridge motor driver (which uses two logic pins for direction and one for PWM) or a mechanical DPDT relay wired in an H-bridge configuration.

What happens if I send a 3.3V PWM signal to a 24V industrial motor driver?

It depends entirely on the driver's logic threshold specifications. Many modern hobby drivers (like those based on the TB6612FNG) accept logic levels from 2.7V to 5.5V, so a 3.3V ESP32 signal works perfectly. However, industrial 24V motor controllers often use optoisolators or discrete logic gates that require a minimum of 5V or even 10V to register a "HIGH" state. If your 3.3V signal is ignored, you must use a logic level shifter or an optocoupler to bridge the voltage gap.