Chapter 11. Motors

11.0 Introduction

In this chapter, you will investigate the use of different types of motors with the Raspberry Pi. This includes DC motors, servo motors and stepper motors.

11.1 Controlling Servo Motors

Problem

You want to use a Raspberry Pi to control the position of a servo motor.

Solution

Use pulse-width modulation (PWM) to control the width of pulses to a servo motor to change its angle. Although this will work, the PWM generated is not completely stable, so there will be a little bit of jitter with the servo. For alternative solutions that produce much more stable pulse timing, see Recipe 11.2 and Recipe 11.3.

If you have an older Raspberry Pi 1, you should also power the servo from a separate 5V power supply because peaks in the load current are very likely to crash or overload the Raspberry Pi. If you have a Raspberry Pi B+ or newer, improvements in the onboard voltage regulation mean that you might get away with powering small servos directly from the 5V pin on the general-purpose input/output (GPIO) port.

Figure 11-1 shows a small 9g servo (see “Miscellaneous”) working quite happily with a Raspberry Pi B+.

F1001
Figure 11-1. Direct connection of a small servo to a Raspberry Pi B+

The leads of the servo are usually 5V wire as red, the ground as brown, and the control lead as orange. The 5V and ground leads are connected to the GPIO header 5V and GND pins, and the control lead is connected to pin 18. The connections are made with female-to-male header leads.

If you are using a separate power supply, a breadboard is a good way of keeping all the leads together.

In this case, you will need the following:

Figure 11-2 shows the breadboard layout for this.

F10b01
Figure 11-2. Controlling a servo motor

The 1kΩ resistor is not essential, but it does protect the GPIO pin from unexpectedly high currents in the control signal, which could occur if a fault developed on the servo.

You can, if you prefer, power the servo from a battery pack rather than a power supply. Using a four-cell AA battery holder with rechargeable batteries will provide around 4.8V and will work well with a servo. Using four alkali AA cells to provide 6V will be fine for many servos, but check the datasheet of your servo to make sure it is OK with 6V.

The user interface for setting the angle of the servo is based on the ch_10_gui_slider.py program, which is intended for controlling the brightness of an LED (Recipe 10.9). However, you can modify it so that the slider sets the angle to be between –90 and 90 degrees (Figure 11-3).

Figure 11-3. User interface for controlling a servo motor

Open an editor and paste in the following code (the file is called ch_11_servo.py):

from gpiozero import AngularServo
from guizero import App, Slider

servo = AngularServo(18, min_pulse_width=0.5/1000, max_pulse_width=2.5/1000)

def slider_changed(angle):
    servo.angle = int(angle)   

app = App(title='Servo Angle', width=500, height=150)
slider = Slider(app, start=-90, end=90, command=slider_changed, width='fill',
                height=50)
slider.text_size = 30
app.display()

As with all the program examples in this book, you can download this code (see Recipe 3.22).

Note that this program uses a graphical user interface, so you cannot run it from SSH or the Terminal. You must run it from the windowing environment on the Pi itself or via remote control using virtual network computing (VNC) (Recipe 2.8) or Remote Desktop Protocol (RDP) (Recipe 2.9).

The gpiozero class AngularServo takes care of all the pulse generation. It just leaves us to specify the angle to which we want the servo arm to position itself. Pretty much all other software that works with servo motors specifies angles of between 0 and 180 degrees, where 0 is as far as the servo arm can go to one side, 90 is in the middle, and 180 is as far as it can go to the other side. The gpiozero library does things differently, and probably more logically, by referring to the center position as 0 and to the angles on one side as negative and on the other side as positive.

When defining the servo, the first parameter (18 in this case) specifies the control pin for the servo motor. The optional parameters of min_pulse_width and max_pulse_width set the minimum and maximum pulse lengths in seconds. For a typical servo, these values should be 0.5 milliseconds and 2.5 milliseconds. For some reason the default values in gpiozero are 1 and 2 milliseconds; thus the servo motor has a very restricted range unless you set these values as we have here.

Discussion

