Components · 5 min read

DC Motor Control with the L298N: Speed and Direction with Arduino

How does the L298N motor driver work? The H-bridge idea, ENA, IN1 and IN2 pins, the 5V jumper and power wiring, speed with PWM, changing direction, two-motor robot car code, and ESP32 and Pico usage.

DC motors are the most common motors, spinning fans, robot wheels, water pumps and toy cars. But you can't connect a motor straight to an Arduino pin: it draws far more current than the pin can supply, and changing its direction means reversing its polarity. The L298N motor driver solves both problems at once: it runs two DC motors forwards and backwards independently and sets their speed with PWM. You'll find it in almost every robot car project.

L298N dual motor driver module
L298N motor driver: under the black heatsink sits the L298N chip with two H-bridges; motor terminals are on both sides, with the power and control pins at the front.

How does a DC motor work, and why does it need a driver?

Apply a voltage across a DC motor's two terminals and it spins; reverse the polarity and it spins the other way; lower the voltage and it slows down. Even a small toy motor draws hundreds of milliamps while running, and more than 1 amp when starting or stalled. And because the motor is a coil, it produces reverse voltage spikes when it switches off. An Arduino pin can supply at most 20–40 mA and isn't protected against those spikes; connecting the motor directly destroys the pin and can even damage the board.

What is an H-bridge?

The way to run a motor in both directions is an H-bridge: four electronic switches arranged around the motor in the shape of the letter "H". When two diagonally opposite switches close, current flows through the motor one way; when the other diagonal pair closes, it flows the other way. The L298N chip contains two such H-bridges, so it can control two motors independently. Each motor uses two direction pins (IN1 and IN2) and one speed pin (ENA):

IN1IN2ENAWhat the motor does
HIGHLOWHIGH or PWMTurns forwards
LOWHIGHHIGH or PWMTurns backwards
HIGHHIGHHIGHBrakes and stops quickly
AnyAnyLOWFree-wheels and slows down on its own

L298N specifications

FeatureValue
Motor supply voltage5–35 V (max 12 V with the 5V jumper fitted)
Current per channel2 A continuous, 3 A peak
Logic voltage5 V (inputs also recognise a 3.3 V signal)
Voltage dropAbout 1.5–3 V (the motor sees that much less)
Motors it can drive2 DC motors or 1 bipolar stepper motor
ProtectionFlyback diodes on the board
Geared DC motor and wheel set
The yellow geared DC motor and wheel used in robot cars: the gearbox lowers the speed and raises the torque; it runs on 3–6 V.

L298N pins and power wiring

Pin or terminalFunction
OUT1, OUT2The two leads of motor A
OUT3, OUT4The two leads of motor B
12V (VS)Motor supply: positive of the battery or adapter
GNDCommon ground: battery negative and the Arduino's GND go here
5V5 V output with the 5V jumper fitted, logic supply input with it removed
ENA, ENBSpeed inputs (PWM); with their jumpers fitted the motor always runs at full speed
IN1, IN2, IN3, IN4Direction inputs
The battery's negative, the L298N's GND and the Arduino's GND must all be connected together; without a common ground the control signals mean nothing. If the motor supply is above 12 V, remove the 5V jumper on the board and feed a separate 5 V into the 5V pin. Never power motors from the Arduino's 5V pin.

Running a motor forwards, backwards and at different speeds

First remove the jumper on ENA and connect ENA to Arduino pin D9, IN1 to D8 and IN2 to D7. Connect the motor to OUT1 and OUT2, and a pack of 2 × 18650 cells (7.4 V) or 4–6 AA batteries to the 12V and GND terminals; run GND to the Arduino's GND as well. The motor() function below takes a value from -255 to 255: positive means forwards, negative backwards and zero brake. The idea behind speed control is in What Is PWM?

Arduino (C++)
1const int ENA = 9;    // hız (PWM) / speed (PWM)
2const int IN1 = 8;
3const int IN2 = 7;
4
5void motor(int speed) {              // -255 … 255
6  if (speed == 0) {                  // fren / brake
7    digitalWrite(IN1, HIGH);
8    digitalWrite(IN2, HIGH);
9    analogWrite(ENA, 255);
10    return;
11  }
12  digitalWrite(IN1, speed > 0);      // ileri ya da geri / forward or backward
13  digitalWrite(IN2, speed < 0);
14  analogWrite(ENA, abs(speed));
15}
16
17void setup() {
18  pinMode(ENA, OUTPUT);
19  pinMode(IN1, OUTPUT);
20  pinMode(IN2, OUTPUT);
21}
22
23void loop() {
24  motor(200);   delay(2000);   // ileri / forward
25  motor(0);     delay(500);    // dur / stop
26  motor(-120);  delay(2000);   // yavaşça geri / slowly backward
27  motor(0);     delay(500);
28}
Most motors hum instead of turning at low PWM values; they usually need a value of around 80–120 to start moving. Stopping the motor briefly before changing direction, and increasing the speed gradually rather than all at once, both reduce sudden current draw and protect the gears.

A two-motor robot car: forwards, backwards, left and right

