How to control a DC motor via ESP32 and Bluetooth with L298N on PlatformIO

Introduction

Welcome to this article where I will walk you step-by-step through a project on how to control a DC motor using an ESP32 and an L298N based H bridge. Follow this comprehensive guide to learn how to control the direction of rotation and speed (via a PWM signal) of a DC motor from your smartphone via a Bluetooth interface.

In this tutorial on DC motor control with ESP32 and L298N, we will explore everything from the basics of electronics to programming the ESP32 using the PlatformIO IDE. We’ll be using Kai Morich’s Serial Bluetooth Terminal application to send commands to our loop.

Not only will this project give you an understanding of DC motor and H-bridge operation, but it will also allow you to master wireless control over Bluetooth, opening up a world of possibilities for future applications.
During the tutorial, I will provide you with the connection diagram, code examples and step-by-step instructions to ensure easy reproducibility of the project. Whether you’re a beginner or an expert in electronics and programming, this guide will suit you.

The DC motor

A DC motor (direct current motor) is a widely used electromechanical device (DC motors are essential components in various industries such as factory automation, robotics, consumer electronics and many others) that converts electrical energy into mechanical energy. It is made up of a combination of electrical and magnetic components that enable rotational motion.
A DC motor consists of two main components: the stator and the rotor. The stator is the stationary part of the motor and can consist of either a permanent magnet or a set of copper wire windings, known as stator windings, which create a stationary magnetic field. The rotor is the moving part of the motor and contains a series of windings, known as rotor windings, which create a magnetic field which interacts with the magnetic field of the stator.

The basic operation of a DC motor is based on the Lorentz force law. When an electric current passes through the rotor windings, a magnetic field is created. This magnetic field interacts with the magnetic field of the stator, generating a force that rotates the rotor.
The DC motor can rotate in both directions.

To reverse the direction of rotation of the motor, the polarity of the current in the rotor must be reversed. This is accomplished by using a switching device, known as a commutator, which changes the direction of the electric current in the various windings of the rotor (or, much more simply, by reversing the power wires).
The electrical energy required to operate the DC motor is provided by an external power source, such as a battery or power supply. The supplied voltage determines the speed and power of the motor, while the current determines the torque or torque generated by the motor.

In this project we will use a DC motor equipped with a gear reducer which you can see in the following image:

The DC motor with gear reducer
The DC motor with gear reducer

As you can see, the motor has two copper tabs (on the left side of the photo) where you will need to solder the power wires, as shown in the photo below:

The DC motor with gear reducer and power wires
The DC motor with gear reducer and power wires

If you don’t know how to solder, you can consult the Yet another tutorial on how to solder article in this blog.

In the next photo you can see what the DC motor looks like separated from the gear reducer:

The DC motor separated from the gear reducer
The DC motor separated from the gear reducer

The PWM signal

PWM, short for Pulse Width Modulation, is a control technique used to regulate the amount of energy delivered to an electrical device (the load) efficiently. It is widely used in various applications including power electronics, motor control, LED lighting and more.

The PWM signal is based on the modulation of a rectangular waveform in which the pulse width is varied with respect to the wave period. The period represents the time taken to complete one cycle of the waveform, while the pulse width indicates the duration that the wave is ON (high) during a period.
The ratio of pulse width to period, known as the duty cycle, represents the percentage of time the signal is ON out of the total period. Duty cycle is usually expressed as a percentage or as a value between 0 and 1.
To generate a PWM signal, a control circuit, such as a microcontroller or dedicated integrated circuit, generates a series of rectangular pulses with a constant frequency. The duration of each pulse is varied to obtain the desired duty cycle. For example, if the duty cycle is 50%, the pulse will be ON for half the period and OFF for the other half.
Using the PWM signal offers several advantages. First, it allows you to control the power delivered to a load efficiently. Since the signal is composed of ON and OFF pulses, energy is only supplied for the duration of the ON pulses, reducing energy dissipation and overall consumption. This makes it ideal for applications where precise power regulation is required, such as motor control.
In addition, the PWM signal allows you to adjust the size or intensity of an application proportionally. By varying the duty cycle, a continuous range of power or brightness levels can be achieved. For example, in LED lighting, the PWM signal can be used to dim light, offering smooth control over brightness.
Finally, the PWM signal is easily implemented using digital electronic circuits. Modern microcontrollers and dedicated ICs offer built-in PWM signal generation functions, simplifying implementation in various designs and applications.
In conclusion, PWM signal is a control technique that modulates the pulse width of a rectangular waveform to regulate the power or intensity of an electrical device. It offers energy efficiency, precise control and flexibility, making it widely used in different areas of electronics and automation.

