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.
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.
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.
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 voltage | 4.5V – 36V |
Logic input voltage | 5V |
Output Current per channel | 600mA |
Peak Output Current per Channel | 1.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:
Let’s get acquainted with all the pins one by one.
Power Pins
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
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.
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.
IN1 | IN2 | Spinning 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
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.
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 connectionsint enA = 9;int in1 = 8;int in2 = 7;// Motor B connectionsint enB = 3;int in3 = 5;int in4 = 4;void setup() {// Set all the motor control pins to outputspinMode(enA, OUTPUT);pinMode(enB, OUTPUT);pinMode(in1, OUTPUT);pinMode(in2, OUTPUT);pinMode(in3, OUTPUT);pinMode(in4, OUTPUT);// Turn off motors - Initial statedigitalWrite(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 motorsvoid directionControl() {// Set motors to maximum speed// For PWM maximum possible values are 0 to 255analogWrite(enA, 255);analogWrite(enB, 255);// Turn on motor A & BdigitalWrite(in1, HIGH);digitalWrite(in2, LOW);digitalWrite(in3, HIGH);digitalWrite(in4, LOW);delay(2000);// Now change motor directionsdigitalWrite(in1, LOW);digitalWrite(in2, HIGH);digitalWrite(in3, LOW);digitalWrite(in4, HIGH);delay(2000);// Turn off motorsdigitalWrite(in1, LOW);digitalWrite(in2, LOW);digitalWrite(in3, LOW);digitalWrite(in4, LOW);}// This function lets you control speed of the motorsvoid speedControl() {// Turn on motorsdigitalWrite(in1, LOW);digitalWrite(in2, HIGH);digitalWrite(in3, LOW);digitalWrite(in4, HIGH);// Accelerate from zero to maximum speedfor (int i = 0; i < 256; i++) {analogWrite(enA, i);analogWrite(enB, i);delay(20);}// Decelerate from maximum speed to zerofor (int i = 255; i >= 0; --i) {analogWrite(enA, i);analogWrite(enB, i);delay(20);}// Now turn off motorsdigitalWrite(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 connectionsint enA = 9;int in1 = 8;int in2 = 7;// Motor B connectionsint 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 outputspinMode(enA, OUTPUT);pinMode(enB, OUTPUT);pinMode(in1, OUTPUT);pinMode(in2, OUTPUT);pinMode(in3, OUTPUT);pinMode(in4, OUTPUT);// Turn off motors - Initial statedigitalWrite(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 255analogWrite(enA, 255);analogWrite(enB, 255);// Turn on motor A & BdigitalWrite(in1, HIGH);digitalWrite(in2, LOW);digitalWrite(in3, HIGH);digitalWrite(in4, LOW);delay(2000);// Now change motor directionsdigitalWrite(in1, LOW);digitalWrite(in2, HIGH);digitalWrite(in3, LOW);digitalWrite(in4, HIGH);delay(2000);// Turn off motorsdigitalWrite(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 motorsdigitalWrite(in1, LOW);digitalWrite(in2, HIGH);digitalWrite(in3, LOW);digitalWrite(in4, HIGH);// Accelerate from zero to maximum speedfor (int i = 0; i < 256; i++) {analogWrite(enA, i);analogWrite(enB, i);delay(20);}// Decelerate from maximum speed to zerofor (int i = 255; i >= 0; --i) {analogWrite(enA, i);analogWrite(enB, i);delay(20);}// Now turn off motorsdigitalWrite(in1, LOW);digitalWrite(in2, LOW);digitalWrite(in3, LOW);digitalWrite(in4, LOW);}