Sizing and driving a DC PWM motor with a microcontroller like an ESP32 or Arduino Nano is a rite of passage for embedded builders. Yet, it remains one of the most common sources of project failure, usually resulting in melted H-bridges, brownout resets, or audible whining. The direct answer to reliable motor control is this: you must match the motor's stall current—not its nominal running current—to a MOSFET-based driver capable of handling that peak load, while isolating your microcontroller's logic voltage from the motor's power rail.

This guide cuts through the generic advice. We will cover exact sizing math, compare motor topologies, detail the wiring for modern drivers, and decode the physical failure signatures your hardware will exhibit when things go wrong.

Sizing a DC PWM Motor: The 150% Rule and Load Profiling

The most frequent mistake on the workbench is sizing a motor driver based on the motor's datasheet 'nominal' or 'no-load' current. When a DC motor starts, or when it encounters a mechanical bind, it draws stall current. This can be 5 to 10 times higher than the running current. If your driver cannot supply this inrush, it will either trigger thermal shutdown or physically melt the internal bond wires.

The 150% Sizing Rule of Thumb: Always select a motor driver whose continuous current rating exceeds your motor's maximum expected continuous load by at least 50%, and whose peak current rating exceeds the motor's absolute stall current.

Worked Load Example: 12V Conveyor Gearmotor

Imagine you are building a small parts conveyor using a 12V brushed DC gearmotor. The datasheet lists the following specs:

  • No-load current: 0.3A
  • Rated continuous load current: 1.2A
  • Stall current: 4.8A

If you select a standard L298N driver (rated for 2A continuous), the motor will spin fine on your desk. But the moment you put parts on the conveyor belt, the startup inrush hits 4.8A. The L298N's internal BJT transistors will overheat in seconds, and its thermal protection will shut it down, or worse, it will fail shorted.

The Fix: Apply the 150% rule to the continuous load (1.2A × 1.5 = 1.8A minimum continuous). However, you must also survive the 4.8A stall. You need a driver rated for at least 3A to 5A continuous, such as the TI DRV8871 (3.6A continuous) or a BTS7960 module (43A peak). Furthermore, your 12V power supply must be rated for at least 60W (12V × 5A) to prevent voltage sag during startup.

Motor Topology Comparison: Which Type Fits Your Load?

Not all 'DC motors' behave the same way under PWM control. Before wiring up your driver, you must confirm the motor topology matches your mechanical load profile. Treating a stepper motor like a simple brushed DC motor, or assuming a servo can hold a static load indefinitely, will destroy your hardware.

Motor Type Comparison for Embedded Projects
Motor Type Torque Curve Profile Microcontroller Control Needs Relative Cost Best Load Profile
Brushed DC (BDC) Maximum torque at zero RPM (stall); drops linearly as speed increases. Simple PWM for speed, H-bridge for direction. 2 GPIO pins. Low ($3 - $15) Wheels, conveyors, fans, pumps. High starting torque needed.
NEMA Stepper High holding torque at zero RPM; torque drops sharply at higher speeds. Step/Dir pulses or 4-phase commutation. Requires dedicated chopper driver (e.g., A4988). Medium ($12 - $30) 3D printers, CNC, precise linear actuators. Open-loop positioning.
Brushless DC (BLDC) Flat, high torque across a wide RPM range. Highly efficient. 3-phase commutation via ESC or complex FOC (Field Oriented Control) algorithms. High ($25 - $80+) Drones, high-speed spindles, heavy-load robotics. High continuous power.
Coreless DC Low inertia, very fast acceleration. Lower absolute torque than iron-core BDC. PWM + H-bridge. Requires high-frequency PWM to avoid cogging. Medium-High ($15 - $40) Camera gimbals, precision valves, medical devices.

Decision Framework: If your application requires moving a heavy load from a dead stop (like a robot chassis on carpet), a Brushed DC motor is the correct choice due to its peak stall torque. If you need to move a load to an exact millimeter position without an encoder, use a Stepper. Never use a standard RC servo for continuous rotation or static heavy-load holding; servos are designed for intermittent positional sweeps and will overheat and strip their internal potentiometers if forced to hold a heavy static load continuously.

Driver Selection and Wiring: TB6612FNG vs. DRV8871

Once you have selected a brushed DC PWM motor, you need an H-bridge driver to interface it with your ESP32 or Arduino. The ancient L298N is obsolete for modern battery-powered projects due to its massive 2V voltage drop across its BJT transistors. Modern designs use MOSFET-based drivers.

Driver Spec Sheet Comparison

Modern MOSFET Motor Driver Specifications
Driver IC Continuous Current Peak Current Voltage Drop (Rds_on) Logic Voltage (VCC) Best Use Case
TB6612FNG 1.2A (per channel) 3.2A ~0.5V 2.7V - 5.5V Small 6V-12V robot chassis, dual motor control.
DRV8871 3.6A 4.5A ~0.6V Not required (Logic built-in) Medium actuators, single heavy 12V/24V motor.
BTS7960 24A (with cooling) 43A Very Low 5.5V - 27V E-bike conversions, large winches, 24V/48V systems.

Wiring the TB6612FNG to an ESP32

The TB6612FNG is the workhorse for dual-motor ESP32 projects. However, its breakout boards often cause confusion due to the separation of logic and motor power.

  • VM (Motor Voltage): Connect to your main battery/power supply (e.g., 12V). This powers the motors.
  • VCC (Logic Voltage): Connect to the ESP32's 3.3V pin. Do not connect this to 5V if you are using a standard ESP32, or you risk back-feeding the 3.3V regulator.
  • STBY (Standby): Must be pulled HIGH (to 3.3V) for the driver to operate. Many beginners leave this floating, and the motor refuses to spin.
  • PWMA / PWMB: Connect to ESP32 hardware PWM-capable GPIOs (e.g., GPIO 16 and 17).
  • AIN1, AIN2 (Direction): Connect to standard digital GPIOs. Set one HIGH and one LOW for forward; reverse them for backward.
  • AO1, AO2: Motor terminals. Polarity doesn't matter; swap wires if the motor spins the wrong way.
  • GND: Must be shared between the ESP32 GND, the motor power supply GND, and the driver GND. A missing common ground is the #1 cause of erratic motor behavior.

Failure Signatures: Decoding Hums, Stalls, and Thermal Runaway

When a DC PWM motor system fails, it rarely does so silently. The physical symptoms tell you exactly what is going wrong electrically. Here is how to diagnose the three most common bench failures.

1. The Audible Whine or Hum

Symptom: The motor spins, but emits a high-pitched whine or a low buzzing hum.
Cause: Your PWM frequency is set within the human hearing range (typically 1kHz to 4kHz). Alternatively, the motor is mechanically stalled, but the driver is still pushing current at a low duty cycle, causing the stator laminations to vibrate.
Fix: Move the PWM frequency above human hearing. On the ESP32 using the LEDC peripheral, configure the frequency to 20,000 Hz (20kHz). In the Arduino ESP32 core, this looks like:

// ESP32 LEDC setup for 20kHz PWM, 8-bit resolution
ledcSetup(0, 20000, 8); 
ledcAttachPin(16, 0);

If the hum persists only when the motor is blocked, your mechanical load is exceeding the motor's stall torque. You need a higher gear reduction ratio.

2. Microcontroller Brownout Resets (The 'Stall Reboot')

Symptom: The ESP32 or Arduino works perfectly on the bench. The moment the motor starts under load, the microcontroller reboots, the WiFi drops, or the serial monitor prints gibberish.
Cause: Motor inrush current causes a massive voltage sag on the shared power rail. The voltage at the microcontroller's VIN or 3.3V pin drops below its brownout detection threshold (typically ~2.8V for the ESP32), triggering an automatic hardware reset.
Fix: Never power high-current motors directly from the microcontroller's onboard 5V/3.3V regulators. Use a dedicated power supply for the motor's VM rail. Furthermore, solder a large bulk electrolytic capacitor (1000µF to 2200µF, rated for at least 25V) directly across the VM and GND terminals on the motor driver. This capacitor acts as a local energy reservoir, supplying the inrush current and preventing the main rail from sagging.

3. Driver Thermal Runaway and Overheat

Symptom: The motor runs fine for two minutes, then stops. The driver IC is too hot to touch. After a minute of cooling, it works again.
Cause: You have tripped the driver's internal thermal shutdown. This happens when the continuous current exceeds the IC's rating, or when the ambient temperature inside your project enclosure rises, lowering the IC's thermal headroom. The L298N is notorious for this because its BJT design dissipates massive heat (P = I²R + V_drop × I).
Fix: Upgrade to a MOSFET-based driver like the DRV8871 or TB6612FNG, which have vastly lower Rds(on) (on-state resistance). If you are already using a MOSFET driver and it still overheats, you must add a physical aluminum heatsink to the IC package or implement software-based current limiting by reading a shunt resistor via the microcontroller's ADC and reducing the PWM duty cycle when current spikes.

Safety Caveat: When working with DC motors rated above 48V or drawing over 20A, the stored inductive energy can cause severe arcing at the terminals. Always use appropriately sized ring terminals, crimp them with a ratcheting crimper, and place a flyback diode (or rely on the driver's internal clamp diodes) to prevent inductive voltage spikes from destroying your circuit.