The H-bridge

An H-bridge is an electronic circuit used to control the direction of current flow through a load, such as a DC motor. It is a component widely used in power electronics and robotics to reverse the polarity and direction of rotation of a motor, allowing its forward and reverse motion to be controlled.
An H-bridge is made up of four switches (usually transistors) arranged in a specific configuration to control the flow of current through a load. The four switches are organized into two branches: an upper branch and a lower branch.

Diagram of an H bridge driving a DC motor
Diagram of an H bridge driving a DC motor

When one leg of the H bridge is closed (switches S1 and S4 are active), current flows in one direction through the load, allowing the motor to turn in a specific direction (e.g. forward). Conversely, when the other branch of the bridge H is closed (switches S2 and S3 active), the current flows in the opposite direction through the load, reversing the direction of rotation of the motor (e.g. reverse).

The combination of opening and closing of switches S1, S2, S3 and S4 makes it possible to control the direction of rotation of the motor. For example, if S1 and S4 are closed and S2 and S3 are open, current flows through the load in one direction, causing the motor to spin forward. By reversing the state of the switches, the direction of current flow can be reversed and the motor run in the opposite direction.
To control the H-bridge, the appropriate control signals must be supplied to the four switches. These signals can come from a microcontroller or from a dedicated control circuit. It is important to ensure that the switches are opened and closed sequentially and appropriately to avoid short circuits or overcurrent situations (for example, S1 and S2 or S3 and S4 must not be closed simultaneously to avoid shorting the supply).

An H-bridge can be controlled using a pulse width modulation (PWM) signal. The PWM signal is a form of digital signal control that alternates between two states: ON and OFF, where the length of the ON period is varied to control the average signal strength.
In the case of the H bridge, the PWM signal is used to control the speed of the DC motor. This is done by modulating the pulse width of the PWM signal which is sent to the H bridge. When the pulse width is larger, a higher average voltage is supplied to the motor, increasing speed. Conversely, when the pulse width is reduced, the average voltage decreases, decreasing the motor speed.
The PWM signal is generated by a microcontroller or a dedicated control circuit. The microcontroller produces a series of pulses with a fixed frequency and the width of each pulse is varied according to the value of the desired control signal.
When the PWM signal is sent to the H-bridge, the H-bridge responds by opening and closing switches rapidly based on the state of the PWM pulse. For example, when the pulse is ON, the appropriate switches are closed to cause current to flow into the load, while when the pulse is OFF, the switches are opened to stop current flow.
Changing the pulse width of the PWM signal allows you to control the motor speed in a smooth manner. By adjusting the percentage of “ON-time” with respect to the total pulse period, a wide range of motor speeds can be obtained.
Control via PWM signal offers many benefits, including more precise motor speed control, higher energy efficiency and the ability to control the motor proportionally. It is particularly useful in applications where fine tuning of the speed is required or when it is necessary to control the speed of the motor according to changing conditions.

The L298N driver

The L298N integrated circuit is a popular motor driver chip used to control DC motors and stepper motors. It is widely used in robotics, automation and general electronics projects. The L298N offers an affordable and efficient solution for motor control, allowing you to control motor direction and speed with ease.
The L298N is an H-bridge type driver, which means it can control the direction of current flow through a motor. It supports driving two independent DC motors or one four-phase stepper motor.
One of the key features of the L298N is its ability to handle high currents. It is capable of handling currents up to 2 amps, making it suitable for medium sized motors. The L298N chip has four outputs (OUT1, OUT2, OUT3, OUT4), which can be connected to the motor terminals to provide power and control.

