Motor controller concepts
The motor controller has two halves. Each half controls a motor using two outputs, using power and three I/O input pins. The motor outputs can handle higher currents and voltage than the inputs need. Connecting motors directly to Raspberry Pi would damage it. The enable input pins turn on half of the controller. Labelled ENA for motor A or ENB for motor B, they are connected with a ‘jumper wire’ to a 5 V line (held high) to keep the half enabled. Each motor has two direction control pins: IN1 and IN2 for motor A; IN3 and IN4 for motor B.
Controlling speed and direction
The IN pins are used in pairs to control a motor. See Table 1 for how the pins control the direction of the motor. You can substitute IN 3 and IN 4 for the behaviour on the other motor.
This controls the direction, but what about speed? By turning the motor power on and off rapidly (in square waves), the ratio of time on vs time off changes the speed of the motor. Figures 1 and 2 show how this works. This is known as pulse-width modulation or PWM. The GPIO Zero library can set the direction and the PWM speed.
Not driving off the table
Robots under test have a tendency to shoot off until they hit a wall or off a desk, and not in the direction you expect. Emergency stop measures are essential. First, ensure that motors are always turned off. Python’s try…finally block applies in almost all cases. Even if the program crashes, it runs the finally code. try: pass # Code that starts motors finally: # Code to stop motors The other measure is an emergency stop button. Python comes with such a button built-in: pressing the keyboard combination CTRL+C will stop the code running and enter the finally code.
Setting up robot code
The setup for robot experiments is in drive_forward.py. Use this as a template for robot code.
import gpiozero import time robot = gpiozero.Robot(left=(27, 17), right=(24, 23)) try: # Robot actions here robot.forward() time.sleep(1) finally: robot.stop()
Line 1 and 2 make the GPIO Zero and time libraries available by importing them. GPIO Zero has a handy robot object to control two motors. At line 4, a robot object is created with pin numbers for the motor controller. Lines 6 and 10 provide the stop mechanism from Step 6, with line 10 stopping the robot.
Between these lines, after the comment (starting with a ‘#’) on line 7 is the code to make the robot do something. This code can be swapped/changed for different movement.
In drive_forward.py, line 8 instructs the controller to drive both motors forward. The delay on line 9 is needed so that the robot drives for a little time before stopping the motors. time.sleep() uses a time in seconds. Put in batteries to switch to battery power. If you don’t have a switch, use the last battery as one. Use SCP to put this code on the robot or use Raspberry Pi to edit it. Put it in /home/pi. Give the robot space to drive and run the code: python3 drive_forward.py It should drive forward for one second and stop. Press CTRL+C if it does not stop.
Troubleshooting driving forwards
If running drive_forward.py shows errors, check everything in Step 3, and that the code is exactly as listed. If one motor (or both) doesn’t move, inspect the motor controller wiring. Ensure the enable jumpers are fitted. If the motors whine but don’t move, try fresh batteries. If a motor goes backwards, then swap its pin numbers on line 4. The robot may veer to one side; check the motors are glued in well, without friction between wheels, axles, and robot. Some veer is unavoidable without sensors. This is when loose screws in the robot will show up and need fixing.
Simple turns and driving backwards
The robot object in GPIO Zero makes it very easy to do this for the simplest movements. Where the code has robot.forward() on line 8 of drive_forward.py, this can be replaced with robot.left(). It is only now you will find out if you have the motors the correct way around! If the robot drives to the right, then swap the left and right keywords on line 4. The robot is likely to turn too far, so reduce the timer value in line 9, this can be decimals, so try 0.3 seconds here. On line 8, try robot.right and robot.backward too.
Moving at slower speeds
A robot’s motors can do more than just change direction: PWM can be used to vary the speed. The listing speed_control.py shows how. Line 8 sets up a loop, in this case counting down from 10 to 4. The speed is set in line 9 using robot.value, with the left value setting the left motor speed, and the right value setting the right. Values go from zero to 1, so divide by 10. Negative values go backwards. Lines 12 to 15 do some turns with more precise control than the robot.left or robot.right commands. These will be handy for sensors.
The full code listing from the MagiPi series is here: