From the workshop: Arduino Uno R3 Development Board (ATmega328P) With USB Cable

View product
All articles
Robotics

🤖How to Control DC Motors for a Robot Car: L298N Motor Driver with Arduino (4 Experiments)

Why an Arduino can't drive a motor directly, how an H-bridge reverses direction, how to wire the L298N driver, and four hands-on experiments that end with a robot car driving a square.

TThinking Robot Team 7 min read
H-bridge diagram and L298N motor driver wiring for an Arduino robot car
In this article (17)

Almost every first robot is a car: two wheels, two DC motors, a battery and a microcontroller. The moment you try to plug a motor into an Arduino pin, though, you hit the first real lesson of robotics — a microcontroller can think, but it can't push much current.

This guide shows how to control DC motors properly with an H-bridge and the popular L298N motor driver, then walks through four experiments that turn two motors into a robot that drives a square. It is written for students and makers building their first robot, and for parents helping them.

Why not connect the motor straight to the Arduino?

Arduino Uno pinSmall yellow "BO" gear motor
Voltage5 V3 V – 6 V (often run at 6 V – 7 V)
Current20 mA recommended, 40 mA absolute maximum100 – 200 mA running, much more when starting or stalled
What happens—The pin is overloaded; the board can reset or be damaged

A motor also creates voltage spikes when it switches off, because its coil resists sudden changes in current. A motor driver handles the high current and absorbs those spikes, while the Arduino only sends small control signals.

How an H-bridge reverses a motor

H-bridge with four switches: closing S1 and S4 drives the motor forwards, closing S2 and S3 drives it backwardsClose S1 + S4 for forwards, S2 + S3 for backwards. Never close S1 + S2 together — that shorts the battery.

A DC motor spins one way when current flows through it from left to right, and the other way when current flows right to left. An H-bridge is four switches arranged in the shape of the letter H with the motor in the middle:

Switches closedCurrent through motorResult
S1 + S4Left → rightForwards
S2 + S3Right → leftBackwards
S1 + S3 or S2 + S4Both ends at the same voltageBrake (motor stops quickly)
NoneNo currentCoast (motor spins down)
S1 + S2 or S3 + S4Straight from + to −Short circuit — never do this

Inside the L298N, these switches are transistors controlled by logic pins, and the chip prevents the dangerous combinations for you.

Meet the L298N module

The common red L298N module contains two H-bridges, so one board drives both wheels of a robot car.

PinConnects toPurpose
+12V (VS)Battery + (7 V – 12 V)Motor power
GNDBattery − and Arduino GNDCommon ground
+5VArduino 5V (optional)5 V output from the on-board regulator when the jumper is fitted
ENA / ENBArduino PWM pinsSpeed of motor A / B
IN1, IN2Arduino digital pinsDirection of motor A
IN3, IN4Arduino digital pinsDirection of motor B
OUT1, OUT2Left motorMotor A
OUT3, OUT4Right motorMotor B

Wiring the robot car

Wiring diagram: Arduino Uno pins 5, 6, 7, 8, 9 and 10 connect to the L298N; two motors connect to OUT1–OUT4; a 7.4 V battery powers the driverArduino Uno → L298N → two gear motors. The battery negative, L298N GND and Arduino GND must all be connected.

Arduino UnoL298NNotes
D5 (PWM)ENARemove the ENA jumper first
D7IN1Left motor direction
D8IN2Left motor direction
D6 (PWM)ENBRemove the ENB jumper first
D9IN3Right motor direction
D10IN4Right motor direction
GNDGNDCommon ground — essential

Power the Arduino from USB while testing, or from the L298N's +5V pin once the robot runs on its own battery (keep the 5 V regulator jumper on, and the battery at 12 V or below).

The code

cpp
// Left motor
const int ENA = 5, IN1 = 7, IN2 = 8;
// Right motor
const int ENB = 6, IN3 = 9, IN4 = 10;

// speed: -255 (full reverse) ... 0 (stop) ... 255 (full forwards)
void setMotor(int en, int inA, int inB, int speed) {
  digitalWrite(inA, speed > 0 ? HIGH : LOW);
  digitalWrite(inB, speed < 0 ? HIGH : LOW);
  analogWrite(en, abs(speed));
}

void drive(int left, int right) {
  setMotor(ENA, IN1, IN2, left);
  setMotor(ENB, IN3, IN4, right);
}

void setup() {
  const int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
  for (int i = 0; i < 6; i++) pinMode(pins[i], OUTPUT);
}

