%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#ECF0F1'}}}%%
flowchart TB
subgraph HBridge[H-Bridge Motor Control Circuit]
VCC[+12V Motor Supply]
MCU[ESP32 GPIO<br/>3.3V Signal<br/>20mA max]
MCU -->|IN1 Signal| DRIVER[Motor Driver<br/>L298N/TB6612]
MCU -->|IN2 Signal| DRIVER
MCU -->|PWM Enable| DRIVER
VCC -->|High Current| DRIVER
DRIVER -->|Forward: IN1=HIGH, IN2=LOW| MOTOR1[Motor Spins<br/>Clockwise]
DRIVER -->|Reverse: IN1=LOW, IN2=HIGH| MOTOR2[Motor Spins<br/>Counter-Clockwise]
DRIVER -->|Brake: Both HIGH or Both LOW| MOTOR3[Motor Stops<br/>Braked]
MOTOR1 --> GND1[Ground]
MOTOR2 --> GND2[Ground]
MOTOR3 --> GND3[Ground]
end
subgraph Control[PWM Speed Control]
PWM0[0% Duty Cycle<br/>Motor OFF]
PWM50[50% Duty Cycle<br/>Half Speed]
PWM100[100% Duty Cycle<br/>Full Speed]
end
MCU -.->|PWM Controls Speed| Control
style MCU fill:#2C3E50,stroke:#16A085,color:#fff
style DRIVER fill:#16A085,stroke:#2C3E50,color:#fff
style MOTOR1 fill:#E67E22,stroke:#2C3E50,color:#fff
style MOTOR2 fill:#E67E22,stroke:#2C3E50,color:#fff
style MOTOR3 fill:#7F8C8D,stroke:#2C3E50,color:#fff
style VCC fill:#E67E22,stroke:#2C3E50,color:#fff
style PWM0 fill:#ECF0F1,stroke:#2C3E50,color:#2C3E50
style PWM50 fill:#16A085,stroke:#2C3E50,color:#fff
style PWM100 fill:#27ae60,stroke:#229954,color:#fff
569 DC Motors
Learning Objectives
After completing this chapter, you will be able to:
- Understand DC motor operating principles and characteristics
- Control DC motor speed using PWM (Pulse Width Modulation)
- Implement bidirectional control using H-bridge circuits
- Interface DC motors with ESP32 using L298N and TB6612 drivers
- Implement PID control for precise speed regulation
- Understand brushless DC (BLDC) motor control basics
569.1 DC Motor Fundamentals
DC motors provide continuous rotational motion, controlled by voltage and PWM for speed regulation.
Characteristics:
- Simple speed control via PWM
- Direction control via H-bridge
- High speed, low precision
- Requires motor driver for high current
569.2 PWM Speed Control
PWM (Pulse Width Modulation) is the standard method for controlling DC motor speed:
- Duty cycle = Percentage of time the signal is HIGH (ON)
- Frequency = How many times per second the signal repeats (typically 500Hz-20kHz for motors)
- Average power = Supply voltage x Duty cycle percentage
Why use PWM? Digital microcontrollers can’t produce true analog voltages. Instead, they rapidly switch between 0V and 5V. A motor responds to the average voltage over time, creating smooth control without complex analog circuits.
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#ECF0F1'}}}%%
gantt
title PWM Duty Cycle Waveforms (5V Supply, 1kHz = 1ms period)
dateFormat X
axisFormat %L
section 0% Duty
OFF (0V avg) :0, 1000
section 25% Duty
HIGH (1.25V avg) :0, 250
LOW :250, 1000
section 50% Duty
HIGH (2.5V avg) :0, 500
LOW :500, 1000
section 75% Duty
HIGH (3.75V avg) :0, 750
LOW :750, 1000
section 100% Duty
HIGH (5V avg) :0, 1000
569.2.1 PWM Frequency Selection
Option A: Low PWM frequency (1 kHz): Minimal switching losses (<1% power loss), audible motor whine at 1kHz, coarse current ripple causing motor heating, suitable for high-inertia loads (fans, pumps), driver efficiency 95-98%
Option B: High PWM frequency (20 kHz): Switching losses increase to 3-5%, inaudible operation (above human hearing), smooth current with reduced ripple/heating, required for precision positioning (servos, gimbals), driver efficiency 90-95%
Decision Factors: For consumer products (smart blinds, HVAC dampers), use 20kHz to eliminate audible noise complaints. For industrial pumps where noise is acceptable and efficiency matters, use 1-5kHz. Stepper motors typically use 1-2kHz to maintain torque at steps.
569.3 L298N Motor Driver Implementation
The L298N is a popular dual H-bridge driver capable of controlling two DC motors or one stepper motor.
// L298N H-Bridge Motor Driver
#define MOTOR_IN1 26
#define MOTOR_IN2 27
#define MOTOR_EN 14 // PWM pin
// PWM Configuration
const int pwmFreq = 5000; // 5 kHz
const int pwmChannel = 0;
const int pwmResolution = 8; // 0-255
void setup() {
Serial.begin(115200);
// Configure pins
pinMode(MOTOR_IN1, OUTPUT);
pinMode(MOTOR_IN2, OUTPUT);
// Configure PWM
ledcSetup(pwmChannel, pwmFreq, pwmResolution);
ledcAttachPin(MOTOR_EN, pwmChannel);
Serial.println("DC Motor Controller Ready");
}
void loop() {
// Forward at 50% speed
motorControl(150, true);
delay(2000);
// Stop
motorControl(0, true);
delay(1000);
// Backward at 75% speed
motorControl(191, false);
delay(2000);
// Stop
motorControl(0, true);
delay(1000);
// Gradual acceleration
for(int speed = 0; speed <= 255; speed += 5) {
motorControl(speed, true);
delay(50);
}
// Gradual deceleration
for(int speed = 255; speed >= 0; speed -= 5) {
motorControl(speed, true);
delay(50);
}
delay(1000);
}
void motorControl(int speed, bool forward) {
// Constrain speed to 0-255
speed = constrain(speed, 0, 255);
// Set direction
if (forward) {
digitalWrite(MOTOR_IN1, HIGH);
digitalWrite(MOTOR_IN2, LOW);
} else {
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, HIGH);
}
// Set speed
ledcWrite(pwmChannel, speed);
Serial.print("Motor: ");
Serial.print(forward ? "Forward" : "Backward");
Serial.print(" @ Speed ");
Serial.println(speed);
}
void motorBrake() {
// Short brake (both inputs HIGH)
digitalWrite(MOTOR_IN1, HIGH);
digitalWrite(MOTOR_IN2, HIGH);
ledcWrite(pwmChannel, 255);
}
void motorCoast() {
// Coast to stop (both inputs LOW)
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, LOW);
ledcWrite(pwmChannel, 0);
}569.4 PID Motor Speed Control
For precise speed control, use a PID (Proportional-Integral-Derivative) controller with encoder feedback.
#include <PID_v1.h>
// Encoder pins
#define ENCODER_A 32
#define ENCODER_B 33
volatile long encoderCount = 0;
unsigned long lastTime = 0;
float currentRPM = 0;
// PID variables
double setpoint, input, output;
double Kp = 2.0, Ki = 5.0, Kd = 1.0;
PID motorPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
void setup() {
Serial.begin(115200);
// Setup encoder
pinMode(ENCODER_A, INPUT_PULLUP);
pinMode(ENCODER_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_A), encoderISR, RISING);
// Setup motor pins
pinMode(MOTOR_IN1, OUTPUT);
pinMode(MOTOR_IN2, OUTPUT);
ledcSetup(pwmChannel, pwmFreq, pwmResolution);
ledcAttachPin(MOTOR_EN, pwmChannel);
// Configure PID
setpoint = 100.0; // Target 100 RPM
motorPID.SetMode(AUTOMATIC);
motorPID.SetOutputLimits(0, 255);
motorPID.SetSampleTime(100); // 100ms
}
void loop() {
// Calculate RPM every 100ms
unsigned long now = millis();
if (now - lastTime >= 100) {
// Calculate RPM (assuming 20 pulses per revolution)
currentRPM = (encoderCount * 60.0 * 1000.0) / (20.0 * (now - lastTime));
encoderCount = 0;
lastTime = now;
// Update PID
input = currentRPM;
motorPID.Compute();
// Apply motor control
motorControl((int)output, true);
// Debug output
Serial.print("Target: ");
Serial.print(setpoint);
Serial.print(" RPM | Current: ");
Serial.print(currentRPM);
Serial.print(" RPM | PWM: ");
Serial.println(output);
}
}
void encoderISR() {
if (digitalRead(ENCODER_B) == HIGH) {
encoderCount++;
} else {
encoderCount--;
}
}569.5 Worked Examples
Scenario: You are designing a smart ceiling fan controller using an ESP32 and a 12V DC motor. The motor runs at 3000 RPM at full voltage and you need 5 discrete speed settings: Off, Low (600 RPM), Medium (1200 RPM), High (1800 RPM), and Max (3000 RPM).
Given:
- Motor supply voltage: 12V DC
- Motor no-load speed at 12V: 3000 RPM
- PWM resolution: 8-bit (0-255)
- PWM frequency: 5 kHz
- Speed is approximately proportional to average voltage
Steps:
- Calculate target duty cycles for each speed:
- Off: 0% duty cycle (0 RPM)
- Low: 600/3000 = 20% duty cycle (600 RPM)
- Medium: 1200/3000 = 40% duty cycle (1200 RPM)
- High: 1800/3000 = 60% duty cycle (1800 RPM)
- Max: 3000/3000 = 100% duty cycle (3000 RPM)
- Convert duty cycles to 8-bit PWM values (0-255):
- Off: 0% x 255 = 0
- Low: 20% x 255 = 51
- Medium: 40% x 255 = 102
- High: 60% x 255 = 153
- Max: 100% x 255 = 255
- Account for motor startup threshold: Most DC motors require ~10-15% duty cycle to overcome static friction. Actual Low setting may need 25-30% (64-77) to reliably start from standstill.
Result: PWM values for 5-speed fan controller: 0 (Off), 64 (Low, adjusted), 102 (Medium), 153 (High), 255 (Max).
Scenario: You need to select a DC motor for a small package sorting conveyor. The conveyor must move packages weighing up to 2 kg at 0.5 m/s using a 50mm diameter drive roller.
Given:
- Maximum package mass: 2 kg
- Conveyor speed: 0.5 m/s
- Drive roller diameter: 50 mm (radius = 0.025 m)
- Coefficient of friction (belt/roller): 0.3
- Safety factor: 1.5
- Available supply voltage: 24V DC
- Gear efficiency: 85%
Steps:
- Calculate required roller angular velocity:
- omega = v / r = 0.5 m/s / 0.025 m = 20 rad/s
- Convert to RPM: 20 rad/s x (60 / 2 x pi) = 191 RPM at output shaft
- Calculate load torque at roller:
- Force to move package: F = m x g x mu = 2 kg x 9.81 m/s^2 x 0.3 = 5.89 N
- Torque at roller: T_load = F x r = 5.89 N x 0.025 m = 0.147 Nm
- Apply safety factor:
- Required torque: T_required = 0.147 Nm x 1.5 = 0.22 Nm (220 mNm)
- Calculate motor power requirement:
- Mechanical power: P_mech = T x omega = 0.22 Nm x 20 rad/s = 4.4 W
- Account for gear efficiency: P_motor = 4.4 W / 0.85 = 5.2 W minimum
- Select motor and gear ratio:
- Typical 24V DC motor: 6000 RPM no-load, 15 mNm stall torque
- Required gear ratio: 6000 RPM / 191 RPM = 31:1
- Torque multiplication: 15 mNm x 31 x 0.85 = 395 mNm (exceeds 220 mNm requirement)
Result: Select a 24V DC motor (6000 RPM, 15 mNm) with 31:1 planetary gearbox.
569.6 Worked Example: Sizing a Motor for a Smart Valve
Scenario: You are designing an IoT-controlled ball valve for a smart irrigation system. The valve is a 1-inch brass ball valve that requires 90 degree rotation to fully open or close. The system operates on 12V DC from a solar-charged battery and must complete valve actuation within 5 seconds.
Goal: Select and size an appropriate motor and gearbox combination.
Ball valve torque specifications (from valve datasheet):
- Breakaway torque (unseating): 2.5 Nm (worst case with sediment buildup)
- Running torque: 0.8 Nm
- Seating torque: 1.5 Nm (ensures tight seal)
Design margin: Apply 1.5x safety factor: T_required = 2.5 Nm x 1.5 = 3.75 Nm
Angular displacement: 90 degrees = 0.25 revolutions
Required speed: omega_output = 0.25 rev / 5 s = 0.05 rev/s = 3 RPM
Option: DC Gearmotor (JGB37-520 12V)
| Parameter | JGB37-520 12V | Requirement | Status |
|---|---|---|---|
| Voltage | 12V DC | 12V DC | Pass |
| No-load speed | 10 RPM | 3 RPM | Pass (margin) |
| Rated torque | 5 Nm | 3.75 Nm | Pass |
| Stall torque | 15 Nm | - | Pass (safety) |
| No-load current | 80 mA | - | OK |
| Rated current | 400 mA | - | OK |
| Gear ratio | 1:488 | - | - |
| Cost | $12 | - | Budget |
Selected: JGB37-520 12V DC gearmotor with L298N driver
Key decisions:
- DC gearmotor over stepper: 3x lower cost, 4x lower power consumption
- 1:488 gear ratio: Converts high-speed/low-torque to low-speed/high-torque
- Limit switch feedback: Prevents motor stall damage
- L298N module: Built-in flyback protection
569.7 Interactive Lab: DC Motor Control
Interactive Challenges:
- Variable Speed Challenge: Add code to smoothly ramp up from 0% to 100% speed over 5 seconds
- Directional Control Challenge: Make the motor alternate between forward and reverse every 3 seconds
- Emergency Stop Challenge: Add a button that immediately stops the motor when pressed
569.8 Brushless DC (BLDC) Motor Control
Brushless DC (BLDC) motors have become the preferred actuator for high-performance IoT applications including drones, robotic arms, electric vehicles, and industrial automation.
569.8.1 Commutation Strategies
Six-Step (Trapezoidal) Commutation:
The simplest control method energizes two phases at a time:
| Step | Hall Sensors (H1 H2 H3) | Active Phases | Current Direction |
|---|---|---|---|
| 1 | 1 0 1 | A+, B- | A to B |
| 2 | 0 0 1 | A+, C- | A to C |
| 3 | 0 1 1 | B+, C- | B to C |
| 4 | 0 1 0 | B+, A- | B to A |
| 5 | 1 1 0 | C+, A- | C to A |
| 6 | 1 0 0 | C+, B- | C to B |
Advantages: Simple implementation, low computational requirements
Disadvantages: Torque ripple (up to 14%), acoustic noise
Sinusoidal Commutation:
Applies continuously varying current to each phase for smoother operation:
- I_A = I_m sin(theta)
- I_B = I_m sin(theta - 120 degrees)
- I_C = I_m sin(theta - 240 degrees)
Field-Oriented Control (FOC):
The most advanced control method for maximum efficiency and smooth operation.
569.8.2 Hardware Implementation
Recommended MCUs for IoT BLDC:
- Entry level: STM32F103, ESP32 (6-step, basic sinusoidal)
- Mid-range: STM32G4, ESP32-S3 (sinusoidal, basic FOC)
- High-performance: STM32H7, TI C2000 (full FOC with observers)
569.9 What’s Next?
Now that you understand DC motor control, you’re ready to explore servo motors for precise angular positioning.