Introduction: DC Motor Control With Raspberry Pi and L293D
Use Python Scripts, a Raspberry Pi 3, and an L293D IC to run a DC motor at any speed in either direction.
Step 1: Materials and Tools
Materials
- Raspberry Pi 3 (RPi)
- L293D control IC
- Breadboard
- Jumper wires, Male to Male (M/M) and Female to Male (F/M)
- DC Motor
- 9v Battery
**In this project, it is necessary to access the Raspberry Pi desktop. This can be done by plugging a monitor, keyboard and mouse into the RPi or by using an SSH connection.**
No tools are necessary for this project as none of the connections are permanent and use jumper wires and a breadboard. If you want to make a permanent, more durable version, simply make the same connections with a soldering iron and some wire.
Step 2: Background Info.
**This step is all background info. If you don't care about how this is done and just want to do it without learning, skip to Step 3.**
In this project, we're using python scripts run on a Raspberry Pi to set GPIO outputs to an L293D motor controller IC and run a DC motor in either direction at any speed.
First things first; a Raspberry Pi is an open-source credit card sized computer with 40 open GPIO pins. GPIO stands for "General Purpose Input/Output", which means these pins can either send electrical signals to drive hardware or receive them and read sensor data. We're using them as outputs, to send signals to the L293D IC Chip, which is just a chip used to control DC motors. Nothing special.
Python is a computer programming language, comparable to Javascript or C++. We'll be using very simple python commands, and no prior computer programming knowledge will be necessary.
The way we'll control the speed of the motor is by using a python module called PWM. That stands for Pulse Width Modulation. What PWM means is just controlling the amount of time a voltage is on by flipping between high and low for a set amount of time. The amount of time the voltage is high is called the 'duty' or 'duty cycle', and whatever percentage that is will be the percentage of power the motor runs on.
To see how PWM looks as an output, refer to the diagram above.
The L293D motor IC uses two pins referred to as inputs to sense the desired direction of the output, and another pin called Enable to sense On/Off. So, in our code, with the Enable pin On, if we want the motor to spin forward, we'll set input 1 to 'True' or 'HIGH', and input 2 to 'False' or 'LOW'. And if we want it to spin backwards, we'll set input 1 to 'False" or 'LOW' and input 2 to 'True' or "HIGH'. If both inputs are True or both are False, the motor will not run.
That's how we'll control the direction, but what about speed? We talked about PWM right? So we'll just Pulse Width Modulate both inputs, right? We could, but it would be too complicated. Since the IC has an Enable pin that controls its On/Off state, we can leave both inputs set to run and just modulate the Enable pin, and the IC will only put out power according to the duty we set in the Enable pin. That way we keep the code simpler, and less things can go wrong.
So, on the Raspberry Pi, we'll be using 3 GPIO output pins on the GPIO board, one 3.3V power supply, and one grounding pin. 2 of the output pins will be for the inputs on the IC, and one will be for the Enable.
Now that we know what will be going on, it's time to start wiring it up.
Step 3: Hardware Setup
The pictures above probably look like a confusing jumble of wires, but don't worry.
The first thing to do is put the L293D chip on the breadboard. Your breadboard should have a split down the middle, like a gap, and the IC chip should straddle it nicely with half of its pins on either side, so it runs parallel with the board.
Next, it's important to plug the wires into the correct breadboard slots, so I recommend color coding the wires. I use red for positive power connections, black for negative power connections (grounds), blue for inputs from the RPi, and orange for the outputs to the motor.
You might notice that there are two sets of power cables. That's because the DC motor should be running on at least 9V and 400mA, but the motor control IC runs on either 5V or 3.3V and less than 20mA. So in this setup, the IC chip is taking 3.3V of power and connected via a ground (negative power plug) to the RPI. Then it also has 9V of power and a ground coming from the battery, which it routes through the chip to the motor. Important: Do not attempt to draw 9V and 400mA off the RPi or run 9V through the IC Chip. This could damage your RPi and/or your L293D. To make sure you route the voltages to the correct pins, use the diagram above.
To know which end of the IC Chip is which, look for a little semi-circle notch on one end that corresponds to the diagram above.
Now that you have your L293D IC on the breadboard, first we're going to connect the M/F jumpers to the RPi. So, on your breadboard, put the male end of the jumpers into the slots next to: Vss, Enable 1, Input 1, Input 2, and either GND pin on the left side. There should be 5 wires ready to be connected to the RPi. Refer to the diagram above for the pin numbers. Now, connect the wire from Vss (I'm hoping you made it red) to the 5V power on the Pi, or pin #1. Next, connect your GND jumper (again, hopefully black) to the GND pin, or pin #6. After that, connect the Input 1 jumper to GPIO2, or pin #3. Then connect the jumper from input 2 to GPIO3, or pin #5. Lastly, connect the Enable 1 jumper to GPIO4, or pin #7. There you go, no more M/F jumpers left! Halfway there!
So, now grab the M/M jumpers. One of these should go from the Vs pin on the IC to the positive end of your 9V. There's lots of ways to make it stay on the battery, but tape is fine as long as both metal ends are touching solidly. Connect the negative end of the battery to the other GND pin on your IC with a black M/M jumper. Lastly, just wire both of the output pins on your IC to the ends of the motor! That's it! Everything is now wired exactly how it needs to be, no more hardware work. On to software.
Step 4: Software Setup
First, we need to open a program on the Pi to write our code. We're going to use IDLE 2, so go to the top left of your desktop, click Menu, click Programming, and click Python 2(IDLE). You should see a blank text editor with an untitled document.
The first thing we need to do is import the GPIO module. So, on the first line, type exactly, CaSe sensitive,
import RPi.GPIO as GPIO
this imports the GPIO module
next, we need a command called 'sleep', so write
from time import sleep
next we need to name all of the pins, so set the naming mode by writing
GPIO.setmode(GPIO.BOARD)
this sets the names to board mode, which just names the pins according to the numbers in the middle of the diagram above.
now we need to set the pins as outputs, so write
GPIO.setup(03, GPIO.OUT)
GPIO.setup(05, GPIO.OUT)
GPIO.setup(07, GPIO.OUT)
now to setup the pwm commands type
pwm=GPIO.PWM(07, 100)
next start the Pulse Width Modulation with 0 duty so it doesn't run yet
pwm.start(0)
The rest of the code changes depending on the way we want to run the motor. For this first pass, we're just going to set up predefined instructions in the code. Later, I'll explain how to make a code that lets you input whatever direction, duty, and duration you want to.
So, for now, we're going to write a code that runs forward at 50% power for 2 seconds, then runs backward at 75% power for 3 seconds.
First, to set the direction to forward write
GPIO.output(03, True)
GPIO.output(05, False)
Now, we're going to set the PWM duty to 50%. Write
pwm.ChangeDutyCycle(50)
then turn on the Enable pin
GPIO.output(07, True)
then put the code to sleep for 2 seconds so the motor runs
sleep(2)
now turn off the Enable pin
GPIO.output(07, False)
then reverse the inputs to set it to reverse
GPIO.output(03, False)
GPIO.output(05, True)
Then change the PWM duty to 75%
pwm.ChangeDutyCycle(75)
then turn the enable back on
GPIO.output(07, True)
put the code to sleep for 3 seconds
sleep(3)
then turn the enable pin back off
GPIO.output(07, False)
stop the Pulse
pwm.stop()
and cleanup all of the GPIO channels.
GPIO.cleanup()
And that's it! You now have a code that will run your motor forwards at 50% for two seconds then backwards at 75% for 3 seconds. Press F5, then save to test your code!
*Note: you may receive an error that says the selected GPIO channels are already in use. This won't affect your project, and you can make the warnings stop appearing by writing "GPIO.setwarnings(False)" to your code.*