void loop() {
  drive(180, 180);   delay(2000);  // forwards
  drive(0, 0);       delay(1000);  // stop
  drive(-150, 150);  delay(600);   // spin left on the spot
  drive(0, 0);       delay(1000);
  drive(-180, -180); delay(1500);  // backwards
  drive(0, 0);       delay(2000);
}

analogWrite() produces PWM — the pin switches on and off about 490 or 980 times a second (depending on the pin), and the fraction of time it is on sets the average power. 255 is fully on, 128 is about half.

Experiment 1: one motor, both directions

Lift the car so the wheels spin freely. Upload the code and watch the left wheel. Now swap the two wires on OUT1 and OUT2. The wheel turns the other way for the same code — this is how you fix a motor that runs backwards.

What you learn: direction depends only on which way the current flows.

Experiment 2: find the "dead zone"

Change the forward speed in steps: 255, 200, 150, 100, 80, 60. Note the value where the wheels stop turning on the floor.

PWM valueApprox. duty cycleTypical result with BO motors on 7.4 V
255100%Full speed
18071%Comfortable driving speed
12047%Slow, smooth
8031%May stall on carpet
6024%Usually just hums

What you learn: motors need a minimum power to overcome friction. Your robot's slowest usable speed is just above this point.

Experiment 3: drive in a straight line

Run drive(180, 180) for 3 seconds on a smooth floor. Most cars drift to one side, because no two motors are identical. Reduce the faster side a little — for example drive(180, 170) — until it goes straight.

What you learn: real robots need calibration. Better robots use wheel encoders and feedback to correct this automatically, just like the PID control in our line-following robot guide.

Experiment 4: differential steering and the square

Top view of a two-wheel robot showing how wheel speeds create straight, curve, pivot and spin turnsTwo-wheel robots steer by running the wheels at different speeds

Left wheelRight wheelMovement
+ 180+ 180Straight forwards
+ 180+ 90Gentle curve right
+ 1800Pivot turn right (around the right wheel)
+ 150− 150Spin right on the spot

Now combine them: drive forwards for 1.5 seconds, spin right for the time that gives a 90° turn, and repeat four times. Adjust the spin time until the car comes back to where it started.

Choosing the battery

BatteryVoltageGood forWatch out for
4 × AA alkaline6 VFirst testsWeak under motor load; ~4 V reaches the motors through an L298N
6 × AA alkaline9 VLight carsHeavy, drains quickly
2 × 18650 Li-ion (2S)7.4 V (8.4 V full)Most robot carsNeeds a proper charger and protection
9 V PP3 battery9 VNot recommendedToo little current for motors

Troubleshooting

ProblemMost likely causeFix
Motors don't move at allENA/ENB left unconnected after removing the jumpers, or no common groundConnect ENA to D5 and ENB to D6; connect all grounds
Speed never changesENA/ENB jumpers still fitted, so the enable pins are always onRemove both jumpers and connect ENA/ENB to PWM pins
Arduino resets when motors startBattery too weak, or motor noiseFresh batteries, 100 nF capacitors across motors, separate supply
One wheel spins backwardsMotor wires reversedSwap that motor's two wires
Motors only humPWM value too low or battery flatIncrease speed value, charge battery
L298N gets very hotMotors drawing too much currentCheck for stalled wheels; add the heatsink; consider a MOSFET driver

Where to go next

Frequently asked questions

Can I use the L298N with an ESP32?

Yes. The ESP32's 3.3 V logic is high enough for the L298N's inputs. Use any GPIO for IN1–IN4 and PWM-capable pins for ENA and ENB, and connect the grounds together.

Why does my robot slow down as the battery gets older?

Battery voltage falls as it discharges, and the L298N's 2 V loss makes this more noticeable. Lithium-ion packs hold their voltage better than AA cells.

What is the difference between brake and coast?

Brake connects both motor terminals to the same voltage, so the motor stops quickly. Coast disconnects it, so it spins down slowly. In the code above, drive(0, 0) with ENA at 0 lets the motors coast.

Should I use the L298N or a newer driver?

The L298N is great for learning because it is tough and widely available. For battery-powered robots, a MOSFET driver like the TB6612FNG runs cooler and gives the motors more of the battery's voltage.

Try the calculators

T

Thinking Robot Team

Thinking Robot is a team of engineers and educators in Pune who design electronics and robotics kits and run hands-on workshops for students and schools. Spotted a mistake or have a question? Get in touch.

Filed under#Robotics#Arduino#Electronics#Tutorial

Keep learning

WhatsApp