The article demonstrates how to use an ESP32 and the L298N Motor Driver to control the direction and speed of a DC motor. We’ll start by looking at how the L298N motor driver works. Then we’ll teach you how to use the ESP32 with Arduino IDE and the L298N motor driver to control the speed and direction of a DC motor.

Parts Required

To complete this tutorial you need the following parts:

  • ESP32 DOIT DEVKIT V1 Board – The DOIT Esp32 DevKit v1 is one of the development boards created by DOIT to evaluate the ESP-WROOM-32 module. It is based on the ESP32 microcontroller that boasts Wifi, Bluetooth, Ethernet and Low Power support all in a single chip.
  • DC motor- A direct current (DC) motor is a type of electric machine that converts electrical energy into mechanical energy. DC motors take electrical power through direct current and convert this energy into mechanical rotation.
  • L298N motor driver-The L298N is a dual H-Bridge motor driver which allows speed and direction control of two DC motors at the same time. The module can drive DC motors that have voltages between 5 and 35V, with a peak current up to 2A. 
  • Power source: 4x 1.5 AA batteries or Bench power supply
  • 2x 100nF ceramic capacitors (optional)
  • 1x SPDT slide switch (optional)
  • Jumper wires

Introducing the L298N Motor Driver

There are many ways to control a DC motor. The method we’ll use here is suitable for most hobbyist motors, that require 6V or 12V to operate.

We’re going to use the L298N motor driver that can handle up to 3A at 35V. Additionally, it allows us to drive two DC motors simultaneously, which is perfect to build a robot.

L298N Motor Driver pinout

Let’s take a look at the L298N motor driver pinout and see how it works.

L298N Motor Driver

The motor driver has a two-terminal block on each side for each motor. OUT1 and OUT2 at the left and OUT3 and OUT4 at the right.

  • OUT1: DC motor A + terminal
  • OUT2: DC motor A – terminal
  • OUT3: DC motor B + terminal
  • OUT4: DC motor B – terminal

A three-terminal block containing +12V, GND, and +5V is located at the bottom. The motors are powered by the +12V terminal block. The L298N chip is powered by the +5V connector. When the jumper is in place, however, the chip is powered by the motor’s power source, so you don’t have to give 5V through the +5V terminal.

If you want to supply more than 12V, remove the jumper and connect 5V to the +5V connector.

It’s worth noting that, despite the +12V terminal’s designation, you may supply any voltage between 6V and 12V with the setup we’ll use here (with the jumper in place). In this lesson, four AA 1.5V batteries with a total output of around 6V will be used, but any other acceptable power supply can be used. To test this instruction, for example, you can utilise a bench power supply.

In summary:

  • +12V: The +12V terminal is where you should connect your power supply
  • GND: power supply GND
  • +5V: provide 5V if the jumper is removed. Acts as a 5V output if jumper is in place
  • Jumper: jumper in place – uses the motors power supply to power up the chip. Jumper removed: you need to provide 5V to the +5V terminal. If you supply more than 12V, you should remove the jumper

At the bottom right you have four input pins and two enable terminals. The input pins are used to control the direction of your DC motors, and the enable pins are used to control the speed of each motor.

  • IN1: Input 1 for Motor A
  • IN2: Input 2 for Motor A
  • IN3: Input 1 for Motor B
  • IN4: Input 2 for Motor B
  • EN1: Enable pin for Motor A
  • EN2: Enable pin for Motor B

There are jumper caps on the enable pins by default. You need to remove those jumper caps to control the speed of your motors.

Control DC motors with the L298N

Now that you’re familiar with the L298N Motor Driver, let’s see how to use it to control your DC motors.

Enable pins

The enable pins are like an ON and OFF switch for your motors. For example:

  • If you give a HIGH signal to the enable 1 pin, motor A is ready to control and is running at maximum speed
  •  if you deliver a LOW signal to the enable 1 pin, motor A is turned off
  •  and if you supply a PWM signal, you can regulate the motor’s speed. The duty cycle is related to the motor speed. However, keep in mind that for low duty cycles, the motors may not spin and produce a constant buzz.
