How to Use the L293D Motor Shield Driver with Arduino

Introduction

If you're planning to build a robot, you'll need to control various motors like DC motors, stepper motors, or servos, and the L293D Motor Driver Shield is the best option for this task. This shield is not only capable of handling these motor types but also eliminates the need for additional modules. The brains of this shield are its two L293D motor drivers and a 74HC595 shift register, which work together seamlessly.

Understanding How the L293D Motor Driver Shield Works

The L293D is a dual-channel H-Bridge motor driver, meaning it can control up to four DC motors or two stepper motors. The 74HC595 shift register, on the other hand, extends the Arduino's digital pins by converting its four pins into eight direction control pins, making it easy to manage multiple motors. With these features, the L293D Shield ensures precision and efficiency for both simple and complex robotic designs.

Important: there are NO direct IN1–IN4 wires from the Arduino to this shield. On a bare L293D chip you wire IN1–IN4 yourself, but on this shield the 74HC595 shift register drives the motors — the Arduino talks to the shield over a few pins (latch, clock, data and PWM) and the AFMotor library does the rest. If you are looking for IN1–IN4 pins on the shield, you will not find them — that is normal.

Key features

  • Controls up to four DC motors or two stepper motors (two L293D chips, two motors each).
  • Two servo connections (servo 1 and servo 2).
  • External power input (EXT_PWR) for the motors, so the Arduino's USB power is not overloaded.
  • Works with the AFMotor library — one line of code per motor.

How to Use L293D Motor Driver with Arduino

The L293D Motor Driver Shield is a versatile and popular component designed for controlling various types of motors in Arduino projects. It simplifies motor operations, especially when dealing with DC motors, by acting as a reliable interface between the Arduino and the motors.

This tutorial covers how to control a DC motor using the L293D Motor Driver Shield and Arduino. To set it up, you simply mount the shield onto your Arduino, connect your motor wires to the output pins, and upload a control code. The L293D handles the power and direction control efficiently, making it ideal for projects like robots, conveyor belts, or any automated system requiring precise motor control.

Controlling a DC Motor with Arduino UNO and L293D Motor Driver Shield

Connecting a DC Motor to an Arduino Uno using the L293D Motor Driver Shield opens up a world of possibilities for motor control. Whether you're working with speed adjustments or directional changes, integrating components like an I2C LCD display, potentiometer (POT), and buttons adds precision and flexibility to your project. Below is a simplified guide to setting up this system for seamless operation.

Key Components and Setup

ComponentPurposePrice / link
Arduino UnoMain controllerArduino UNO R3 DIP — Rs 1,200
L293D Motor Driver ShieldMotor driver (two L293D + 74HC595)Rs 490
DC gear motorThe motor (connect to M3)Rs 165
16×2 LCD with I2CVisual feedbackRs 660
Tactile push buttonsFWD / REV / STOP (×3)Rs 10 each
Potentiometer (10k)Speed adjustmentAvailable on order — message us on WhatsApp
BreadboardPrototypingMB102 — Rs 250
Jumper wiresConnectionsRs 180
12V 2A adapterExternal motor powerRs 275
  1. DC Motor and Motor Control: Connect the DC Motor to the M3 motor output terminal of the L293D Motor Driver Shield. This configuration allows precise control of motor speed and rotation direction, including clockwise and anti-clockwise rotation.
  2. Buttons for Control: Use three buttons for motor commands: Clockwise Rotation Button connected to A1, Anti-Clockwise Rotation Button connected to A2, and Stop Button connected to A3. The other side of each button goes to GND (the code uses the Arduino's internal pull-up resistors, so no external resistors are needed).
  3. Potentiometer (POT) for Speed Adjustment: The potentiometer regulates speed by connecting one side to 5V, the other to GND, and the middle pin to an analog input pin (A0).
  4. I2C LCD Display: For visual feedback, link the I2C LCD display to the Arduino via SDA (A4) and SCL (A5) pins, ensuring efficient communication.
  5. External Power Supply: An external 6–12V supply (matching your motor's voltage) connects to the L293D Motor Driver Shield's EXT_PWR terminals to ensure sufficient power for the motor. Remember to remove the power jumper between the Arduino 5V and shield power when using an external source — otherwise the external supply feeds back into the Arduino.
  6. Arduino and Shield Alignment: Mount the L293D Motor Driver Shield on the Arduino Uno, ensuring all pins align. Power the Arduino via USB or another external power source.

By setting up these components with proper connections and leveraging the versatility of the L293D Motor Driver Shield, you can create a reliable and efficient motor control system tailored to your project's needs.

L293D motor shield wiring diagram — Arduino UNO, DC motor on M3, potentiometer, buttons and I2C LCD

Arduino Code

#include <AFMotor.h>            // Library to run DC Motor Using Motor Driver Shield
#include <Wire.h>
#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("%  ");
  }
}