Servo motors are used in remote control vehicles and robotics. Most servo motors are not continuous; that is, they cannot rotate all the way around but rather can rotate only over an angle range of about 180 degrees.

The position of the servo motor is set by the length of a pulse. The servo expects to receive a pulse at least every 20 milliseconds. If that pulse is high for 0.5 milliseconds, the servo angle will be –90 degrees; if it’s for 1.5 milliseconds, the motor will be at its center position (0 degrees); and if the pulse is high for 2.5 milliseconds, the servo angle will be 90 degrees (Figure 11-4).

Figure 11-4. Servo motor timing pulses

If you have a few servo motors to connect, the MonkMakes ServoSix board (Figure 11-5) makes the wiring easier.

Figure 11-5. Connecting servo motors with the ServoSix board

See Also

If you have a lot of servos to control or require greater stability and precision, you can use a dedicated servo controller module, as described in Recipe 11.3.

See more information in the full documentation of the ServoSix board.

Adafruit has developed another method of servo control.

For an alternative solution that produces much more stable pulse timing using the ServoBlaster device driver software, see Recipe 11.2.

11.2 Controlling Servo Motors Precisely

Problem

The pulse generation function of the gpiozero library is not precise or jitter-free enough for your servo application.

Solution

Install the ServoBlaster device driver.

ServoBlaster and Sound

The ServoBlaster software uses Raspberry Pi hardware that is also involved in generating sound. Thus, you won’t be able to play audio through your Raspberry Pi’s audio jack or HDMI while using ServoBlaster.

The ServoBlaster software created by Richard Hirst uses Raspberry Pi CPU hardware to generate pulses with much more accurate timings than are possible using gpiozero. Install ServoBlaster using the following commands and then reboot your Raspberry Pi:

$ git clone git://github.com/richardghirst/PiBits.git
$ cd PiBits/ServoBlaster/user
$ sudo make 
$ sudo make install

You can modify the program from Recipe 11.1 to use the ServoBlaster code. You can find the modified program in the file ch_11_servo_blaster.py. As with all the program examples in this book, you can download it (see Recipe 3.22). This program assumes that the servo control pin is connected to GPIO 18:

import os
from guizero import App, Slider

servo_min = 500  # uS
servo_max = 2500 # uS
servo = 2        # GPIO 18

def map(value, from_low, from_high, to_low, to_high): 
  from_range = from_high - from_low
  to_range = to_high - to_low
  scale_factor = float(from_range) / float(to_range)
  return to_low + (value / scale_factor)
  
def set_angle(angle):
  pulse = int(map(angle+90, 0, 180, servo_min, servo_max))
  command = "echo {}={}us > /dev/servoblaster".format(servo, pulse)
  os.system(command)

def slider_changed(angle):
  set_angle(int(angle))  

app = App(title='Servo Angle', width=500, height=150)
slider = Slider(app, start=-90, end=90, command=slider_changed, width='fill',
                height=50)
slider.text_size = 30
app.display()

The user interface code is just the same as Recipe 11.1. The differences are in the set_angle function. The set_angle function first uses a utility function called map that converts the angle into a pulse duration using the constants servo_min and servo_max. Then it constructs a command that will be run as if from the command line. The format of this line starts with the echo command, followed by the servo number to be controlled, an equals sign, and then a pulse duration in microseconds. This string part of the command will be directed to the device /dev/servoblaster. The servo will then adjust its angle.

Killing ServoBlaster

When ServoBlaster, or more specifically, the service servo.d, is running, you will not be able to use the servo pins for anything, and audio on the Raspberry Pi will not work. So when you need to use the pins for something else, use the following commands to disable ServoBlaster and then reboot your Pi:

$ sudo update-rc.d servoblaster disable
$ sudo reboot

When your Raspberry Pi restarts, ServoBlaster will no longer have control of your pins, and you will be able to use sound again on your Pi. You can always turn ServoBlaster back on again using:

$ sudo update-rc.d servoblaster enable
$ sudo reboot

Discussion

The ServoBlaster driver is actually very powerful, and you can configure it to allow you to use pretty much all the GPIO pins to control servos. Its default setup defines eight GPIO pins to act as servo control pins. These are each given a channel number, as shown in Table 11-1.

