DC Motors with L298N Driver

How to drive DC motors using the L298N motor driver and ESP32

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

ParameterValue
Motor supply voltage$5$ to $35\,\text{V}$ DC
Logic voltage$5\,\text{V}$ (onboard regulator available)
Max current per channel$2\,\text{A}$
Channels2 (dual H-bridge, can drive 2 motors)
Speed controlPWM on enable pin
Direction controlIN1/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

ComponentQtyNotesBuy
ESP32 dev board1AliExpress | Amazon.de .co.uk .com
L298N motor driver module1AliExpress | Amazon.de .co.uk .com
DC motor1AliExpress | Amazon.de .co.uk .com
5V power supply1Or 12V depending on your motorAmazon.de .co.uk .com
Breadboard1AliExpress | Amazon.de .co.uk .com
Jumper wires7AliExpress | 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 TerminalConnection
Motor A OUT1DC motor wire 1
Motor A OUT2DC motor wire 2
+12V (VMS)External power supply positive ($6$--$12\,\text{V}$ typical)
GNDExternal power supply GND and ESP32 GND

🔗Control Connections

L298N PinESP32 PinFunction
IN1GPIO 25Direction control input 1
IN2GPIO 26Direction control input 2
ENAGPIO 27Speed 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

IN1IN2Motor Action
HIGHLOWForward
LOWHIGHReverse
LOWLOWCoast (stop)
HIGHHIGHBrake (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:

  1. 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.

  2. 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

ProblemPossible CauseSolution
Motor does not spinENA jumper removed but no PWM signalVerify ledcAttach() and ledcWrite() on ENA pin
Motor only runs at full speedENA jumper still in placeRemove the jumper and use PWM on the ENA pin
Motor runs but ESP32 resetsNo shared ground between suppliesConnect external supply GND to ESP32 GND
Motor spins the wrong directionIN1/IN2 swappedSwap the IN1 and IN2 pin assignments in code or wiring
Motor vibrates but does not spinPWM duty cycle too lowIncrease the duty cycle -- motors need a minimum voltage to start
L298N gets very hotMotor draws near the $2\,\text{A}$ limitAdd 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