SIGNAL ON THE ENABLE PINMOTOR STATE
HIGHMotor enabled
LOWMotor not enabled
PWMMotor enabled: speed proportional to duty cycle

Input pins

The input pins control the direction the motors are spinning. Input 1 and input 2 control motor A, and input 3 and 4 control motor B.

  • The motor will rotate forward if you apply LOW to input 1 and HIGH to input 2
  •  the motor will rotate backwards if you apply power the other way around: HIGH to input 1 and LOW to input 2. Motor B can be operated in the same way as Motor A, but with inputs 3 and 4 set to HIGH or LOW.

Controlling 2 DC Motors – ideal to build a robot

If you want to design a robot vehicle out of two DC motors, make sure they’re rotating in the same direction so the robot can go left, right, forward, or backwards.

If you want your robot to travel forward, for example, both motors should be spinning forward. Both should be spinning rearward to make it go backwards.

To move the robot in one way, you must accelerate the opposite motor. To have the robot turn right, for example, enable the left motor and inhibit the right motor. The state combinations of the input pins for the robot directions are shown in the table below.

DIRECTIONINPUT 1INPUT 2INPUT 3INPUT 4
Forward0101
Backward1010
Right0100
Left0001
Stop0000

Control DC Motor with ESP32 – Speed and Direction

Now that you know how to control a DC motor with the L298N motor driver, let’s build a simple example to control the speed and direction of one DC motor.

Schematic

Because the motor we’ll control is linked to the motor A output pins, we’ll need to connect the motor driver’s ENABLEA, INPUT1 and INPUT2 pins to the ESP32. To connect the DC motor and the L298N motor driver to the ESP32, see the next schematic diagram.

ESP32 with DC Motor and L298N Motor Driver
ESP32 with DC Motor and L298N Motor Driver

Because the DC motors require a large change in current to move, they should be driven by an external power source such as the ESP32. We’re using 4AA batteries as an example, but you can use any other acceptable power supply. You can use a power source with a voltage range of 6 to 12 volts in this arrangement.

Although the switch between the battery holder and the motor driver is not required, it is quite useful for cutting and applying power. You won’t have to constantly connect and unhook the wires to save power this way.

To smooth out any voltage spikes, we propose attaching a 0.1uF ceramic capacitor to the positive and negative terminals of the DC motor, as indicated in the diagram. (It’s worth noting that the motors can run without the capacitor.)

Uploading code

The following code controls the speed and direction of the DC motor. This code is not useful in the real world, this is just a simple example to better understand how to control the speed and direction of a DC motor with the ESP32.

// Motor A
int motor1Pin1 = 27; 
int motor1Pin2 = 26; 
int enable1Pin = 14; 

// Setting PWM properties
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 200;

void setup() {
  // sets the pins as outputs:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(enable1Pin, OUTPUT);
  
  // configure LED PWM functionalitites
  ledcSetup(pwmChannel, freq, resolution);
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(enable1Pin, pwmChannel);

  Serial.begin(115200);

  // testing
  Serial.print("Testing DC Motor...");
}

void loop() {
  // Move the DC motor forward at maximum speed
  Serial.println("Moving Forward");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, HIGH); 
  delay(2000);

  // Stop the DC motor
  Serial.println("Motor stopped");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  delay(1000);

  // Move DC motor backwards at maximum speed
  Serial.println("Moving Backwards");
  digitalWrite(motor1Pin1, HIGH);
  digitalWrite(motor1Pin2, LOW); 
  delay(2000);

  // Stop the DC motor
  Serial.println("Motor stopped");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  delay(1000);

  // Move DC motor forward with increasing speed
  digitalWrite(motor1Pin1, HIGH);
  digitalWrite(motor1Pin2, LOW);
  while (dutyCycle <= 255){
    ledcWrite(pwmChannel, dutyCycle);   
    Serial.print("Forward with duty cycle: ");
    Serial.println(dutyCycle);
    dutyCycle = dutyCycle + 5;
    delay(500);
  }
  dutyCycle = 200;
}

How code works

Declaring motor pins

First, you define the GPIOs the motor pins are connected to. In this case, Input 1 for motor A is connected to GPIO 27, the Input 2 to GPIO 26, and the Enable pin to GPIO 14.