Table 11-1. Servo channel default pin allocation for ServoBlaster
Servo channel GPIO pin
0 4
1 17
2 18
3 27
4 22
5 23
6 24
7 25

Connecting so many servos can result in jumper-lead spaghetti. A board like the MonkMakes ServoSix (Figure 11-5) greatly simplifies the wiring of the servos to your Raspberry Pi.

See Also

More information is available in the full documentation for ServoBlaster.

If you do not need the precise timing of ServoBlaster, the gpiozero library can also generate pulses for your servo, as described in Recipe 11.1.

11.3 Controlling Multiple Servo Motors Precisely

Problem

You need to control lots of servos with high precision and without the loss of sound that comes with using ServoBlaster.

Solution

Although the ServoBlaster code (see Recipe 11.2) allows you to control up to eight servos accurately, it does rather take over your Raspberry Pi’s hardware and disables sound generation.

The alternative to ServoBlaster is to use a servo motor HAT like the one shown in Figure 11-6 that has its own servo controlling hardware, relieving the Raspberry Pi’s hardware.

This Adafruit HAT allows you to control up to 16 servos or PWM channels using the I2C interface of the Raspberry Pi. The servos just plug straight into the HAT.

Power is supplied to the logic circuits of the module from the 3.3V connection of the Raspberry Pi. This is entirely separate from the power supply for the servo motors, which comes from an external 5V power adapter.

You can, if you prefer, power the servos from a battery pack rather than a power supply. Using a four-cell AA battery holder with rechargeable batteries provides around 4.8V and works well with most servos. Using four alkali AA cells to provide 6V will be fine for many servos, but check the datasheet of your servo to make sure it is OK with 6V.

The pin headers for connecting servos are conveniently arranged so that the servo lead fits directly onto the pins. Be careful to get them facing the correct way.

F1002
Figure 11-6. Adafruit servo motor HAT

To use the Adafruit software for this module, you will need to set up I2C on the Raspberry Pi (Recipe 9.3).

The software for this board uses some useful software from Adafruit that allows you to use an entire range of their accessory add-on boards.

To install the Adafruit blinka code needed for this board, run the following commands:

$ pip3 install adafruit-blinka
$ sudo pip3 install adafruit-circuitpython-servokit

Open an editor and paste in the following code (the name of the file is ch_11_servo_adafruit.py):

from adafruit_servokit import ServoKit
from guizero import App, Slider

servo_kit = ServoKit(channels=16)

def slider_changed(angle):
    servo_kit.servo[0].angle = int(angle) + 90  

app = App(title='Servo Angle', width=500, height=150)
slider = Slider(app, start=-90, end=90, command=slider_changed, width='fill',
                height=50)
slider.text_size = 30
app.display()

As with all the program examples in this book, you can also download this code (see Recipe 3.22).

When you run the program, you will get the same window containing a slider as shown in Figure 11-3. Use this to move the servo arm about. Adafruit’s software is not compatible with Python 2, so you need to run any programs that use the Adafruit software via the python3 command.

Note that this program uses a graphical user interface (GUI), so you can’t run it from SSH or the Terminal; you must run it from the windowing environment on the Pi itself or via remote control using VNC (Recipe 2.8) or RDP (Recipe 2.9):

$ python3 ch_11_servo_adafruit.py

The Adafruit software uses the servo motor angle range of 0 to 180 rather than gpiozero’s –90 to 90 degrees, so to keep the user interface the same, 90 is added to the angle supplied by the slider.

To address a specific servo channel among the 16 available channels, the channel number (between 0 and 15) is specified inside the square brackets in the command servo_kit.servo[0].angle.

Discussion

When selecting a power supply for this module, remember that a standard remote control servo can easily draw 400mA while it’s moving, and more if it’s under load. So if you plan to have a lot of large servos moving at the same time, you will need a big power adapter.

See Also

For information on this Adafruit product, see https://www.adafruit.com/product/2327.