How the code works: the potentiometer on A0 sets the speed (0–255), the three buttons on A1/A2/A3 select forward, reverse or stop, and the LCD shows the direction and the speed as a percentage. The buttons use the Arduino's internal pull-up resistors (INPUT_PULLUP), so a pressed button reads LOW — that is why the code checks for LOW. When the direction changes, the code stops the motor for one second first — reversing a spinning DC motor instantly can damage the gears.

For a complete robot car that uses a motor driver and an ultrasonic sensor, see our obstacle-avoidance robot car guide. And if you want to control a single DC motor's speed without a shield, see our DC motor speed control guide — it uses a MOSFET instead.

Troubleshooting Common Issues

  • Motor does not move: check the external power supply is connected to EXT_PWR and the power jumper is removed. The Arduino's USB power alone cannot run most motors.
  • Motor runs in the wrong direction: swap the two motor wires on the M3 terminal, or swap FORWARD and BACKWARD in the code.
  • LCD shows nothing: check the I2C address (0x27 or 0x3F) and the SDA/SCL wiring (SDA to A4, SCL to A5 on the UNO).
  • Buttons do nothing: check the button wiring — one side to A1/A2/A3, the other side to GND. The code uses INPUT_PULLUP, so a pressed button reads LOW.
  • Motor stutters or the Arduino resets: the motor is drawing too much current from the USB. Use the external supply and make sure the Arduino GND and the external supply GND are connected (the shield does this through its ground plane, but check the jumper).

Where to Buy the Parts

The Arduino UNO R3 DIP (Rs 1,200), L293D motor driver shield (Rs 490), DC gear motor (Rs 165), 16×2 LCD with I2C (Rs 660), tactile push buttons (Rs 10 each), MB102 breadboard (Rs 250), jumper wires (Rs 180) and 12V 2A adapter (Rs 275) are available at QKZEE Technologies, Shop 20, 1st Floor, Al-Khalil Center, Hall Road, Lahore, and online at qkzeetech.com with delivery all over Pakistan — see the links above. The potentiometer is available on order — message us on WhatsApp and we will arrange it for you.

Still Stuck?

If the motor does not move, or the LCD stays blank, message us — tell us whether the external supply is connected, whether the power jumper is removed, and what the LCD shows, and we will help you find the fault.

Chat on WhatsAppSubscribe on YouTube

FAQs

How many motors can the L293D shield control?

Up to four DC motors or two stepper motors (two L293D chips, two motors each). It also has two servo connections.

Why are there no IN1–IN4 pins on the shield?

Because the shield uses a 74HC595 shift register to drive the motors. The Arduino talks to the shield over a few pins and the AFMotor library handles the direction logic — you never wire IN1–IN4 yourself on this shield.

Why does the motor not move when the Arduino is powered by USB?

USB power (5V, 500 mA) is usually not enough for a motor. Connect an external 6–12V supply to the shield's EXT_PWR terminals and remove the power jumper.

What happens if I leave the power jumper on with an external supply?

The external supply feeds back into the Arduino's 5V rail, which can damage the Arduino and the USB port. Always remove the jumper when using EXT_PWR.

Can I use this shield with a stepper motor?

Yes — the shield controls up to two stepper motors (one per L293D chip). Use the AF_Stepper class from the same AFMotor library instead of AF_DCMotor.

Which library do I need?

The AFMotor library (for the motors) and LiquidCrystal_I2C (for the LCD). Install both from the Arduino IDE Library Manager. The code will not compile without them — the old post had the #include lines with the library names stripped out.

Conclusion

The L293D motor shield is the fastest way to drive motors from an Arduino: plug it on, connect the motor to M3, add an external supply, and the AFMotor library does the rest. Remember the three things that trip everyone up — the external supply with the jumper removed, the I2C address (0x27 or 0x3F), and that there are no IN1–IN4 wires on this shield. That is the whole project, and it works.