Robot cars have no steering; they turn by spinning the two wheels at different speeds and directions. If both motors run forwards the car goes straight; if the left motor runs backwards and the right one forwards, the car spins left on the spot. The drive() function below takes each motor's speed separately, from -255 to 255:

Arduino (C++)
1// Sol motor / left motor: ENA=9, IN1=8, IN2=7 — Sağ motor / right motor: ENB=10, IN3=5, IN4=4
2const int ENA = 9, IN1 = 8, IN2 = 7;
3const int ENB = 10, IN3 = 5, IN4 = 4;
4
5void drive(int left, int right) {            // her biri -255 … 255 / each -255 … 255
6  digitalWrite(IN1, left >= 0);  digitalWrite(IN2, left < 0);
7  digitalWrite(IN3, right >= 0); digitalWrite(IN4, right < 0);
8  analogWrite(ENA, abs(left));
9  analogWrite(ENB, abs(right));
10}
11
12void setup() {
13  int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
14  for (int p : pins) pinMode(p, OUTPUT);
15}
16
17void loop() {
18  drive(200, 200);   delay(1500);   // ileri / forward
19  drive(-200, 200);  delay(600);    // sola dön / turn left
20  drive(200, -200);  delay(600);    // sağa dön / turn right
21  drive(-180, -180); delay(1000);   // geri / backward
22  drive(0, 0);       delay(1000);   // dur / stop
23}

Add a distance sensor to the front of the car and you have a robot that stops and turns when it sees an obstacle; for the sensor side, see HC-SR04 Distance Sensor. If you'll use the Servo library on an Uno, be careful: it disables PWM on pins 9 and 10, so move ENA and ENB to pins 5 and 6.

L298N with the ESP32 and Raspberry Pi Pico

The L298N's inputs treat anything above about 2.3 V as HIGH, so they work directly with the 3.3 V signals of the ESP32 and Pico; the board's logic supply should still be 5 V. On the ESP32 you can use the same Arduino code with PWM-capable pins for ENA and ENB (for example GPIO 25 and 26); pins 34–39 can't output. On the Pico with MicroPython, controlling one motor looks like this:

MicroPython
1from machine import Pin, PWM
2import time
3
4ena = PWM(Pin(15), freq=1000)
5in1 = Pin(14, Pin.OUT)
6in2 = Pin(13, Pin.OUT)
7
8def motor(speed):                   # -100 … 100
9    in1.value(speed > 0)
10    in2.value(speed < 0)
11    ena.duty_u16(int(abs(speed) * 655.35))
12
13while True:
14    motor(80);  time.sleep(2)       # ileri / forward
15    motor(0);   time.sleep(0.5)     # dur / stop
16    motor(-50); time.sleep(2)       # geri / backward

L298N, TB6612FNG or MOSFET?

DriverProsConsBest for
L298NCheap, rugged, 2 A per channelAbout 2 V lost, gets hot, largeHobby robots, 6–12 V motors
TB6612FNGSmall, efficient (MOSFET), 3.3 V compatible1.2 A continuous, max 13.5 VSmall battery robots
L9110SVery small and cheapAbout 800 mA per channelMini motors
Single MOSFET (such as the IRLZ44N)Very efficient, high currentOne direction onlyFans, pumps, LED strips

If you only need to switch a motor on and off, a relay will do, but it can't adjust the speed; we compared the two in What Is a Relay Module? To choose a suitable transistor or MOSFET, have a look at the Transistors tool.

L298N project ideas

  • Obstacle-avoiding robot: a car that sees obstacles with an HC-SR04 and changes direction.
  • Bluetooth-controlled car: a robot steered over an HC-05 with an app on your phone.
  • Joystick-controlled car: turn a joystick's two axes into the speeds of two motors; details in How to Use a Joystick Module.
  • Line-following robot: a car that follows a black line on the floor with infrared sensors.
  • Automatic curtain: a motorised system that opens the curtain when light arrives in the morning and closes it in the evening.
  • Conveyor belt: a small conveyor whose speed you set with a potentiometer.

Common mistakes and how to fix them

  • The board's LED is on but the motor doesn't turn: the grounds aren't shared, the ENA jumper was removed but the pin isn't connected, or the PWM value is too low.
  • The Arduino resets when the motor runs: the motor and the Arduino share a weak supply; power them separately and solder a 100 nF capacitor across the motor terminals.
  • The motor is very slow and weak: the L298N swallows about 2 V; raise the battery voltage (for example 2 × 18650) or use a more efficient driver.
  • The motor only turns one way: one of the IN pins isn't connected, or the code writes the same values for both directions.
  • The L298N gets very hot: the motor draws too much current; make sure the heatsink is exposed, and choose a beefier driver if needed.
  • Using a 9 V PP3 battery: these can't supply high current and run flat quickly; use a rechargeable 18650 or AA pack.

Once you've learned motor control with the L298N, the door to robot projects opens. In the BlueGrays app you'll find L298N Bluetooth-controlled car and obstacle-avoiding robot projects step by step with circuit diagrams and code.

Frequently asked questions

How many motors can the L298N drive?

Because the L298N contains two H-bridges, it can drive two DC motors independently, forwards and backwards and at different speeds. Using both channels together, it can also drive one bipolar stepper motor.

What is the 5V jumper on the L298N for?

With the jumper fitted, the on-board regulator makes 5 V from the motor supply to power the chip; you can also use that 5 V to power the Arduino. If the motor supply is above 12 V the regulator can overheat, so remove the jumper and feed a separate 5 V into the 5V pin.

What battery should I connect to the L298N?

For small 6–9 V motors, 2 × 18650 lithium cells (7.4 V) or 6 AA batteries (9 V) are a good choice. Because the L298N loses about 2 V, pick a supply a little above the motor's rated voltage. 9 V PP3 batteries can't deliver enough current to drive motors.

Why remove the ENA jumper?

With the jumper on ENA fitted, the motor always runs at full speed. To adjust the speed, remove the jumper and connect the ENA pin to one of the Arduino's PWM pins; you can then set the speed from 0 to 255 with analogWrite.

Why won't my motor turn at low speeds?

A motor needs a certain minimum voltage to overcome friction and start moving, and the L298N's voltage drop makes this harder. Usually, when the PWM value drops below 80–120, the motor just hums. Set a minimum speed in your code or use a higher-voltage supply.

Does the L298N work with the ESP32 and Raspberry Pi Pico?

Yes. The L298N's input pins recognise a 3.3 V signal as HIGH, so it can connect directly to the ESP32 and Pico. The board's logic side should still be powered from 5 V, and all grounds must be shared.

See all projects
Bluetooth Controlled Car with L298N
#80Advanced
Premium

Bluetooth Controlled Car with L298N

2WD (two-motor, four-wheeled) robot car project that can be controlled from the phone with Arduino and HC-05 Bluetooth module. A total of four wheels are driven simultaneously by connecting two motors

5.0(38)
64
Obstacle Avoidance Robot
#81Advanced
Premium

Obstacle Avoidance Robot

How about building a smart vehicle that finds its own way? The Obstacle Avoidance Robot constantly scans its surroundings thanks to the ultrasonic sensor in front of it. When it encounters an obstacle

5.0(38)
49
Servo Control with Joystick
#60Intermediate
Premium

Servo Control with Joystick

Pan-tilt project that independently controls two servo motors in X and Y axes with joystick module. Teaches the logic of joystick-servo integration and position tracking.

4.7(42)
58
ESP32 Servo Motor (Potentiometer Control)
#118Intermediate
Premium

ESP32 Servo Motor (Potentiometer Control)

In this project, we control an SG90 servo motor using a potentiometer. We adjust the servo angle by mapping the analog value read from the potentiometer to the 0–180-degree range. Thanks to the ESP32Servo library, any GPIO pin on the ESP32 can generate a PWM signal. This is a fundamental control method for robotic arms, camera gimbals, and automatic door mechanisms.

4.3(29)
42
Led Control with Joystick
#59Intermediate
Premium

Led Control with Joystick

Control project that lights LEDs in 4 different directions according to the X and Y axis values of the joystick module. Teaches analog joystick reading and direction detection logic.

4.7(50)
66
ESP32 HC-SR04 Ultrasonic Distance Sensor
#116Intermediate
Premium

ESP32 HC-SR04 Ultrasonic Distance Sensor

The HC-SR04 ultrasonic sensor calculates distance by measuring the time it takes for the sound wave it emits to bounce off an object and return (Time of Flight). In this project, we will send a 10-microsecond pulse to the TRIG pin of the ESP32 and read the echo duration from the ECHO pin using `pulseIn()`. We will display the calculated distance in centimeters on the Serial Monitor. Since the HC-SR04 operates at 5V, a **voltage divider** is required on the ECHO pin—otherwise, the ESP32’s 3.3V GP

4.9(27)
43
ESP32 Parking Sensor (HC-SR04 + 5-LED Bar + Buzzer + OLED)
#142Advanced
Premium

ESP32 Parking Sensor (HC-SR04 + 5-LED Bar + Buzzer + OLED)

The ESP32 version of the car parking sensor! We use the HC-SR04 ultrasonic sensor to measure the distance to the object in front of it. As the distance decreases, the 5-LED bar fills up (green → yellow → red) and the buzzer beep interval shortens. When the object gets very close (under 10 cm), a continuous alarm sounds and all LEDs light up. The SSD1306 OLED display shows the current distance in cm in large font, a status message (STOP / CAUTION / CLOSE / STOP! / DANGER), and a simulation of the

0.0(0)
14
HC-SR04 Distance Measurement (Serial Display)
#27Beginner

HC-SR04 Distance Measurement (Serial Display)

Project that measures distance with HC-SR04 ultrasonic sensor and displays the result in cm on Serial Monitor. It teaches the principle of distance calculation with sound wave.

4.6(44)
65

Learn why a DC motor can't connect straight to Arduino, how an H-bridge works, the L298N's pins and power wiring, speed and direction control with PWM, and a two-motor robot car step by step.

DC Motor Control with the L298N: Speed and Direction with Arduino | BlueGrays