A Servo HAT is great if your Raspberry Pi is close to the servo motors, but if your servos are distant from where you want the Raspberry Pi to be, Adafruit also sells a servo module (product ID 815) that has the same servo controller hardware as the servo HAT but just four pins to connect the I2C interface of the board to the Raspberry Pi’s I2C interface.

11.4 Controlling the Speed of a DC Motor

Problem

You want to control the speed of a DC motor using your Raspberry Pi.

Solution

You can use the same design as Recipe 10.4. It is, however, a good idea to place a diode across the motor to prevent voltage spikes from damaging the transistor or even the Raspberry Pi. The 1N4001 is a suitable diode for this. The diode has a stripe at one end, so make sure that this is facing the proper direction (Figure 11-7).

F10b05
Figure 11-7. Controlling a high-power motor

You will need the following:

As with all the program examples in this book, you can also download this program (see Recipe 3.22). The file is called ch_10_gui_slider.py.

Note that this program uses a GUI, so you can’t run it from SSH. You must run it from the windowing environment on the Pi itself or via remote control using VNC (Recipe 2.8) or RDP (Recipe 2.9).

Discussion

If you are using only a low-power DC motor (less than 200mA), you can use a smaller (and cheaper) transistor such as the 2N3904 (see “Transistors and Diodes”). Figure 11-8 shows the breadboard layout to use a 2N3904.

You can probably get away with powering a small motor from the 5V supply line on the GPIO connector. If you find that the Raspberry Pi crashes, use an external power supply, as shown in Figure 11-7.

F10b06
Figure 11-8. Controlling a low-power motor

See Also

This design controls only the motor’s speed. It can’t control its direction. For that, you need to see Recipe 11.5.

For more information on using a breadboard and jumper wires with the Raspberry Pi, see Recipe 9.8.

11.5 Controlling the Direction of a DC Motor

Problem

You want to control both the speed and direction of a small DC motor.

Solution

Use an H-Bridge chip or module, the most common chip being the L293D. These are low cost and easy to use. Other H-Bridge chips or modules usually use the same pair of control pins for the direction of each motor (see the forthcoming Discussion).

The L293D chip is actually capable of driving two motors without any extra hardware. The Discussion also mentions a few other options for controlling DC motors. To try out the L293D to control a motor, you will need the following:

Figure 11-9 shows the breadboard layout.

Figure 11-9. Using an L293D chip to control a motor

Make sure the chip is facing the proper direction: there is a notch in its top, which is the end that should be at the top of the breadboard.

The test program for this recipe (ch_11_motor_control.py) allows you to enter the letter f or r and then a single digit between 0 and 9. The motor will then either go forward or backward at a speed specified by the digit—0 for stopped, 9 for full speed:

$ python3 ch_11_motor_control.py
Command, f/r 0..9, E.g. f5 :f5
Command, f/r 0..9, E.g. f5 :f1
Command, f/r 0..9, E.g. f5 :f2
Command, f/r 0..9, E.g. f5 :r2

Open an editor and paste in the following code. As with all the program examples in this book, you can also download it (see Recipe 3.22).

This program uses the command line, so you can run it from SSH or the Terminal:

from gpiozero import Motor

motor = Motor(forward=23, backward=24)
 
while True:
    cmd = input("Command, f/r 0..9, E.g. f5 :")
    direction = cmd[0]
    speed = float(cmd[1]) / 10.0
    if direction == "f":
        motor.forward(speed=speed)
    else: 
        motor.backward(speed=speed)

gpiozero conveniently has a class called Motor that we can use to control both the speed and direction of a single DC motor. When you create an instance of the class, you need to specify the forward and backward control pins.

The forward and backward methods of Motor take an optional parameter of speed between 0 and 1, where 1 is full speed.

Discussion

The Motor class of gpiozero hides the complexity of the H-Bridge’s hardware.

Figure 11-10 shows how an H-Bridge works, using switches rather than transistors or a chip. By reversing the polarity across the motor, an H-Bridge also reverses the direction in which the motor turns.

In Figure 11-10, S1 and S4 are closed and S2 and S3 are open. This allows current to flow through the motor, with terminal A being positive and terminal B being negative. If we were to reverse the switches so that S2 and S3 are closed and S1 and S4 are open, B would be positive and A would be negative, and the motor would turn in the opposite direction.

