Motor control is an essential part of robotics, automation systems and mechatronics projects. However, driving motors directly from an Arduino is not possible because the microcontroller cannot supply the required current.
This is where a motor driver shield becomes useful. The L293D Motor Driver Shield provides an easy interface between the Arduino and multiple types of motors including DC motors, servo motors and stepper motors.
In this project we will learn how to use the L293D motor shield with an Arduino UNO to control:
• DC motor speed and direction
• Servo motor movement
• Stepper motor rotation and direction
User inputs are taken through push buttons and a potentiometer, while a 16×2 I2C LCD displays the motor status and speed.
L293D Motor Driver Shield Overview
The L293D motor driver shield is designed to simplify motor control projects with Arduino. The shield contains two L293D H-bridge driver ICs which allow bidirectional control of motors.
Each L293D IC can control 2 DC motors or 1 stepper motor.
Since the shield includes two L293D chips, it can control:
• 4 DC motors
• or 2 stepper motors
In addition, the shield provides two dedicated servo connectors.
Hardware Architecture of the Shield
The shield contains several important components that make motor control possible.
L293D Motor Driver IC: The L293D is a dual H-bridge motor driver that controls the direction of current through the motor. This allows the motor to rotate in both clockwise and anticlockwise directions.
Each L293D IC can drive two motors.
Since the shield contains two L293D ICs, four DC motors can be controlled simultaneously.
74HC595 Shift Register: The 74HC595 shift register expands the Arduino's digital output capability.
Instead of using many digital pins directly from Arduino, the shift register allows multiple motor direction signals to be controlled using fewer pins.
Reset Button: A reset button is provided on the shield so the Arduino can be reset easily even when the shield is mounted.
Power Indicator LED: The power LED indicates when the motor power supply is active.
Pull-Down Resistor Network: The resistor array ensures that motor driver inputs remain in a known state during startup.
L293D Motor Driver Pinout
Motor Connection Ports
The shield provides dedicated connectors for different motor types.
DC Motor Connections
The shield provides four motor output ports labeled M1, M2, M3 and M4.
Each port can drive a DC motor.
Important details:
• Voltage range: 4.5V – 24V
• Maximum current per channel: 600mA continuous
Servo Motor Connections
The shield includes two servo ports labeled:
SERVO_1
SERVO_2
Stepper Motor Connections
Stepper motors use two motor channels.
Power Supply Configuration
The shield supports two power configurations.
Option 1: Single Power Supply
If motors operate below 12V, the Arduino and motors can share the same power supply.
Steps:
Connect supply to Arduino DC jack
Keep the PWR jumper installed
Option 2: Separate Motor Power Supply
This is recommended for higher current motors.
Steps:
Remove the PWR jumper
Power Arduino via USB
Connect motor supply to EXT_PWR terminals
⚠ Important Warning: Never keep the jumper installed while using external power at EXT_PWR.
This can create a short circuit and damage the board.
Controlling DC Motor
In this example we control:
• Motor direction
• Motor speed
Speed is controlled using a 10K potentiometer.
Components:
Arduino UNO
L293D Motor Driver Shield
5V DC Motor
3 Push Buttons
10K Potentiometer
16×2 LCD (I2C)
External 5V motor supply
Breadboard
Jumper wires
The L293D motor driver shield should be mounted directly on top of the Arduino UNO, but in the wiring diagram it is shown separately for clarity and to better illustrate the external connections such as buttons and the potentiometer. The potentiometer is connected to analog pin A0, with its middle pin acting as the variable output, while the other two pins are connected to 5V and GND. By adjusting the potentiometer, the voltage at A0 changes, which directly controls the motor speed—higher voltage results in higher speed.
Since the shield occupies most of the Arduino’s digital pins (D3 to D12), and D0–D1 are reserved for serial communication while D13 is connected to the onboard LED, only one digital pin (D2) remains free. To overcome this limitation, analog pins A1, A2, and A3 are used as digital input pins for push buttons. These buttons control motor operation: A1 for clockwise rotation, A2 for anticlockwise rotation, and A3 for stopping the motor.
A 16×2 LCD with I2C interface is connected to the Arduino’s SDA and SCL pins to display motor speed and direction. The 5V DC motor is connected to the M3 terminal of the motor shield. An external 5V power supply is provided to the shield through the EXT_PWR terminal to ensure sufficient current for the motor.
⚠️** Important:** Ensure that the power jumper (PWR) is removed when using an external power supply to avoid short circuits and potential damage.
Arduino Code
/*
Interfacing DC Motor with Arduino UNO using L293D motor Driver shield
by www.playwithcircuit.com
*/
#include <AFMotor.h>
// Library to run DC Motor Using Motor Driver Shield
#include <LiquidCrystal_I2C.h>
// Library to Run I2C LCD
LiquidCrystal_I2C lcd(0x27, 16, 2); // Format -> (Address,Columns,Rows )
// Create the motor object connected to M3
AF_DCMotor motor(3);
// Define button pins
const int forwardButtonPin = A1;
const int reverseButtonPin = A2;
const int stopButtonPin = A3;
// Define potentiometer pin
const int potPin = A0;
// Variables to store motor state and direction
bool motorRunning = false;
int motorDirection = BACKWARD; // FORWARD or BACKWARD
// Read the potentiometer value
int potValue;
int motorSpeed;
// Variable to store button states
bool forwardButtonState;
bool stopButtonState;
bool reverseButtonState;
// Inline function to check if button is pressed packed with debouncing logic
inline bool chkButtonState(int pinNum, int checkState, int debounceDelay) {
if (((digitalRead(pinNum) == checkState) ? true : false) == true) {
delay(debounceDelay);
return (((digitalRead(pinNum) == checkState) ? (true) : (false)) == true);
} else {
return false;
}
}
void setup() {
// initialize the lcd
lcd.init();
// Turn on the Backlight
lcd.backlight();
// Clear the display buffer
lcd.clear();
// Set cursor (Column, Row)
lcd.setCursor(0, 0);
lcd.print("DC Motor using");
lcd.setCursor(0, 1);
lcd.print("L293D Shield");
// Set button pins as inputs
pinMode(forwardButtonPin, INPUT_PULLUP);
pinMode(stopButtonPin , INPUT_PULLUP);
pinMode(reverseButtonPin, INPUT_PULLUP);
// Start with motor off
motor.setSpeed(0);
motor.run(RELEASE);
delay(2000);
// Clear the display buffer
lcd.clear();
// Set cursor (Column, Row)
lcd.setCursor(0, 0);
lcd.print("Motor Direction:");
lcd.setCursor(0, 1);
lcd.print("Stopped ");
}
void loop() {
// Read the potentiometer value for changing speed as per Analog input
potValue = analogRead(potPin);
motorSpeed = map(potValue, 0, 1023, 0, 255);
// Read the button states
forwardButtonState = chkButtonState(forwardButtonPin, LOW, 20);
reverseButtonState = chkButtonState(reverseButtonPin, LOW, 20);
stopButtonState = chkButtonState(stopButtonPin, LOW, 20);
// check for Forward run
if (forwardButtonState && (!motorRunning || motorDirection == BACKWARD)) {
// Set cursor (Column, Row)
lcd.setCursor(0, 1);
lcd.print("Clock ");
if (motorDirection == BACKWARD) {
motor.setSpeed(0);
motor.run(RELEASE);
delay(1000);
}
motorRunning = true;
motorDirection = FORWARD;
motor.setSpeed(motorSpeed);
motor.run(FORWARD);
}
// check for Reverse run
else if (reverseButtonState && (!motorRunning || motorDirection == FORWARD)) {
// Set cursor (Column, Row)
lcd.setCursor(0, 1);
lcd.print("Anti-Clk");
if (motorDirection == FORWARD) {
motor.setSpeed(0);
motor.run(RELEASE);
delay(1000);
}
motorRunning = true;
motorDirection = BACKWARD;
motor.setSpeed(motorSpeed);
motor.run(BACKWARD);
}
// Stop motor
else if (stopButtonState && motorRunning) {
// Set cursor (Column, Row)
lcd.setCursor(0, 1);
lcd.print("Stopped ");
motorRunning = false;
motor.setSpeed(0);
motor.run(RELEASE);
}
// Adjust motor speed if running and display speed on LCD
if (motorRunning) {
motor.setSpeed(motorSpeed);
// Set cursor (Column, Row)
lcd.setCursor(9, 1);
lcd.print("SPD:");
lcd.print(((motorSpeed*100)/255));
lcd.print("% ");
}
}
If you want the complete tutorial to learn how to control servo and stepper motor including detailed schematics, Arduino code, and deeper explanation, you can read the full guide here: https://playwithcircuit.com/l293d-motor-driver-shield-arduino-tutorial/


Top comments (0)