Control DC Motors with L293D Motor Driver IC & Arduino

If you’re planning on assembling your new robot friend, you’ll eventually want to learn how to control DC motors. The easiest and inexpensive way to control DC motors is to interface the L293D Motor Driver IC with the Arduino. It can control both the speed and the spinning direction of two DC motors.

And as a bonus, it can also control a unipolar stepper motor like the 28BYJ-48 or a bipolar stepper motor like the NEMA 17.

Controlling a DC Motor

To have complete control over DC motor we have to control its speed and rotation direction. This can be achieved by combining these two techniques.

  • PWM – to control speed
  • H-Bridge – to control the rotation direction

PWM – to control speed

The speed of a DC motor can be controlled by changing its input voltage. A common technique to do this is to use PWM (Pulse Width Modulation).

PWM is a technique where the average value of the input voltage is adjusted by sending a series of ON-OFF pulses.

The average voltage is proportional to the width of the pulses known as the Duty Cycle.

The higher the duty cycle, the higher the average voltage applied to the DC motor (resulting in higher speed) and the shorter the duty cycle, the lower the average voltage applied to the DC motor (resulting in lower speed).

The image below shows PWM technique with different duty cycles and average voltages.

Pulse Width Modulation PWM Technique with Duty Cycles
Pulse Width Modulation(PWM) Technique

H-Bridge – to control the rotation direction

The spinning direction of a DC motor can be controlled by changing the polarity of its input voltage. A common technique for doing this is to use an H-bridge.

An H-bridge circuit consists of four switches with the motor in the center forming an H-like arrangement.

Closing two specific switches at a time reverses the polarity of the voltage applied to the motor. This causes a change in the spinning direction of the motor.

The following animation shows the working of the H-bridge circuit.

H-Bridge Working Motor Direction Control Animation
Working of H-Bridge

L293D Motor Driver IC

The L293D is a dual-channel H-Bridge motor driver capable of driving a pair of DC motors or a single stepper motor. This means it can drive up to two motors individually which makes it ideal for building a two-wheeled robotic platform.

l293d ic

The L293D is most often used to drive motors, but can also be used to drive any inductive load such as a relay solenoid or large switching power transistor.

It is capable of driving four solenoids, four uni-directional DC motors, two bi-directional DC motors or one stepper motor.

The L293D IC has a supply range of 4.5V to 36V and is capable of 1.2A peak output current per channel, so it works very well with most of our motors.

The IC also includes built-in kick-back diodes to prevent damage when the motor is de-energized.

Technical Specifications

Here are the specifications:

Motor output voltage4.5V – 36V
Logic input voltage5V
Output Current per channel600mA
Peak Output Current per Channel1.2A

For more details, please refer below datasheet.

L293D Motor Driver IC Pinout

The L293D IC has a total of 16 pins that connect it to the outside world. The pinout is as follows:

l293d dual h bridge motor driver ic pinout

Let’s get acquainted with all the pins one by one.

Power Pins

l293d power supply connections

The L293D motor driver IC actually has two input power pins – VS and VSS.

VS (Vcc2) pin gives power to the internal H-Bridge of the IC to drive the motors. You can connect an input voltage anywhere between 4.5 to 36V to this pin.

VSS (Vcc1) is used to drive the internal logic circuitry which should be 5V.

GND pins are common ground pins. All 4 GND pins are internally connected and used to dissipate the heat generated under high load conditions.

Output Pins

l293d output terminals

The L293D motor driver’s output channels for the motor A and B are brought out to pins OUT1,OUT2 and OUT3,OUT4 respectively. You can connect two 5-36V DC motors to these pins.

Each channel on the IC can deliver up to 600mA to the DC motor. However, the amount of current supplied to the motor depends on system’s power supply.

Direction Control Pins

By using the direction control pins, you can control whether the motor rotates forward or backward. These pins actually control the switches of the H-Bridge circuit inside the L293D IC.