However, you might have spotted a danger with this circuit. If by some chance S1 and S2 are both closed, the positive supply will be directly connected to the negative supply and you will have a short circuit. The same is true if S3 and S4 are both closed at the same time.

rpck 1010
Figure 11-10. An H-Bridge

Although you can use individual transistors to make an H-Bridge, it is simpler to use an H-Bridge integrated circuit (IC) such as the L293D. This chip actually has two H-Bridges in it, so you can use it to control two motors. It also has logic to ensure that the equivalent of closing both S1 and S2 cannot happen.

The L293 uses two control pins for each of the two motor control channels: a forward pin and a backward pin. If the forward pin (23) is high and the backward pin (24) is low, the motor will turn in one direction. If those two pins are reversed, the motor will turn in the opposite direction.

As an alternative to using an L293D on a breadboard, very low-cost modules are available from eBay that include a L293D on a printed circuit board (PCB) with screw terminals to attach motors and header pins to link directly to the Raspberry Pi GPIO connector. If you need a higher-power motor controller module, you can find motor controller modules that operate on the same principles but at much higher currents, even up to 20A or more. Pololu has an impressive range of such motor controller boards.

See Also

You also can use the Adafruit Stepper Motor HAT (Recipe 11.8) and RasPiRobot Board (Recipe 11.9) to control the speed and direction of a DC motor.

Check out the L293D datasheet and the SparkFun Motor Driver module product page.

For more information on using a breadboard and jumper wires with the Raspberry Pi, see Recipe 9.8.

11.6 Using a Unipolar Stepper Motor

Problem

You want to drive a five-lead unipolar stepper motor using a Raspberry Pi.

Solution

Use a ULN2803 Darlington driver chip on a breadboard.

Stepper motors fit somewhere between DC motors and servo motors in the world of motor technologies. Like a regular DC motor, they can rotate continuously, but you can also very accurately position them by moving them a step at a time in either direction.

To make this recipe, you will need the following:

Figure 11-11 shows the wiring diagram for using a ULN2803. Note that you can use the chip to drive two such motors. To drive a second stepper motor, you need to connect four more control pins from the GPIO connector to pins 5 to 8 of the ULN2803, and then you connect the second motor’s four pins to pins 11 to 14 of the ULN2803.

F10b11
Figure 11-11. Using a ULN2803 to control a unipolar stepper motor

The 5V supply from the GPIO connector can work acceptably with a small stepper motor. If you experience problems with the Raspberry Pi crashing or need to use a bigger stepper motor, use a separate supply for the power to the motor (pin 10 of the ULN2803).

Open an editor and paste in the following code (ch_11_stepper.py). This program uses the command line, so you can run it from SSH:

from gpiozero import Motor
import time

coil1 = Motor(forward=18, backward=23, pwm=False)
coil2 = Motor(forward=24, backward=17, pwm=False)
 
forward_seq = ['FF', 'BF', 'BB', 'FB']
reverse_seq = list(forward_seq) # to copy the list
reverse_seq.reverse()
 
def forward(delay, steps):  
  for i in range(steps):
    for step in forward_seq:
      set_step(step)
      time.sleep(delay)
 
def backwards(delay, steps):  
  for i in range(steps):
    for step in reverse_seq:
      set_step(step)
      time.sleep(delay)

def set_step(step):
  if step == 'S':
    coil1.stop()
    coil2.stop()
  else:
    if step[0] == 'F':
      coil1.forward()
    else:
      coil1.backward()
    if step[1] == 'F':
      coil2.forward()
    else:
      coil2.backward()

while True:
  set_step('S')
  delay = input("Delay between steps (milliseconds)?")
  steps = input("How many steps forward? ")
  forward(int(delay) / 1000.0, int(steps))
  set_step('S')
  steps = input("How many steps backwards? ")
  backwards(int(delay) / 1000.0, int(steps))

As with all the program examples in this book, you can also download this code (see Recipe 3.22).

