Controlling a Large Number of Servo Motors
You want to control a number of servos, and you need high-quality positioning of the servo motor.
Use a servo controller module like this one from Adafruit: http://www.adafruit.com/products/815.
This module allows you to control up to 16 servos or PWM channels using the I2C interface of the Raspberry Pi.
To make this recipe, you will need:
• 1 or more 5V servo motors (see “Miscellaneous” on page 382)
• Adafruit 12-bit PWM/servo driver—I2C interface (see “Modules” on page 381)
• Breadboard and jumper wires (see “Prototyping Equipment” on page 380)
• 5V power supply or 4.8V battery pack (see “Miscellaneous” on page 382)
Figure 10-4 shows how you can wire one of these modules to a Raspberry Pi using a breadboard.
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 will provide around 4.8V and work 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 will fit directly onto the pins. Be careful to get them the right way around.
To use the Adafruit software for this module, you will need to install Git (Recipe 3.19) and also set up I2C on the Raspberry Pi (Recipe 8.4). Follow both of these recipes before you go any further.
The Adafruit library isn’t really a proper library that contains an installation script, but rather just a directory that contains a number of files. So, when using it, you need to be in the directory to which they are downloaded or your program will not find them.
To download all the Adafruit software library for Raspberry Pi, enter the following:
$ git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git $ cd Adafruit-Raspberry-Pi-Python-Code $ cd Adafruit_PWM_Servo_Driver |
The last two lines set the current directory to the directory containing the code for PWM as well as an example program supplied by Adafruit, which you can run with the command:
$ sudo python Servo_Example.py |
An alternative example next modifies the example program from Recipe 10.2 so that you can use a slider to set the servo position between 0 and 180 degrees. The program file must be saved in the Adafruit_PWM_Servo_Driver directory. The slider will change the servo positions of both channels 0 and 1 at the same time, so the two servos should move in the same way when you adjust the slider.
Open an editor (nano or IDLE) and paste in the following code. As with all the program examples in this book, you can also download the program from the Code section of the Raspberry Pi Cookbook website, where it is called servo_module.py. Note that this program uses a graphical user interface, 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).
from Tkinter import * from Adafruit_PWM_Servo_Driver import PWM import time pwm = PWM(0x40) pwm.setPWMFreq(50) class App: def __init__(self, master): frame = Frame(master) frame.pack() scale = Scale(frame, from_=0, to=180, orient=HORIZONTAL, command=self.update) scale.grid(row=0) def update(self, angle): pulse_len = int(float(angle) * 500.0 / 180.0) + 110 pwm.setPWM(0, 0, pulse_len) pwm.setPWM(1, 0, pulse_len) root = Tk() root.wm_title(‘Servo Control’) app = App(root) root.geometry(“200×50+0+0”) root.mainloop() |
Discussion
The first line after the import creates a new instance of PWM using the I2C address specified as its argument—in this case, 0 × 40. The module has solder pad connections that allow you to change the I2C address if this conflicts with another I2C device you are using, or you want to use more than one of these modules.
The next line sets the PWM frequency to 50 Hz, which will provide an update pulse every 20 milliseconds.
The line that actually sets the PWM for a particular channel is:
pwm.setPWM(0, 0, pulse_len) |
The first argument is the PWM channel whose duty cycle is to be changed. Each cycle of PWM is divided into 4,096 ticks, and the second argument is the tick at which the pulse should start. This will always be 0. The third argument is the tick at which the pulse should end. The constants of 500.0 and 110 in the following line were tweaked with a little trial and error to provide a standard servo with as close to 180 degrees of movement as possible:
pulse_len = int(float(angle) * 500.0 / 180.0) + 110 |
When selecting a power supply for this module, remember that a standard remote control servo can easily draw 400 mA 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
To control a single servo without using a module, see Recipe 10.1. To control a number of servos at the same time using an Arduino, see Recipe 14.9.
See the Adafruit documentation for its Raspberry Pi library.
For more information on using a breadboard and jumper wires with the Raspberry Pi, see Recipe 8.10.
Table A-3. Prototyping equipment | |
Description | Suppliers |
M-M jumper wires | SparkFun: PRT-08431, Adafruit: 759 |
M-F jumper wires | SparkFun: PRT-09140, Adafruit: 825 |
F-F jumper wires | SparkFun: PRT-08430, Adafruit: 794 |
Half-sized breadboard | SparkFun: PRT-09567 Adafruit: 64 |
Pi Cobbler | Adafruit: 1105 |
Table A-8. Modules | |
Raspberry Pi camera module | Adafruit: 1367, MCM: 28-17733, CPC: SC13023 |
Arduino Uno | SparkFun: DEV-11021, Adafruit: 50, CPC: A000066 |
Level converter, four-way | SparkFun: BOB-11978, Adafruit: 757 |
Level converter eight-way | Adafruit: 395 |
LiPo boost converter/charger | SparkFun: PRT-11231 |
PowerSwitch tail | Adafruit: 268 |
16-channel servo controller | Adafruit: 815 |
Motor driver 1A dual | SparkFun: ROB-09457 |
RaspiRobot board | Sparkfun: KIT-11561, raspirobot.com |
PiFace digital interface board | MCM: 83-14472, CPC: SC12827 |
Humble Pi | MCM: 83-14637, CPC: SC12871 |
Pi Plate | Adafruit: 801 |
Gertboard | MCM: 83-14460, CPC: SC12828 |
Breakout board with paddle terminals | MCM: 83-14876, CPC: SC12885 |
PIR motion detector | Adafruit: 189 |
Venus GPS module | SparkFun: GPS-11058 |
Methane sensor | SparkFun: SEN-09404 |
Gas sensor breakout board | SparkFun: BOB-08891 |
ADXL335 triple-axis accelerometer | Adafruit: 163 |
4×7-segment LED with I2C backpack | Adafruit: 878 |
Bicolor LED square-pixel matrix with I2C backpack | Adafruit: 902 |
PiLite interface board | Ciseco, CPC: SC13018 |
aLaMode interface board | Makershed: MKWY1, Seeedstudio: ARD10251P |
Freetronics Arduino LCD shield | www.freetronics.com |
RTC module | Adafruit: 264 |
16 x 2 HD44780 compatible LCD module | SparkFun: LCD-00255, Adafruit: 181 |
Table A-9. Miscellaneous | |
1200mAh LiPo battery | Adafruit: 258 |
5V relay | SparkFun: COM-00100 |
5V panel meter | SparkFun: TOL-10285 |
Servo motor | SparkFun: ROB-09065, Adafruit: 1449 |
5V 1A power supply | Adafruit: 276 |
Low power 6V DC motor | Adafruit: 711 |
0.1 inch header pins | SparkFun: PRT-00116, Adafruit: 392 |
5 V 5-pin unipolar stepper motor | Adafruit: 858 |
12 V, 4-pin bipolar stepper motor | Adafruit: 324 |
Magician chassis with gearmotors | SparkFun: ROB-10825 |
Tactile push switch | SparkFun: COM-00097, Adafruit: 504 |
Miniature slide switch | SparkFun: COM-09609, Adafruit: 805 |
Rotary encoder | Adafruit: 377 |
4×3 keypad | SparkFun: COM-08653 |
Piezo buzzer | SparkFun: COM-07950, Adafruit: 160 |