l293d direction control inputs

The IC has two direction control pins for each channel. The IN1 and IN2 pins control the spinning direction of motor A; While IN3 and IN4 control the spinning direction of motor B.

The spinning direction of the motor can be controlled by applying logic HIGH (5V) or logic LOW (Ground) to these inputs. The chart below shows how this is done.

IN1IN2Spinning Direction
Low(0)Low(0)Motor OFF
High(1)Low(0)Forward
Low(0)High(1)Backward
High(1)High(1)Motor OFF

Speed Control Pins

l293d speed control inputs

The speed control pins ENA and ENB are used to turn on/off the motors and control its speed.

Pulling these pins HIGH will cause the motors to spin, while pulling it LOW will stop them. But, with Pulse Width Modulation (PWM), you can actually control the speed of the motors.

Wiring a L293D Motor Driver IC to an Arduino

Now that we know everything about the IC, we can start connecting it to our Arduino!

Let’s start by connecting the power supply to the motors. In our experiment we are using DC gearbox motors (also known as ‘TT’ motors) commonly found in two-wheel-drive robots. They are rated for 3 to 12V. Therefore, we will connect the external 5V power supply to the VS (Vcc2) pin.

Next, we need to supply 5V to the logic circuitry of the L293D. Connect the VSS (Vcc1) pin to the 5V output on the Arduino. And make sure your circuit and Arduino share a common ground.

Now connect the L293D IC’s Input and Enable pins (ENA, IN1, IN2, IN3, IN4 and ENB) to the six Arduino digital output pins (9, 8, 7, 5, 4 and 3). Note that Arduino output pins 9 and 3 are both PWM-enabled.

Finally, connect one motor to OUT1 and OUT2 and the other motor to OUT3 and OUT4. You can interchange the connections of your motor. There is technically no right or wrong way.

When you are done you should have something that looks similar to the illustration shown below.

wiring l293d motor driver ic with dc motors arduino

Arduino Example Code

The following sketch will give you a complete understanding on how to control the speed and spinning direction of a DC motor with the L293D motor driver IC and will serve as the basis for more practical experiments and projects.

// Motor A connections
int enA = 9;
int in1 = 8;
int in2 = 7;
// Motor B connections
int enB = 3;
int in3 = 5;
int in4 = 4;

void setup() {
	// Set all the motor control pins to outputs
	pinMode(enA, OUTPUT);
	pinMode(enB, OUTPUT);
	pinMode(in1, OUTPUT);
	pinMode(in2, OUTPUT);
	pinMode(in3, OUTPUT);
	pinMode(in4, OUTPUT);
	
	// Turn off motors - Initial state
	digitalWrite(in1, LOW);
	digitalWrite(in2, LOW);
	digitalWrite(in3, LOW);
	digitalWrite(in4, LOW);
}

void loop() {
	directionControl();
	delay(1000);
	speedControl();
	delay(1000);
}

// This function lets you control spinning direction of motors
void directionControl() {
	// Set motors to maximum speed
	// For PWM maximum possible values are 0 to 255
	analogWrite(enA, 255);
	analogWrite(enB, 255);

	// Turn on motor A & B
	digitalWrite(in1, HIGH);
	digitalWrite(in2, LOW);
	digitalWrite(in3, HIGH);
	digitalWrite(in4, LOW);
	delay(2000);
	
	// Now change motor directions
	digitalWrite(in1, LOW);
	digitalWrite(in2, HIGH);
	digitalWrite(in3, LOW);
	digitalWrite(in4, HIGH);
	delay(2000);
	
	// Turn off motors
	digitalWrite(in1, LOW);
	digitalWrite(in2, LOW);
	digitalWrite(in3, LOW);
	digitalWrite(in4, LOW);
}

// This function lets you control speed of the motors
void speedControl() {
	// Turn on motors
	digitalWrite(in1, LOW);
	digitalWrite(in2, HIGH);
	digitalWrite(in3, LOW);
	digitalWrite(in4, HIGH);
	
	// Accelerate from zero to maximum speed
	for (int i = 0; i < 256; i++) {
		analogWrite(enA, i);
		analogWrite(enB, i);
		delay(20);
	}
	
	// Decelerate from maximum speed to zero
	for (int i = 255; i >= 0; --i) {
		analogWrite(enA, i);
		analogWrite(enB, i);
		delay(20);
	}
	
	// Now turn off motors
	digitalWrite(in1, LOW);
	digitalWrite(in2, LOW);
	digitalWrite(in3, LOW);
	digitalWrite(in4, LOW);
}

Code Explanation:

The Arduino code is pretty straightforward. It doesn’t require any libraries to work. The sketch begins with declaring the Arduino pins to which the L293D’s control pins are connected.

// Motor A connections
int enA = 9;
int in1 = 8;
int in2 = 7;
// Motor B connections
int enB = 3;
int in3 = 5;
int in4 = 4;

In the setup section of the code, all the motor control pins (both direction and speed control pins) are configured as digital OUTPUT and the direction control pins are pulled LOW to turn off both the motors.

void setup() {
	// Set all the motor control pins to outputs
	pinMode(enA, OUTPUT);
	pinMode(enB, OUTPUT);
	pinMode(in1, OUTPUT);
	pinMode(in2, OUTPUT);
	pinMode(in3, OUTPUT);
	pinMode(in4, OUTPUT);
	
	// Turn off motors - Initial state
	digitalWrite(in1, LOW);
	digitalWrite(in2, LOW);
	digitalWrite(in3, LOW);
	digitalWrite(in4, LOW);
}

In the loop section of the code, we call two user defined functions at an interval of one second.

void loop() {
	directionControl();
	delay(1000);
	speedControl();
	delay(1000);
}

These functions are:

  • directionControl() – This function makes both motors spin forward at maximum speed for two seconds. It then reverses the motor’s spinning direction and spins for two seconds. Finally it turns off the motors.

    void directionControl() {
    	// Set motors to maximum speed
    	// For PWM maximum possible values are 0 to 255
    	analogWrite(enA, 255);
    	analogWrite(enB, 255);
    
    	// Turn on motor A & B
    	digitalWrite(in1, HIGH);
    	digitalWrite(in2, LOW);
    	digitalWrite(in3, HIGH);
    	digitalWrite(in4, LOW);
    	delay(2000);
    	
    	// Now change motor directions
    	digitalWrite(in1, LOW);
    	digitalWrite(in2, HIGH);
    	digitalWrite(in3, LOW);
    	digitalWrite(in4, HIGH);
    	delay(2000);
    	
    	// Turn off motors
    	digitalWrite(in1, LOW);
    	digitalWrite(in2, LOW);
    	digitalWrite(in3, LOW);
    	digitalWrite(in4, LOW);
    }
  • speedControl() – This function accelerates both motors from zero to maximum speed by producing a PWM signal using the analogWrite() function, then it decelerates them back to zero. Finally it turns off the motors.

    void speedControl() {
    	// Turn on motors
    	digitalWrite(in1, LOW);
    	digitalWrite(in2, HIGH);
    	digitalWrite(in3, LOW);
    	digitalWrite(in4, HIGH);
    	
    	// Accelerate from zero to maximum speed
    	for (int i = 0; i < 256; i++) {
    		analogWrite(enA, i);
    		analogWrite(enB, i);
    		delay(20);
    	}
    	
    	// Decelerate from maximum speed to zero
    	for (int i = 255; i >= 0; --i) {
    		analogWrite(enA, i);
    		analogWrite(enB, i);
    		delay(20);
    	}
    	
    	// Now turn off motors
    	digitalWrite(in1, LOW);
    	digitalWrite(in2, LOW);
    	digitalWrite(in3, LOW);
    	digitalWrite(in4, LOW);
    }