When you run the program, you are prompted for a delay between steps. This should be 2 or more. You are then prompted for the number of steps in each direction:

$ python3 ch_11_stepper.py
Delay between steps (milliseconds)?2
How many steps forward? 100
How many steps backwards? 100
Delay between steps (milliseconds)?10
How many steps forward? 50
How many steps backwards? 50
Delay between steps (milliseconds)?

This code is explained in the Discussion section that follows, because it helps to know a bit more about how stepper motors work to follow the code.

Discussion

Stepper motors use a cogged rotor with alternating north and south poles and electromagnets to nudge the wheel around a step at a time (Figure 11-12). Note that the colors of the leads will vary.

Energizing the coils in a certain order drives the motor around. The number of steps that the stepper motor has in a 360-degree rotation is actually the number of teeth on the rotor.

rpck 1012
Figure 11-12. A stepper motor

The two coils are each controlled by an instance of the gpiozero class Motor and are called coil1 and coil2.

The program uses a list of strings to represent each of the four energization stages that make up a single step:

forward_seq = ['FF', 'BF', 'BB', 'FB']

Each pair of letters indicates the current direction for coil1 and coil2: either Forward or Backward. So, looking for a moment at Figure 11-12 and assuming that the common Red connection is to GND, the letter F for the Pink-Orange coil might make Pink high and Orange low, whereas B would reverse this.

The sequence for rotating the motor in the opposite direction is just the reverse of the sequence for moving forward.

You can use the forward and backward functions in your programs to step the motor back and forth. The first argument to either function is the delay in milliseconds between each part of the step sequence. The minimum value for this depends on the motor you use. If it’s too small, the motor will not turn. Typically, two milliseconds or more will be fine. The second parameter is the number of steps to take:

def forward(delay, steps):
  for i in range(steps):
    for step in forward_seq:
      set_step(step)
      time.sleep(delay)

The forward function has two nested for loops. The outer loop repeats for the number of steps, and the inner one iterates over the sequence of motor activations, calling set_step for each in sequence:

def set_step(step):
  if step == 'S':
    coil1.stop()
    coil2.stop()
  else:
    if step[0] == 'F':
      coil1.forward()
    else:
      coil1.backward()
    if step[1] == 'F':
      coil2.forward()
    else:
      coil2.backward() 

The set_step function sets each coil’s polarity, depending on the message supplied as its step argument. The command S stops the power to both coils so that we can avoid using current when the motor isn’t moving. If the first letter is an F, then coil1 is set to forward; otherwise it is set to backward. coil2 is set in the same way but using the second letter of step.

The main loop sets the step to S between moving forward and backward, to deactivate both coils when the motor is not actually turning. Otherwise, one of the coils might be left on, causing the motor to unnecessarily draw current.

See Also

If you have a four-wire bipolar stepper motor, see Recipe 11.7.

For more information, see the Wikipedia article on stepper motors, where you will also see the different types and how they work, as well as find a nice, animated explanation of the activation pattern for driving the motor.

For information on using servo motors, see Recipe 11.1; for information on controlling DC motors, see Recipes Recipe 11.4 and Recipe 11.5.

For more information on using a breadboard and jumper wires with the Raspberry Pi, see Recipe 9.8.

11.7 Using a Bipolar Stepper Motor

Problem

You want to drive a four-lead bipolar stepper motor using a Raspberry Pi.

Solution

Use an L293D H-Bridge driver chip. An H-Bridge is required to drive a bipolar stepper motor because, as the word bipolar suggests, the direction of current across the windings needs to be reversed, rather like driving a DC motor in both directions (see Recipe 11.5).

To make this recipe, you will need the following:

The motor used here, a 12V, is somewhat larger than the previous unipolar stepper motor example. The power for the motor itself is therefore supplied from an external power supply rather than from the Raspberry Pi. See the wiring diagram in Figure 11-13.

F10b13
Figure 11-13. Using an L293D to control a bipolar stepper motor

Discussion

A bipolar stepper motor is just like the unipolar version shown in Figure 11-12, except that the “Red” central tapping connections to the coils are not present. The same energization pattern will work just as well on both variants, but for a bipolar motor, the direction of the current in the whole of the coil must be reversable; hence, two H-bridges are necessary.