To control the L298N, an appropriate control signal must be provided for its various input lines. Main input lines include ENA, ENB, IN1, IN2, IN3 and IN4. The ENA and ENB lines enable or disable the motor driver. The IN1 and IN2 lines control the direction of the motor connected to the OUT1 and OUT2 outputs, while the IN3 and IN4 lines control the direction of the motor connected to the OUT3 and OUT4 outputs.
To regulate motor speed, the L298N supports Pulse Width Modulation (PWM). By connecting the PWM signal to one of the ENA or ENB lines, it is possible to vary the width of the pulses to adjust the motor speed according to the duty cycle of the PWM signal.
The L298N requires an external power supply to power the motor. Adequate power supply voltage (generally between 5V and 35V, depending on chip specifications) must be provided for proper motor and driver operation. Also, it is important to connect the motor terminals correctly to the driver to ensure proper current flow.
So, L298N integrated circuit is a motor driver chip widely used for DC motor and stepper motor control. It offers motor speed and direction control capabilities, supports high currents, and can be controlled using control signals such as PWM. With its reliability and ease of use, the L298N has established itself as a popular choice for a variety of projects requiring motor control.

You can download its datasheet from this link:L298N

In this project we will use a board that mounts an L298N that you can see in the following image:

H bridge board used to drive the DC motor
H bridge board used to drive the DC motor

Let’s see the meaning of the various elements of the board:

  • the OUTPUT MOTOR 1 and OUTPUT MOTOR 2 are the motor driving outputs (this board is able to drive two motors at the same time even if we will use only one)
  • the POWER SUPPLY FROM BATTERIES section receives the voltage coming from the battery pack (in this case equal to 6V)
  • we leave the CON5 JUMPER connected as it is used to use the voltage coming from the POWER SUPPLY FROM BATTERIES section to power the H bridge chip as well as the DC motor
  • ENABLE A JUMPER and ENABLE B JUMPER are two jumpers that act on the enabling pins of the two motors on the chip. In our case we have to remove the first one to be able to drive the DC motor through the ESP32 with the PWM signal
  • pins IN1, IN2 are the inputs for driving motor 1 while pins IN3, IN4 are the inputs for driving motor 2. By setting IN1 to HIGH and IN2 to LOW, motor 1 will turn in one direction, by setting IN1 to LOW and IN2 at HIGH the motor will run in the opposite direction, putting IN1 and IN2 at LOW the motor stops. Same thing for IN3 and IN4 on the second motor.

What components do we need?

The list of components is not particularly long:

  • a breadboard to connect the ESP32 NodeMCU to the other components
  • some DuPont wires (male – male, male – female, female – female)
  • a DC motor with supply voltage between 3V and 6V
  • an H bridge board
  • a battery holder for 4 AA or AAA batteries (in order to have 6V)
  • and, of course, an ESP32 NodeMCU !

Project realization

The wiring diagram

Before realizing the actual circuit let’s look at the pinout of the board:

ESP32 pinout
ESP32 pinout

Here, in the following image, the connection diagram created with Fritzing:

Wiring diagram
Wiring diagram

The GPIOs used are 3 and, more precisely, they are 5, 18 and 19 and are used to control the H bridge. The ESP32 is powered by the USB cable connected to the computer while the motor is powered by the batteries as it absorbs a current relatively high. The two power supplies have the ground in common.

In the following image you can see a photo of the battery holder used in this project:

The battery holder
The battery holder

As you can see the connection is quite simple. Actually you could even do without the breadboard, unless you want to add a few more components.

The sketch

Let’s create the PlatformIO project

We have already seen the procedure for creating a PlatformIO project in the How to create a project for NodeMCU ESP8266 with PlatformIO article.

Although it refers to the ESP8266 board, the procedure is similar.
Simply, when choosing the platform, you will have to choose the AZ-Delivery ESP-32 Dev Kit C V4.

Do not install the libraries indicated in that article because we don’t need them in this project. But you must, following the procedure indicated in the article, install the BluetoothSerial by Seeed library as shown in the following image:

Installing the BluetoothSerial library
Installing the BluetoothSerial library

Now edit the platformio.ini file to add these two lines:

monitor_speed = 115200
upload_speed = 921600

so that the file looks like this:

[env:az-delivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
monitor_speed = 115200
upload_speed = 921600
framework = arduino
lib_deps = mbed-seeed/[email protected]+sha.f56002898ee8

Of course you can download the project from the following link:

Replace the main.cpp file of the project you created with the one present in the zip file.

Now let’s see how the sketch works.

Initially the necessary libraries are included:

#include <Arduino.h>
#include "BluetoothSerial.h"

The SerialBT object that manages Bluetooth is then instantiated and the BTData variable is defined in which the data received from Bluetooth will transit:

BluetoothSerial SerialBT;
byte BTData;

We then define the GPIOs used for motor control:

// GPIOs DC motor
int DCmotorInput1 = 19;               // IN1
int DCmotorInput2 = 18;               // IN2
int EnableDCmotor = 5;                // ENA

Immediately afterwards, the operating parameters of the PWM and the dutyCycle variable, initialized to 200, are defined:

// Configuring the PWM values
const int PWM_Frequency = 5000;
const int PWM_Channel = 0;
const int PWM_Resolution = 8;
int dutyCycle = 200;

In the setup function, the serial port is initialized and waits for it to be ready:

Serial.begin(115200);
delay(2000);

The GPIOs are configured as outputs:

// Configuring the output GPIOs
pinMode(DCmotorInput1, OUTPUT);
pinMode(DCmotorInput2, OUTPUT);
pinMode(EnableDCmotor, OUTPUT);

Configure the PWM channel output and connect it to the EnableDCmotor pin:

// Configuring the PWM output
ledcSetup(PWM_Channel, PWM_Frequency, PWM_Resolution);
  
// Connecting the PWM channel
ledcAttachPin(EnableDCmotor, PWM_Channel);

Finally, Bluetooth is activated:

// Starts the Bluetooth device
SerialBT.begin();
Serial.println("Bluetooth Started! Ready to pair...");

If you want to assign a specific name to the ESP32 Bluetooth device, you need to specify it as an argument to the SerialBT.begin() function. For example, if you want to name it myESP32BT, enter SerialBT.begin(“myESP32BT”).
If you leave the command without a parameter, such as SerialBT.begin(), the default name ESP32 will be applied.

We now meet the loop function.

The first part reads the character sent from the mobile application (which we will see later) to the ESP32:

if(SerialBT.available())
{
  BTData = SerialBT.read();
}

The decoding of the commands follows:

if(BTData == 'S')
{
  // Stops the DC motor
  Serial.println("Motor stopped");
  digitalWrite(DCmotorInput1, LOW);
  digitalWrite(DCmotorInput2, LOW);
  delay(1000);
}

When the S (Stop) command is received, the two pins DCmotorInput1 and DCmotorInput2 are put in the LOW state. In this case the motor stops.

if(BTData == 'F')
{
  // Moves the DC motor forward with speed according to PWM duty cycle
  Serial.println("Moving Forward");
  digitalWrite(DCmotorInput1, LOW);
  digitalWrite(DCmotorInput2, HIGH); 
  ledcWrite(PWM_Channel, dutyCycle); 
  delay(2000);
}

When the F (Forward) command is received, the DCmotorInput1 pin is set to LOW while the DCmotorInput2 pin is set to HIGH. In this case the motor rotates in one direction. Furthermore, the value present in the dutyCycle variable is written in the PWM channel. The rotation speed will be proportional to this value.

if(BTData == 'B')
{
  // Moves the DC motor backwards with speed according to PWM duty cycle
  Serial.println("Moving Backwards");
  digitalWrite(DCmotorInput1, HIGH);
  digitalWrite(DCmotorInput2, LOW); 
  ledcWrite(PWM_Channel, dutyCycle); 
  delay(2000);
}

When the B (Backwards) command is received, the DCmotorInput1 pin is set to HIGH while the DCmotorInput2 pin is set to LOW state. In this case the motor runs in the opposite direction. Furthermore, the value present in the dutyCycle variable is written in the PWM channel. The rotation speed will be proportional to this value.

if(BTData == 'I')
{
  // Increments the PWM duty cycle by 10
  dutyCycle = dutyCycle + 10;
  // Limits the PWM duty cycle value to a maximum of 250
  if(dutyCycle >= 250)
  {
    dutyCycle = 250;
  }
  Serial.print("I ");
  Serial.println(dutyCycle);
  ledcWrite(PWM_Channel, dutyCycle);
}

When the I (Increment) command is received, the value contained in the dutyCycle variable is increased by 10 (as a result, the rotation speed increases). However, the value is limited to 250 as we are already close to the maximum value that can be set for the PWM which is 255. Furthermore, the value present in the dutyCycle variable is written in the PWM channel.

if(BTData == 'D')
{
  // Decrements the PWM duty cycle by 10
  dutyCycle = dutyCycle - 10;
  // Limits the PWM duty cycle value to a minimum of 170
  if(dutyCycle <= 170)
  {
    dutyCycle = 170;
  }
  
  Serial.print("D ");
  Serial.println(dutyCycle);
  ledcWrite(PWM_Channel, dutyCycle);    
}

When the D (Decrement) command is received, the value contained in the dutyCycle variable is decreased by 10 (consequently the rotation speed decreases). However, the value is limited to 170 as for lower values ​​the motor stops. Furthermore, the value present in the dutyCycle variable is written in the PWM channel.

The Serial Bluetooth Terminal application

To send the Bluetooth commands to the ESP32 I chose to use Kai Morich’s Serial Bluetooth Terminal application. You can download it from the Play Store.

Now turn on Bluetooth in your smartphone and search for Bluetooth devices. You should see a list of Paired Devices and Available Devices. Go to Available Devices.

Select ESP32 if you left the SerialBT.begin() line without a parameter in the sketch, otherwise choose the device with the name you put as a parameter in that line. Your mobile phone will ask you if you want to pair it with ESP32 (or with the name you set for it). At this point give OK. No need for passwords.

Open the Serial Bluetooth Terminal application and click on the point indicated in the following image:

Click on the point indicated to bring out the menu
Click on the point indicated to bring out the menu

Select the Devices item as shown in the figure below:

Select the Devices item
Select the Devices item

Another menu will open from which you will have to select your device (for example ESP32):

Select your device
Select your device

Now click on the point indicated in the following image to connect the application to the selected device:

Connect the application to the device
Connect the application to the device

Hopefully the connection should establish:

Connection successful
Connection successful

Now you need to record the commands to be sent to the device with macros in the application. Hold down the M1 key. The menu for editing it will open:

Let's make the first macro
Let’s make the first macro

Instead of M1, put the character S in the Name field and fill the Value field with the character S, then save by pressing at the indicated point:

The first macro is ready
The first macro is ready

Repeating the exact same procedure, perform the following associations:

  • on M2 put the character F in the Name and Value fields
  • on M3 put the character B in the Name and Value fields
  • on M4 put the label +10 in the Name field and the character I in the Value field
  • on M5 put the label -10 in the Name field and the character D in the Value field
  • M6 leave it unchanged

At the end you should have a screen like this:

Here's what the screen looks like after recording all the macros
Here’s what the screen looks like after recording all the macros

Pressing the S button will cause the motor to stop. By pressing the F key you will make the motor go forward (you can adjust its speed using the +10 and -10 keys) while by pressing the B key you will make the motor turn in the opposite direction (always with the possibility of adjusting the speed with the +10 and -10). The +10 and -10 keys do nothing but increase/decrease the PWM duty cycle by ten units (within the limits of 170 and 250 because for a duty cycle lower than 170 the motor has difficulty rotating while at 250 it is almost maximum value which is 255).

Operation video

Below you can see a simple video showing how the device works:

Operation video

To make the rotation of the motor more evident I attached a wheel to the motor shaft.

Newsletter

If you want to be informed about the release of new articles, subscribe to the newsletter. Before subscribing to the newsletter read the page Privacy Policy (UE)

If you want to unsubscribe from the newsletter, click on the link that you will find in the newsletter email.

Enter your name
Enter your email
0 0 votes
Article Rating
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
Scroll to Top