A DC motor is one of the most common actuators in electronics -- it converts electrical energy into rotational motion. However, you cannot connect a DC motor directly to an ESP32 GPIO pin. The GPIO can only supply about $12\,\text{mA}$, while even a small motor needs hundreds of milliamps. You also have no way to reverse the motor's direction with a single pin. That is where a motor driver comes in.
The L298N is a dual H-bridge motor driver that solves both problems. It can power motors at much higher voltages and currents than the ESP32 can provide, and it lets you control both direction and speed from your code. In this guide, you will learn how an H-bridge works, how to wire the L298N, and how to control a DC motor's speed and direction.
This guide uses the ESP32-WROOM-32 DevKit. Pin labels and GPIO numbers may differ on your board -- always check your board's pinout diagram.
🔗Key Specs
| Parameter | Value |
|---|---|
| Motor supply voltage | $5$ to $35\,\text{V}$ DC |
| Logic voltage | $5\,\text{V}$ (onboard regulator available) |
| Max current per channel | $2\,\text{A}$ |
| Channels | 2 (dual H-bridge, can drive 2 motors) |
| Speed control | PWM on enable pin |
| Direction control | IN1/IN2 logic levels |
Note: The L298N has a voltage drop of approximately $1.5$ to $2\,\text{V}$ internally. If you power it with $12\,\text{V}$, your motor will see roughly $10$ to $10.5\,\text{V}$. Keep this in mind when choosing a power supply.
Which motor type? DC motors spin continuously with speed control. Need to move to a specific angle? See servo motors. Need precise stepping? See stepper motors. Our motor comparison guide explains the differences.
🔗What Is an H-Bridge?
An H-bridge is a circuit arrangement of four switches (transistors) that allows you to reverse the direction of current through a load -- in this case, a motor. The name comes from the shape of the circuit when drawn schematically (it looks like the letter H).
graph LR
subgraph H-Bridge
S1[Switch 1] --- M[Motor]
S2[Switch 2] --- M
M --- S3[Switch 3]
M --- S4[Switch 4]
end
S1 --- VCC[V+]
S2 --- GND1[GND]
S3 --- VCC
S4 --- GND2[GND]- Close S1 and S4 (open S2 and S3): current flows left-to-right through the motor -- it spins one way
- Close S2 and S3 (open S1 and S4): current flows right-to-left -- motor spins the other way
- Open all switches: motor coasts to a stop
- Close S1 and S3 (or S2 and S4): motor brakes (both terminals shorted)
The L298N contains two full H-bridges, so it can drive two motors independently.
🔗What You'll Need
| Component | Qty | Notes | Buy |
|---|---|---|---|
| ESP32 dev board | 1 | AliExpress | Amazon.de .co.uk .com | |
| L298N motor driver module | 1 | AliExpress | Amazon.de .co.uk .com | |
| DC motor | 1 | AliExpress | Amazon.de .co.uk .com | |
| 5V power supply | 1 | Or 12V depending on your motor | Amazon.de .co.uk .com |
| Breadboard | 1 | AliExpress | Amazon.de .co.uk .com | |
| Jumper wires | 7 | AliExpress | Amazon.de .co.uk .com |
Links marked Amazon/AliExpress are affiliate links. We may earn a small commission at no extra cost to you.
🔗Wiring
🔗Motor and Power Connections
| L298N Terminal | Connection |
|---|---|
| Motor A OUT1 | DC motor wire 1 |
| Motor A OUT2 | DC motor wire 2 |
| +12V (VMS) | External power supply positive ($6$--$12\,\text{V}$ typical) |
| GND | External power supply GND and ESP32 GND |
🔗Control Connections
| L298N Pin | ESP32 Pin | Function |
|---|---|---|
| IN1 | GPIO 25 | Direction control input 1 |
| IN2 | GPIO 26 | Direction control input 2 |
| ENA | GPIO 27 | Speed control (PWM) |
Important: Remove the ENA jumper on the L298N board. When the jumper is in place, the motor runs at full speed whenever IN1 or IN2 is HIGH. Removing it lets you control speed via PWM on the ENA pin.
Shared ground is critical. The ESP32 GND and the external motor power supply GND must be connected together. Without this, the logic signals from the ESP32 have no voltage reference and the motor driver will not respond.
🔗Direction Control Logic
| IN1 | IN2 | Motor Action |
|---|---|---|
| HIGH | LOW | Forward |
| LOW | HIGH | Reverse |
| LOW | LOW | Coast (stop) |
| HIGH | HIGH | Brake (stop) |
🔗Code Example: Direction and Speed Control
This sketch spins the motor forward at increasing speed, stops, then reverses at full speed.
#define IN1_PIN 25
#define IN2_PIN 26
#define ENA_PIN 27
void setup() {
Serial.begin(115200);
pinMode(IN1_PIN, OUTPUT);
pinMode(IN2_PIN, OUTPUT);
// Attach ENA to LEDC for PWM speed control (5 kHz, 8-bit resolution)
ledcAttach(ENA_PIN, 5000, 8);
Serial.println("Motor driver ready.");
}
void motorForward(int speed) {
digitalWrite(IN1_PIN, HIGH);
digitalWrite(IN2_PIN, LOW);
ledcWrite(ENA_PIN, speed); // 0-255
}
void motorReverse(int speed) {
digitalWrite(IN1_PIN, LOW);
digitalWrite(IN2_PIN, HIGH);
ledcWrite(ENA_PIN, speed);
}
void motorStop() {
digitalWrite(IN1_PIN, LOW);
digitalWrite(IN2_PIN, LOW);
ledcWrite(ENA_PIN, 0);
}
void loop() {
// Accelerate forward
Serial.println("Forward - accelerating...");
for (int speed = 0; speed <= 255; speed += 5) {
motorForward(speed);
delay(50);
}
delay(2000);
// Stop
Serial.println("Stopping...");
motorStop();
delay(1000);
// Full speed reverse
Serial.println("Reverse - full speed");
motorReverse(255);
delay(2000);
// Stop
Serial.println("Stopping...");
motorStop();
delay(2000);
}🔗How It Works
The ESP32 controls the L298N through three signals:
IN1 and IN2 set the motor direction by controlling which pair of transistors in the H-bridge are active. These are digital signals -- just HIGH or LOW.
ENA controls the motor speed using PWM. The L298N's H-bridge rapidly switches the motor on and off. The duty cycle determines the effective voltage reaching the motor:
$$V_{motor} \approx \frac{\text{dutyCycle}}{255} \times V_{supply}$$
At a duty cycle of 128 (50%), the motor receives roughly half the supply voltage and runs at approximately half speed.
Note: Most DC motors need a minimum voltage to overcome internal friction and start spinning. Do not be surprised if duty cycle values below 50--80 (roughly 20--30%) produce no movement. This is normal.
🔗Driving Two Motors
The L298N has a second channel (IN3, IN4, ENB) that works identically. Connect a second motor to OUT3/OUT4 and control it independently. This is the basis for differential-drive robots, where each wheel is controlled separately.
🔗Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| Motor does not spin | ENA jumper removed but no PWM signal | Verify ledcAttach() and ledcWrite() on ENA pin |
| Motor only runs at full speed | ENA jumper still in place | Remove the jumper and use PWM on the ENA pin |
| Motor runs but ESP32 resets | No shared ground between supplies | Connect external supply GND to ESP32 GND |
| Motor spins the wrong direction | IN1/IN2 swapped | Swap the IN1 and IN2 pin assignments in code or wiring |
| Motor vibrates but does not spin | PWM duty cycle too low | Increase the duty cycle -- motors need a minimum voltage to start |
| L298N gets very hot | Motor draws near the $2\,\text{A}$ limit | Add a heatsink or use a more powerful driver (such as BTS7960) |
🔗Next Steps
- Build a two-wheel robot by adding a second motor on Channel B
- Add an ultrasonic distance sensor for obstacle avoidance
- Control the motor speed over WiFi from your phone
- Use encoder feedback for precise speed and position control