You can use the same ch_11_stepper.py program to control this stepper (see Recipe 11.6). The design uses both H-Bridges of the L293D, so you need one of these chips for each motor that you want to control.

See Also

If the type of stepper motor you have is a five-wire unipolar stepper motor, see Recipe 11.6.

For more information on stepper motors—the different types and how they work—see Wikipedia, where you will also find a nice animated explanation of the activation pattern for driving the motor.

For information on using servo motors, see Recipe 11.1; for information on controlling DC motors, see Recipes Recipe 11.4 and Recipe 11.5.

For more information on using a breadboard and jumper wires with the Raspberry Pi, see Recipe 9.8.

You can also drive a stepper motor by using the RasPiRobot Board (Recipe 11.9).

11.8 Using a Stepper Motor HAT to Drive a Bipolar Stepper Motor

Problem

You want to control multiple bipolar stepper motors using a single interface board.

Solution

Use an Adafruit Stepper Motor HAT.

This board is capable of driving two bipolar stepper motors. Figure 11-14 shows the board with one bipolar stepper motor, with one coil connected to the M1 terminals and the other coil to the M2 terminals. The power for the motors is supplied separately at the screw terminals on the right.

I2C Busses

If you followed Recipe 9.20 to make your own HAT and enabled the I2C bus 0 as described there, you will need to reverse the change to /boot/config.txt because the Adafruit autodetects the I2C bus to use and will detect the wrong one if bus 0 is enabled.