int motor1Pin1 = 27; 

int motor1Pin2 = 26; 

int enable1Pin = 14;

Setting the PWM  properties to control the speed

You may regulate the DC motor speed by sending a PWM signal to the enable pin of the L298N motor driver, as we’ve seen before. The duty cycle will be proportionate to the speed. Before you can utilise PWM with the ESP32, you must first set the PWM signal parameters.

const int freq = 30000;

const int pwmChannel = 0;

const int resolution = 8;`

int dutyCycle = 200;

In this scenario, we’re using channel 0 to generate a 30000 Hz signal with an 8-bit resolution. We begin with a 200-hour duty cycle (you can set a duty cycle value from 0 to 255).

When duty cycles are less than 200 for the frequency we’re using, the motor won’t move and will create an odd buzz sound. As a result, we started with a duty cycle of 200.

Note that the PWM properties we’re defining here are only for demonstration purposes. Other frequencies do not affect the motor’s performance.

setup()

In the setup(), you start by setting the motor pins as outputs.

pinMode(motor1Pin1, OUTPUT);

pinMode(motor1Pin2, OUTPUT);

pinMode(enable1Pin, OUTPUT);

You need to configure a PWM signal with the properties you’ve defined earlier by using the ledcSetup() function that accepts as arguments, the pwmChannel, the frequency, and the resolution, as follows:

ledcSetup(pwmChannel, freq, resolution);

The next step is to select the GPIO from which you will receive the signal. Use the ledcAttachPin() function, which takes two arguments: the GPIO from which you wish to get the signal and the channel from which the signal is generated. In this example, we’ll use the enable1Pin GPIO to receive the signal that corresponds to GPIO 14. The pwmChannel, which corresponds to channel 0, is the channel that generates the signal.

ledcAttachPin(enable1Pin, pwmChannel);

Moving the DC motor forward

In the loop() is where the motor moves. The code is well comment on what each part of the code does. To move the motor forward, you set input 1 pin to LOW and input 2 pint to HIGH. In this example, the motor speeds forward for 2 seconds (2000 milliseconds).

// Move the DC motor forward at maximum speed

Serial.println("Moving Forward");

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, HIGH); 

delay(2000);

Moving the DC motor backwards

To move the DC motor backwards you apply power to the motor input pins the other way around. HIGH to input 1 and LOW to input 2.

// Move DC motor backwards at maximum speed

Serial.println("Moving Backwards");

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW); 

delay(2000);

Stop the DC motor

To make the DC motor stop, you can either set the enable pin to LOW, or set both input 1 and input 2 pins to LOW. In this example we’re setting both input pins to LOW.

// Stop the DC motor

Serial.println("Motor stopped");

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, LOW);

delay(1000);

Controlling the DC motor speed

The duty cycle of the PWM signal must be changed to regulate the DC motor speed. To do so, use the ledcWrite() function, which accepts the PWM channel that is generating the signal (not the output GPIO) and the duty cycle as parameters, as shown below.

ledcWrite(pwmChannel, dutyCycle);

In our example, we have a while loop that increases the duty cycle by 5 in every loop.

// Move DC motor forward with increasing speed

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW);

while (dutyCycle <= 255){

  ledcWrite(pwmChannel, dutyCycle);

  Serial.print("Forward with duty cycle: ");

  Serial.println(dutyCycle);

  dutyCycle = dutyCycle + 5;

  delay(500);

}

When the while condition is no longer true, we set the duty cycle to 200 again.

dutyCycle = 200;

Conclusion

We’ve taught you how to use an ESP32 and the L298N motor driver to control the direction and speed of a DC motor in this tutorial. In conclusion:

  • The input 1 and input 2 pins are used to regulate the direction the DC motor spins
  •  apply LOW to input 1 and HIGH to input 2 to spin the motor forward. To make it spin backwards, reverse the power
  •  to control the speed of the DC motor, use a PWM signal on the enable pin. The duty cycle is proportional to the DC motor’s speed.
author avatar
Amith G Nair
Experience as a product developer, innovation coach, and electronics lecturer,a seasoned professional driven by passion for designing projects.expertise extends to 3D modelling, hardware designing, and web development using HTML, WordPress, and Django.