Upload
dinhcong
View
231
Download
2
Embed Size (px)
Citation preview
Student Workbook
1
Controlling a Motor with your Raspberry Pi In this exercise you will show how the Raspberry Pi’s GPIO port may be used along with a motor control chip to control a DC motor. The concept of Pulse Width Modulation will be introduced and you will learn how PWM can be used to control the speed of the motor. Finally you will use some push buttons connected to the Raspberry GPIO port to provide a simple human machine interface to control the speed and direction of the motor. The GPIO pins are located at one corner of the Raspberry Pi, as shown below. There are 26 pins in all, and they are used for a variety of different things. It isn’t important to remember what all the pins do, but it is important to note how they are numbered.
If necessary, prepare your Raspberry Pi by performing the following tasks:
Insert the prepared SD(HC) memory card into the card slot on the underside to the Raspberry Pi
Connect the USB Keyboard and Mouse to the two USB sockets
Connect the computer monitor or TV screen to the HDMI socket using the HDMI cable
However, do not connect the power supply to the Micro USB socket at this stage.
Student Workbook
2
Step 1 – Simple On/Off motor control In this exercise you will use your Raspberry Pi to turn a DC motor on and off, and control the direction of rotation of the motor by using the L293D motor control (H-Bridge) chip.
The L293D chip can control two motors independently (although you will use it to control just one motor), and it allows a separate power supply to be used for the motors to that used for the chip itself. This is important because the power available from the Raspberry Pi’s GPIO port is sufficient to power the chip, but it is not powerful enough to run a motor. There are three control inputs for each motor – Enable, Input A, and Input B. This allows the direction of the motor to be controlled as follows.
Enable Input A Input B Motor Behaviour
Off On or Off On or Off Stopped
On On Off Turn Forwards
On Off On Turn Backwards
On Off Off Stopped
On On On Stopped
Therefore the direction the motor turns depends on whether Input A or Input B is “On”, provided that Enable is “On”. If both Input A and Input B are “Off”, the motor is turned off, but the same is true if both Input A and Input B are “On”. If Enable is “Off” then it doesn’t matter what state Inputs A and B are in, the motor will always be turned off.
Student Workbook
3
Please make sure your Raspberry Pi is turned off and the power supply disconnected before proceeding. Build the circuit for this exercise by performing the following tasks:
Insert the L293D chip into the breadboard so that its pins straddle the gap down the centre of the breadboard
Connect one end of the Black wire to pin number 6 on the GPIO header and connect the other end to the ground rail on the left side of the breadboard
Connect one end of the Red wire to pin number 2 on the GPIO header and connect the other end to the power rail on the right side of the breadboard
Connect one end of the Orange wire to the power rail on the right side of the breadboard and connect the other end to the breadboard next to pin number 16 on the L293D chip
Connect one end of the Purple wire to the power rail on the right side of the breadboard and connect the other end to the breadboard next to pin number 9 on the L293D chip
Connect one end of the Black wire to the ground rail on the left side of the breadboard and connect the other end to the breadboard next to pin number 5 on the L293D chip
Connect one end of the Green wire to pin number 16 on the GPIO header and connect the other end to the breadboard next to pin number 15 on the L293D chip
Connect one end of the Blue wire to pin number 18 on the GPIO header and connect the other end to the breadboard next to pin number 10 on the L293D chip
Connect the motor to the breadboard so that one wire is next to pin number 11 on the L293D chip and the other wire is next to pin number 14 on the L293 chip. It isn’t important which war round you connect the motor wires
Connect the battery pack to the power rails down the left side of the breadboard so that the black wire is connected to the ground rail, and the red wire is connected to the power rail. Be careful not to short circuit the battery pack.
Connect one end of the Red wire to the power rail on the left side of the breadboard (which carries power from the battery pack) and connect the other end to the breadboard next to pin number 8 on the L293D chip
Student Workbook
4
The finished circuit is shown below.
Student Workbook
5
Connect the power supply to the Micro USB socket on the Raspberry Pi and turn the power supply on
Allow your Raspberry Pi to boot up and then log in and launch the Graphical User Interface (GUI). If you’re not sure how to do this please follow the instructions in Step 2 of the Setup Guide
Click on the LXDE icon on the bottom left corner of the screen – this will display the “Start Menu”
Click on “Run”
Student Workbook
6
You will now see the “Run” dialog box displayed in the centre of the screen.
Type “sudo idle3” in the Run dialog box and click “OK” or press Enter
Once the “Python Shell” window appears, do the following:
Type “import RPi.GPIO as GPIO” at the Python prompt and press Enter This imports the GPIO Python library so you can program the GPIO interface
Type “GPIO.setmode(GPIO.BOARD)” at the Python prompt and press Enter
This means that you can reference the GPIO header pins by their pin numbers
Type “GPIO.setup(16, GPIO.OUT)” at the Python prompt and press Enter
This sets GPIO pin number 16 as an Output pin
Type “GPIO.setup(18, GPIO.OUT)” at the Python prompt and press Enter
This sets GPIO pin number 18 as an Output pin
Type “GPIO.output(16, 0)” at the Python prompt and press Enter
This turns pin 16 “Off” (digital state “0”)
Student Workbook
7
Type “GPIO.output(18, 1)” at the Python prompt and press Enter
This turns pin 18 “On” (digital state “1”) When this line is typed in and Enter is pressed, the motor will start turning. Take note of what direction it is running
Type “GPIO.output(18, 0)” at the Python prompt and press Enter
This turns pin 18 “Off” (digital state “0”) When this line is typed in and Enter is pressed, the motor will stop turning
Type “GPIO.output(16, 1)” at the Python prompt and press Enter
This turns pin 16 “On” (digital state “1”) When this line is typed in and Enter is pressed, the motor will start turning again, but in the opposite direction.
Type “GPIO.output(16, 0)” at the Python prompt and press Enter
This turns pin 16 “Off” (digital state “0”) When this line is typed in and Enter is pressed, the motor will stop turning
You can carry on entering commands to turn the motor on and off if you want.
When you’re finished, click on “File” and then “Exit” to close the Python Shell window and exit IDLE3
Shutdown your Raspberry Pi (refer back to Step 4 of the Setup Guide if you can’t remember how to do this)
Student Workbook
8
Step 2 – Controlling the speed of the motor using Pulse Width Modulation (PWM) In the previous part of this exercise you were able to turn the motor on and off, and make it change direction. In this part of the exercise you are going to control the speed of the motor using Pulse Width Modulation (PWM). You might think that the best way to control the speed of a motor would be to vary the voltage, but using this method is problematic because it takes a minimum voltage to get the motor started, and if the voltage is then reduced to make the motor run slowly, the torque produced by the motor at low voltages is very small. A much better way of controlling the speed of the motor is to very quickly switch the power to the motor on and off. The comparative ratio of the time the power is on to the time the power is off is called the Duty Cycle and this determines the speed of the motor. The plot of voltage against time for duty cycles of 100%, 90%, 50%, 10% and 0% are as follows:
So for a duty cycle of 100%, the power is applied 100% of the time and the motor runs at full speed. For a duty cycle of 90%, the power is applied 90% of the time, so the power delivered to the motor is 90% of the maximum. For a duty cycle of 50%, the power is applied 50% of the time, so the power delivered to the motor is 50% of the maximum. For a duty cycle of 10%, the power is applied 10% of the time, so the power delivered to the motor is 10% of the maximum. For a duty cycle of 0%, the power is applied 0% of the time, or in other words the motor us turned off. The Raspberry Pi is capable of PWM output on GPIO pin number 12, and when the PWM signal is applied to the “Enable” pin on the L293D chip, the chip will modulate the power sent to the motor accordingly.
Student Workbook
9
Please make sure your Raspberry Pi is turned off and the power supply disconnected before proceeding. In this exercise you will use Pulse Width Modulation (PWM) to control the speed of the motor This exercise follows on from the previous exercise, so start with the circuit from the previous exercise and perform the following tasks:
Remove the Purple wire from the breadboard.
Connect one end of the Yellow wire to pin number 22 on the GPIO header and connect the other end to the breadboard next to pin number 9 on the L293D chip
The finished circuit is shown below.
Student Workbook
10
Connect the power supply to the Micro USB socket on the Raspberry Pi and turn the power supply on
Allow your Raspberry Pi to boot up and then log in and launch the Graphical User Interface (GUI). If you’re not sure how to do this please follow the instructions in Step 2 of the Setup Guide
Launch IDLE3 by typing “sudo idle3” in the Run dialog box as you did in the previous exercise (Step 1)
Student Workbook
11
In the previous exercise (Step 1) you entered Python commands directly at the Python prompt. This worked fine, but it meant that if you wanted to run a series of commands more than once, you had to type them in each time. In this exercise you will enter Python commands in to a file which you can save. This means that if you want to run the commands more than once, all you have to do is open the saved file and “Run” it.
In the Python Shell window, click on “File” and then “New Window”
Type the following Python commands into the new code window Import time import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) GPIO.setup(16, GPIO.OUT) GPIO.setup(18, GPIO.OUT) GPIO.setup(22, GPIO.OUT) GPIO.output(22,1) GPIO.output(16,0) GPIO.output(18, 1) time.sleep(5) GPIO.output(18, 0) time.sleep(2) GPIO.output(16,1) time.sleep(5) GPIO.output(16,0) GPIO.cleanup() Most of these lines of code should be familiar to you from the previous exercise (Step 1). The last line simply closes the GPIO port when the program has finished with it. This prevents error messages being generated next time the program is run
Click on “File” and then “Save”
Type “motor” into the Save dialog box and click “Save”
As soon as you do this you will notice the title of the code window change from “Untitled” to “motor.py - /home/pi/motor.py”
Student Workbook
12
Your code window should now look like this
Click on “Run” and then “Run Module”
After a short delay, the motor will run at full speed for a few seconds in one direction, pause for a short time, and then run at full speed for a few seconds in the opposite direction
Click anywhere on the code window to bring it to the front
Delete the line “GPIO.output(22,1)” and replace it with motor=GPIO.PWM(22,50) motor.start(10)
This sets up PWM on GPIO pin 22 with a frequency of 50 Hz, and starts the motor with a duty cycle to 10%
Insert the following line just before the “GPIO.cleanup()” line:
motor.stop() This stops the PWM output
Click on “File” and then “Save”
Student Workbook
13
Your code window should now look like this
Click on “Run” and then “Run Module”
After a short delay, the motor will run very slowly for a few seconds in one direction, pause for a short time, and then run very slowly for a few seconds in the opposite direction
You can try using different values for the duty cycle by changing the parameter of the “motor.start(X)” command. The higher the duty cycle, the more power will be delivered to the motor and the faster it will run.
Student Workbook
14
Now, suppose you wanted the motor to run forwards at duty cycle of 10% for 10 seconds, then pause for 1 second, then forwards with a duty cycle of 50% for 5 seconds, then pause for 1 second, then backwards at a duty cycle of 30% for 10 seconds, and then stop. The Python code for doing this is given below. Some comments have been added to make the code easier to follow. # import modules import time import RPi.GPIO as GPIO # setup GPIO and PWM GPIO.setmode(GPIO.BOARD) GPIO.setup(16, GPIO.OUT) GPIO.setup(18, GPIO.OUT) GPIO.setup(22, GPIO.OUT) motor=GPIO.PWM(22,50) # run motor forwards at 10% for 10 seconds motor.start(10) GPIO.output(16,0) GPIO.output(18,1) time.sleep(10) GPIO.output(18,0) motor.stop() # pause for 1 second time.sleep(1) # run motor forwards at 50% for 5 seconds motor.start(50) GPIO.output(16,0) GPIO.output(18,1) time.sleep(5) GPIO.output(18,0) motor.stop() # pause for 1 second time.sleep(1) # run motor backwards at 30% for 10 seconds motor.start(30) GPIO.output(18,0) GPIO.output(16,1) time.sleep(10) GPIO.output(16,0) motor.stop() # cleanup and close GPIO GPIO.cleanup() This Python code will work fine, and like all the code you have written so far, it is executed from the top, line by line, all the way to the bottom. Look at the code that makes the motor run forwards at 10% for 10 seconds, and then look at the code that makes the motor run forwards at 50% for 5 seconds. The code is identical, apart from some of the numbers inside the brackets. Instead of repeating blocks of code like this, it is much better to reorganize the code using functions. A function is a series of commands that performs the same operation on whatever parameters are passed to it, and can be thought of as a program within a program.
Student Workbook
15
For example, you can reorganize the Python code above by defining two functions – one to make the motor run forwards at a specified duty cycle for a specified time, and the other to make the motor run backwards at a specified duty cycle for a specified time. The resulting program is as follows. # import modules import time import RPi.GPIO as GPIO # setup GPIO and PWM GPIO.setmode(GPIO.BOARD) GPIO.setup(16, GPIO.OUT) GPIO.setup(18, GPIO.OUT) GPIO.setup(22, GPIO.OUT) motor=GPIO.PWM(22,50) # define a function to make motor run forwards # at duty cycle of "speed" for "duration" seconds def forwards(speed,duration): motor.start(speed) GPIO.output(16,0) GPIO.output(18,1) time.sleep(duration) GPIO.output(18,0) motor.stop() # define a function to make motor run backwards # at duty cycle of "speed" for "duration" seconds def backwards(speed,duration): motor.start(speed) GPIO.output(18,0) GPIO.output(16,1) time.sleep(duration) GPIO.output(16,0) motor.stop() # run motor forwards at 10% for 10 seconds forwards(10,10) # pause for 1 second time.sleep(1) # run motor forwards at 50% for 5 seconds forwards(50,5) # pause for 1 second time.sleep(1) # run motor backwards at 30% for 10 seconds backwards(30,10) # cleanup and close GPIO GPIO.cleanup()
Edit your existing code so that it is the same as shown above
Click on “File” and then “Save”
Student Workbook
16
Your code window should now look like this
Click on “Run” and then “Run Module”
After a short delay, the motor will run very slowly in one direction for about 10 seconds, pause, run much faster in the same direction for about 5 seconds, pause, run more slowly in the opposite direction for about 10 seconds and then stop
Using functions in this way can help simplify code and make it much easier to write and understand. By defining the “forwards(x,x)” and “backwards(x,x)” functions in the code above, the motor can be programmed to run at a specified speed for a specified time in a specified direction by a single line of code.
Try programming the motor to run at different speeds for different periods of time using the “forwards(x,x)” and “backwards(x,x)” functions
When you have finished, close the code window by clicking on “File” and then “Close”
If you have made any changes to the code since the last time you saved you will be asked if you want to save before closing
Click “Yes” if you want to save your changes, or “No” if you want to close without saving
Click on “File” and then “Exit” to close the Python Shell window and exit IDLE3
Shutdown your Raspberry Pi (refer back to Step 4 of the Setup Guide if you can’t remember how to do this)
Student Workbook
17
Step 3 – Adding a “User Interface” to allow direct control of the motor In the previous part of this exercise you programmed the motor to perform a predetermined sequence of operations, and to make any changes to the sequence of operations required that the Python code be changed accordingly. In this part of the exercise you will create a very simple user interface in the form of three pushbutton switches which will allow the user to directly control the motor and interact with it. This is an example of a simple human-machine interface as found in many modern electronic products. The function of the individual buttons may be changed by editing the Python code, but once the program is running the system will “wait” for the user to press one of the buttons and then perform the operation or sequence of operations assigned to that button. Please make sure your Raspberry Pi is turned off and the power supply disconnected before proceeding. In this exercise you will use three push button switches connected to the GPIO pins on your Raspberry Pi to directly control the motor
This exercise follows on from the previous exercise, so start with the circuit from the previous exercise and perform the following tasks:
Insert the three push button switches into the breadboard so that they straddle the gap down the centre of the breadboard
Connect one end of the Orange wire to pin number 1 on the GPIO header and connect the other end to the power rail on the right side of the breadboard
Connect one end of the Grey wire to the power rail down the right side of the breadboard and connect the other end to the breadboard next to the bottom right terminal of the lowermost push button switch
Connect one end of the Purple wire to the power rail down the right side of the breadboard and connect the other end to the breadboard next to the bottom right terminal of the middle push button switch
Connect one end of the Brown wire to the power rail down the right side of the breadboard and connect the other end to the breadboard next to the bottom right terminal of the uppermost push button switch
Connect one end of the Grey wire to pin number 11 on the GPIO header and connect the other end to the breadboard next to the top left terminal of the lowermost push button switch
Connect one end of the Purple wire to pin number 13 on the GPIO header and connect the other end to the breadboard next to the top left terminal of the middle push button switch
Connect one end of the Brown wire to pin number 15 on the GPIO header and connect the other end to the breadboard next to the top left terminal of the uppermost push button switch
Insert a 10K Ohm (10,000 Ohm) resistor into the breadboard so that one end connects with the Grey wire going to pin number 11 on the GPIO header and the other end connects to the ground rail on the left side of the breadboard
Student Workbook
18
Insert a 10K Ohm (10,000 Ohm) resistor into the breadboard so that one end connects with the Purple wire going to pin number 13 on the GPIO header and the other end connects to the ground rail on the left side of the breadboard
Insert a 10K Ohm (10,000 Ohm) resistor into the breadboard so that one end connects with the Brown wire going to pin number 15 on the GPIO header and the other end connects to the ground rail on the left side of the breadboard
The finished circuit is shown below.
Connect the power supply to the Micro USB socket on the Raspberry Pi and turn the power supply on
Allow your Raspberry Pi to boot up and then log in and launch the Graphical User Interface (GUI). If you’re not sure how to do this please follow the instructions in Step 2 of the Setup Guide
Launch IDLE3 by typing “sudo idle3” in the Run dialog box as you did in the previous exercises (Steps 1 & 2)
Student Workbook
19
In the Python Shell window, click on “File” and then “Open”
Then select your previously saved file called “motor.py” and click “Open”
Click on “File” and then “Save As…”
Type “motorinterface” into the Save dialog box and click “Save”
Edit the existing code by copying, pasting, deleting and inserting until your code listing looks like this # import modules import time import RPi.GPIO as GPIO # setup GPIO and PWM GPIO.setmode(GPIO.BOARD) GPIO.setup(16, GPIO.OUT) GPIO.setup(18, GPIO.OUT) GPIO.setup(22, GPIO.OUT) GPIO.setup(11, GPIO.IN) GPIO.setup(13, GPIO.IN) GPIO.setup(15, GPIO.IN) motor=GPIO.PWM(22,50) # prepare to start motor motor.start(50) GPIO.output(16,0) GPIO.output(18,0) print("Press Ctrl+C to exit") # wait for user input try: while True: if (GPIO.input(11)): # run motor forwards GPIO.output(16,1) if (GPIO.input(13)): # turn motor off GPIO.output(16,0) GPIO.output(18,0) if (GPIO.input(15)): # run motor backwards GPIO.output(18,1) # stop motor and cleanup GPIO except KeyboardInterrupt: print("Exiting now...") motor.stop() GPIO.cleanup()
Click on “File” and then “Save” Most of the Python code you have just entered should be familiar to you from previous parts of this exercise of from previous exercises. The “while Ture:” statement sets up an infinite loop and the code within the loop will be executed repeatedly until the user interrupts the loop by pressing “Ctrl + C”. The code within the loop checks if any of the buttons are pressed by reading the state of GPIO pins 11, 13 and 15, and if a button is pressed, the appropriate code within the “if” statement is executed.
Student Workbook
20
The “while” loop is placed inside a try clause to allow you to deal with the exception (or error) that is generated when the user terminates the program by pressing “Ctrl+C”. The error handling code is placed within the except clause, and in this case the code simply informs the user that the program is exiting (by printing a message on the Python Shell window), stops the motor, and cleans up the GPIO port (which prevents error messages being generated next time the program is run).
Your code window should now look like this
Click on “Run” and then “Run Module”
After a short delay the message “Press Ctrl+C to exit” appears in the Python Shell window. The program is now running and waiting for user input.
Press the uppermost button - the motor will start turning
Press the middle button - the motor will stop turning
Press the lowermost button - the motor will start turning in the opposite direction
What do you think will happen if you press the uppermost button while the motor is running?
Have a look back at the Python code and at the way the L293D chip’s inputs are used to control the motor and see if you can figure out what will happen
Now go ahead and press the uppermost and see what happens…
Was it what you expected to happen?
Student Workbook
21
You might have expected the direction of rotation of the motor to have instantly reversed, but instead the motor stopped. This is due to the way the L293D chip controls the motor according to the state of the two inputs “A” and “B”
Enable Input A Input B Motor Behaviour
Off On or Off On or Off Stopped
On On Off Turn Forwards
On Off On Turn Backwards
On Off Off Stopped
On On On Stopped
When you press the lowermost button (which is connected to GPIO pin 11), GPIO pin 16 is turned “On” and this pin is connected to input “A” on the L293D chip. If you now press the uppermost button (which is connected to GPIO pin 15), GPIO pin 18 is turned “On” and this pin is connected to input “B” on the L293D chip. Therefore the end result is that both inputs “A” and “B” on the L293D chip are “On” and this turns the motor off. The only way now to get the motor running again is to press the middle button (which will turn both inputs “A” and “B” on the L293D chip “Off”) and then press either of the other two buttons to start the motor.
Press the middle button to “reset” the motor controls.
Now press one of the other two buttons make the motor start turning again
When you have finished, press Ctrl+C (i.e. press and hold the “Ctrl” key, and at the same time press the “C” key) to exit the program
The message “Exiting now…” will be displayed on the Python Shell window
Click anywhere on the code window to bring it to the front You have programmed the buttons to allow the user to start and stop the motor in either direction. At the moment, however, the duty cycle (or speed of the motor) is set in the Python code to 50 and can not be changed via the user interface. Suppose instead you want the user to be able to control the speed of the motor using the buttons. There are three buttons available, so the first thing to do is to decide which function to assign to each of the buttons. One simple way of achieving this would be to assign the following functions to the buttons: Uppermost Button Increase speed of the motor each time button is pressed
If motor is stopped (speed=0), motor will start at low speed If motor is already at maximum speed (speed=100), motor remains at maximum speed
Middle Button Emergency Stop Lowermost Button Decrease speed of the motor each time button is pressed If motor is stopped (speed=0), motor remains stopped Simply writing down what you want to achieve can help when it comes to writing the Python code. It can also be very helpful to write what you want to achieve in the form of a System Flowchart, which is a graphical representation of how the program is executed and the different paths that may be taken depending on user input or the value of various variables. A simplified flowchart for the modified user interface is shown on the following page.
With the help of the description of the desired behaviour and the system flowchart on the following page, see if you can edit the Python code to reprogram the user interface (buttons) so that the user can increase and decrease the speed of the motor
Student Workbook
22
Upper Button
Pressed?
Middle Button
Pressed?
Lower Button
Pressed?
Ctrl+C
Pressed?
Speed=0
Set Speed
START
Increase Speed
(max=100)
Sleep 0.05s
Set Speed
Decrease Speed (min=0)
Set Speed
While True
STOP
Yes
No
Yes
No
No
No
Yes
Yes
Student Workbook
23
Here is the code for the reprogrammed user interface # import modules import time import RPi.GPIO as GPIO # setup GPIO and PWM GPIO.setmode(GPIO.BOARD) GPIO.setup(16, GPIO.OUT) GPIO.setup(18, GPIO.OUT) GPIO.setup(22, GPIO.OUT) GPIO.setup(11, GPIO.IN) GPIO.setup(13, GPIO.IN) GPIO.setup(15, GPIO.IN) motor=GPIO.PWM(22,50) # prepare to start motor speed=0 # new motor.start(speed) # changed GPIO.output(16,1) # changed GPIO.output(18,0) print("Press Ctrl+C to exit") # wait for user input try: while True: if (GPIO.input(11)): # decrese speed # changed speed=speed-1 # new if (speed<0): # new speed=0 # new motor.ChangeDutyCycle(speed) # new if (GPIO.input(13)): # emergency stop # changed speed=0 # new motor.ChangeDutyCycle(speed) # new if (GPIO.input(15)): # increase speed # changed speed=speed+1 # new if (speed>100): # new speed=100 # new motor.ChangeDutyCycle(speed) # new time.sleep(0.05) # new # stop motor and cleanup GPIO except KeyboardInterrupt: print("Exiting now...") motor.stop() GPIO.cleanup() Most of the Python code above is fairly straightforward. The only statement that you haven’t come across before is the “motor.ChangeDutyCycle(speed)” statement which allows you to change the duty cycle of the PWM (and hence the speed of the motor) while the motor is running
Edit the existing code by copying, pasting, deleting and inserting until your code listing looks like as shown above. I have indicated where new lines of code have been inserted, and where existing lines of code have been changed to help you, but you do not need to include these comments
Student Workbook
24
Click on “File” and then “Save”
Click on “Run” and then “Run Module”
After a short delay the message “Press Ctrl+C to exit” appears in the Python Shell window. The program is now running and waiting for user input.
Press and hold the uppermost button
The motor will start running and increase in speed for as long as you hold the button down, or until it reaches its maximum speed
Press and hold the lowermost button
The motor will slow down for as long as you hold the button down, or until it stops completely
Start the motor again by pressing and holding the uppermost button until you reach the desired speed
Press the middle button
The motor will stop immediately
Continue to investigate the human machine interface to satisfy yourself that the buttons are controlling the motor in the way you expect them to.
When you have finished, press Ctrl+C (i.e. press and hold the “Ctrl” key, and at the same time press the “C” key) to exit the program
The message “Exiting now…” will be displayed on the Python Shell window
Click anywhere on the code window to bring it to the front
Now see if you can reprogram the user interface so that when you press the middle button, the motor not only stops immediately if it is running, but also when it is started again (by pressing the uppermost button) it turns in the opposite direction
This requires the inputs “A” and “B” to the L293D chip to be reversed. In other words, if input “A” is “On” and input “B” is “Off”, to change the direction of rotation of the motor requires that input “A” is “Off” and input “B” is “On”. Inputs “A” and “B” to the L293D chip are connected to GPIO pins 16 and 18 respectively, so to make the motor change direction you have to find a way of reversing the state of GPIO pins 16 and 18. To “read” the state of an output pin you can use the command “GPIO.input(x)” where “x” is the GPIO pin number, and to reverse the state of the pin (i.e. turn it “Off if it is “On”, or turn it “On” if it is “Off” you can use the operator “not”. Therefore to reverse the state of GPIO pins 16 and 18, you can use the following commands:
GPIO.output(16, (not GPIO.input(16))) GPIO.output(18, (not GPIO.input(18)))
Insert the two lines of code in the “if (GPIO.input(13)):” clause after the line “motor.ChangeDutyCycle(speed)”
Student Workbook
25
Your code should now look like this. I have indicated where new lines of code have been inserted but you do not need to include these comments # import modules import time import RPi.GPIO as GPIO # setup GPIO and PWM GPIO.setmode(GPIO.BOARD) GPIO.setup(16, GPIO.OUT) GPIO.setup(18, GPIO.OUT) GPIO.setup(22, GPIO.OUT) GPIO.setup(11, GPIO.IN) GPIO.setup(13, GPIO.IN) GPIO.setup(15, GPIO.IN) motor=GPIO.PWM(22,50) # prepare to start motor speed=0 motor.start(speed) GPIO.output(16,1) GPIO.output(18,0) print("Press Ctrl+C to exit") # wait for user input try: while True: if (GPIO.input(11)): # decrese speed speed=speed-1 if (speed<0): speed=0 motor.ChangeDutyCycle(speed) if (GPIO.input(13)): # emergency stop and change direction # changed speed=0 motor.ChangeDutyCycle(speed) GPIO.output(16, (not GPIO.input(16))) # new GPIO.output(18, (not GPIO.input(18))) # new if (GPIO.input(15)): # increase speed speed=speed+1 if (speed>100): speed=100 motor.ChangeDutyCycle(speed) time.sleep(0.05) # stop motor and cleanup GPIO except KeyboardInterrupt: print("Exiting now...") motor.stop() GPIO.cleanup()
Click on “File” and then “Save”
Click on “Run” and then “Run Module”
After a short delay the message “Press Ctrl+C to exit” appears in the Python Shell window. The program is now running and waiting for user input.
Student Workbook
26
Press and hold the uppermost button
The motor will start running and increase in speed for as long as you hold the button down, or until it reaches its maximum speed
Press the middle button
The motor will stop immediately
Press and hold the uppermost button
The motor will start running in the opposite direction and increase in speed for as long as you hold the button down, or until it reaches its maximum speed
Try stopping and reversing the direction of the motor a few times.
Does it work consistently?
You should find that sometimes the motor changes direction, and sometimes it doesn’t! The reason for this behaviour is that the code in the if (GPIO.input(13)):” clause will be executed on each cycle of the “while” loop as long as the middle button is pressed, and if the button is pressed long enough for the “wjile” loop to go through two cycles, the direction will first be reversed, and then reversed again, meaning that the direction of rotation of the motor will be back to where it was originally.
See if you can come up with a way to solve this problem There may be a number of ways to solve the problem, but one very simple way would be to add a short delay directly after the GPIO output pins are reversed. This should give time for the user to release the middle button before the “while” loop has time to cycle round again. It would also be a good idea to tell the user that the direction of rotation of the motor has been changed by printing a message on the Python Shell window
Insert the following two lines of code after “GPIO.output(18, (not GPIO.input(18)))”
print("Changing direction...") time.sleep(1)
Student Workbook
27
Your code should now look like this. I have indicated where new lines of code have been inserted but you do not need to include these comments # import modules import time import RPi.GPIO as GPIO # setup GPIO and PWM GPIO.setmode(GPIO.BOARD) GPIO.setup(16, GPIO.OUT) GPIO.setup(18, GPIO.OUT) GPIO.setup(22, GPIO.OUT) GPIO.setup(11, GPIO.IN) GPIO.setup(13, GPIO.IN) GPIO.setup(15, GPIO.IN) motor=GPIO.PWM(22,50) # prepare to start motor speed=0 motor.start(speed) GPIO.output(16,1) GPIO.output(18,0) print("Press Ctrl+C to exit") # wait for user input try: while True: if (GPIO.input(11)): # decrese speed speed=speed-1 if (speed<0): speed=0 motor.ChangeDutyCycle(speed) if (GPIO.input(13)): # emergency stop and change direction speed=0 motor.ChangeDutyCycle(speed) GPIO.output(16, (not GPIO.input(16))) GPIO.output(18, (not GPIO.input(18))) print("Changing direction...") # new time.sleep(1) # new if (GPIO.input(15)): # increase speed speed=speed+1 if (speed>100): speed=100 motor.ChangeDutyCycle(speed) time.sleep(0.05) # stop motor and cleanup GPIO except KeyboardInterrupt: print("Exiting now...") motor.stop() GPIO.cleanup()
Click on “File” and then “Save”
Click on “Run” and then “Run Module”
Student Workbook
28
After a short delay the message “Press Ctrl+C to exit” appears in the Python Shell window. The program is now running and waiting for user input
Investigate the behaviour of the system and check that it behaves in the way you expect it to
You should find now that pressing the middle button consistently causes the direction of rotation of the motor to reverse, and that each time the middle button is pressed, the message “Changing direction…” is displayed on the Python Shell window
When you have finished, press Ctrl+C (i.e. press and hold the “Ctrl” key, and at the same time press the “C” key) to exit the program
The message “Exiting now…” will be displayed on the Python Shell window
Click anywhere on the code window to bring it to the front
Now see if you can reformat the Python code by defining functions for “increasespeed”, “decreasespeed” and “stopandchangedirection” and calling these functions from within the “while” loop. Refer back to the previous part of this exercise (Step 2) if you can’t remember how to define a function
When you have finished running your modified code, press Ctrl+C (i.e. press and hold the “Ctrl” key, and at the same time press the “C” key) to exit the program
Click anywhere on the code window to bring it to the front
Close the code window by clicking on “File” and then “Close”
If you have made any changes to the code since the last time you saved you will be asked if you want to save before closing
Click “Yes” if you want to save your changes, or “No” if you want to close without saving
Click on “File” and then “Exit” to close the Python Shell window and exit IDLE3
Shutdown your Raspberry Pi (refer back to Step 4 of the Setup Guide if you can’t remember how to do this)