In /boot/config.txt, delete or comment out this line (by putting a # at the beginning of it):

dtparam=i2c_vc=on

After you do this, reboot your Raspberry Pi.

F1004
Figure 11-14. Using an Adafruit Stepper Motor HAT to control a bipolar stepper motor

This HAT uses I2C, so make sure that you have I2C enabled (Recipe 9.3).

This board is supported by an excellent Adafruit tutorial.

Discussion

When you run the program supplied in the Adafruit tutorial, the motor begins to turn, and the program loops around four different modes of stepping.

See Also

For a discussion of the HAT standard and how to make your own HAT, see Recipe 9.20.

For more information on using this HAT and its accompanying library, see https://learn.adafruit.com/adafruit-dc-and-stepper-motor-hat-for-raspberry-pi.

To use an L293D to control a stepper motor, see Recipe 11.7; to use a RasPiRobot Board, see Recipe 11.9.

11.9 Using a RasPiRobot Board to Drive a Bipolar Stepper Motor

Note

Be sure to check out the accompanying video for this recipe at http://razzpisampler.oreilly.com.

Problem

You want to control a bipolar stepper motor by using one power supply for both the motor and your Raspberry Pi.

Solution

Use a RasPiRobot Board version 4.

The RasPiRobot Board uses the power supply directly from its screw terminals as the supply to the motor and regulates that same supply down to 5V to drive the Raspberry Pi. So in this case, the 12V power will be supplying both the 12V stepper motor and the Raspberry Pi.

Warning

If you are using one of the first versions of the RasPiRobot Board (version 1 or 2), do not power the Raspberry Pi through its USB connection at the same time, because you power it through the RasPiRobot Board.

There is no problem powering it through both in version 3 or 4 of the board.

Connect the stepper motor and power supply to the RasPiRobot Board as shown in Figure 11-15. TThe wire colors for the Adafruit 12V stepper motor are, in order from the bottommost wire: yellow and red (coil 1), gray and green (coil 2).

Figure 11-15. Using a RasPiRobot Board to control a bipolar stepper motor

Before you can run the program, you will need to install the library for the RaspiRobot Board v4 using the following commands:

$ git clone https://github.com/simonmonk/rrb4.git
$ cd rrb4/python
$ sudo python3 setup.py install

Open an editor and paste in the following code (ch_11_stepper_rrb.py). This program uses the command line, so you can run it from SSH:

from rrb4 import *
import time

rr = RRB4(12.0, 12.0) # battery, motor

try: 
    while True:
        delay = input("Delay between steps (milliseconds)?")
        steps = input("How many steps forward? ")
        rr.step_forward(int(delay) / 1000.0, int(steps))
        steps = input("How many steps backwards? ")
        rr.step_reverse(int(delay) / 1000.0, int(steps))

finally:
    GPIO.cleanup()

As with all the program examples in this book, you can also download this code (see Recipe 3.22).

Discussion

You will find that there is a minimum value of "Delay between steps", below which the motor will judder rather than turn.

See Also

You can find full documentation for the RasPiRobot Board and other projects that use it at the RasPiRobot website.

To drive a stepper motor using an L293D H-Bridge driver chip on a breadboard, see Recipe 11.7.

11.10 Building a Simple Robot Rover

Problem

You want to use a Raspberry Pi as the controller for a simple roving robot.

Solution

Use a RasPiRobot Board v4 or other motor controller board as an interface board to the Raspberry Pi to control two motors and a robot chassis kit.

To make this recipe, you will need the following:

The first step in building the robot is to assemble the chassis. Most low-cost gearmotor chassis are supplied with a four-cell AA battery holder, so you might not need to buy one separately.

Follow the wiring instructions shown in Figure 11-16.

Figure 11-16. Wiring a roving robot

The battery pack will supply power to the RasPiRobot Board, which in turn supplies 5V to the Raspberry Pi. So only one power supply is required.

The finished rover should look something like Figure 11-17, which also has a rangefinder on the front for good measure.

F1007
Figure 11-17. The finished robot

To drive the robot, you are going to use a control program that allows you to steer the rover using keys on a laptop or other computer connected to your Raspberry Pi over SSH. If you have not already done so, set up your Raspberry Pi to use WiFi and SSH, using Recipe 2.5 and Recipe 2.7, respectively.

Open an editor and paste in the following code (ch_11_rover.py):

from rrb4 import *
import sys
import tty
import termios

rr = RRB4(6.0, 6.0) # battery, motor

UP = 0
DOWN = 1
RIGHT = 2
LEFT = 3

print("Use the arrow keys to move the robot")
print("Press Ctrl-C to quit the program")

# These functions allow the program to read your keyboard
def readchar():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    if ch == '0x03':
        raise KeyboardInterrupt
    return ch

def readkey(getchar_fn=None):
    getchar = getchar_fn or readchar
    c1 = getchar()
    if ord(c1) != 0x1b:
        return c1
    c2 = getchar()
    if ord(c2) != 0x5b:
        return c1
    c3 = getchar()
    return ord(c3) - 65  # 0=Up, 1=Down, 2=Right, 3=Left arrows

# This will control the movement of your robot and display on your screen
try: 
    while True:
        keyp = readkey()
        if keyp == UP:
            rr.forward(1)
            print('forward')
        elif keyp == DOWN:
            rr.reverse(1)
            print('backward')
        elif keyp == RIGHT:
            rr.right(1)
            print('clockwise')
        elif keyp == LEFT:
            rr.left(1)
            print('anti clockwise')
        elif keyp == LEFT:
            rr.left(1)
            print('anti clockwise')   
        elif ord(keyp) == 3:
            break

except KeyboardInterrupt:
    GPIO.cleanup()


As with all the program examples in this book, you can also download this code (see Recipe 3.22).

To be able to intercept keypresses, this program uses the termios library and the functions readchar and readkey.

After the import commands, a new instance of RRB4 is created. The two parameters to this are the battery voltage and the motor voltage (in this case, 6V and 6V). If your chassis has different voltage motors, change the second parameter.

The main loop just checks for keypresses and then sends the appropriate commands of forward, reverse, left, or right to the RRB4 library.

Discussion

You can make the rover more interesting by adding peripherals to it. You could, for example, attach a webcam and set up web streaming so that your roving robot becomes a roving spycam (Recipe 4.3).

The RRB4 library also supports the HC-SR04 rangefinder, which can be plugged into a socket on the RasPiRobot Board v4. You can use this to detect obstacles. You can find example software for this in the RRB4 library.

See Also

You can find out more about the RasPiRobot board and the RRB4 library on GitHub.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset