PWM and Servo Control
Using the GPIO ports provides binary on/off control. Often, more moderate control is required. Dimming LEDs or controlling motor speed are two such examples. One possible way to slow down a motor is to run it on lower voltage (3 volts instead of 5). Lowering the voltage is not possible with the Raspberry Pi (or most microcontrollers) without specialized circuitry. Instead, the Raspberry Pi switches the output on and off very rapidly, making it appear to the motor like the voltage is lower. This technique is called Pulse Width Modulation (PWM).
In addition to motor speed control, PWM can also be used to steer a servo motor. Servos are a special class of motors, which do not (usually) spin continuously, but rather set an output angle (position). They are often used for steering robots or adjusting control surfaces on RC planes.
The Raspberry Pi contains a single hardware PWM/servo driver. The pure hardware PWM from the hardware driver provides a very accurate and clean PWM signal. Support for this driver is limited, currently supported by the semi-outdated Adafruit Occidentalis distribution and the more up to date WiringPi library. As there is only a single PWM channel, only 1 servo can be controlled.
To control more than 1 servo, some timing accuracy can be traded off for more channels. Libraries like RPIO and Servoblaster (what we'll use today) are not a pure hardware solution (they are driven by DMA transfers). Their signal is slightly less clean and might be affected by other programs running on the Raspberry Pi.
Servoblaster
Installing Servoblaster:
1. git clone /github.com/richardghirst/PiBits.git
2. cd PiBits/ServoBlaster/user
3. make
4. sudo make install
5. Verify that servoblaster is installed: ls /dev/servoblaster
Servoblaster is controlled by writing into the /dev/servoblaster file. The content is written as <servo-number>=<servo-position>
. The first field written is the servo number. The following table shows which output pin each servo channel is connected to.
Servo number | GPIO number | Pin in P1 header |
---|---|---|
0 | 4 | P1-7 |
1 | 17 | P1-11 |
2 | 18 | P1-12 |
3 | 21/27 | P1-13 |
4 | 22 | P1-15 |
5 | 23 | P1-16 |
6 | 24 | P1-18 |
7 | 25 | P1-22 |
Source Code
Appendix A: Adafruit Occidentalis PWM Instructions
The steps to set up the PWM driver are as follows (must be run as root, i.e. with sudo):
- Set the frequency in the
/sys/class/rpi-pwm/pwm0/frequency
file. Somewhere in the 1000Hz-5000Hz range is recommended - Turn on the PWM by writing a value of 1 into the
/sys/class/rpi-pwm/pwm0/active
file - Adjust the duty cycle by writing a value between 1-100 in the
/sys/class/rpi-pwm/pwm0/duty
file
PWM Example Code
Servo Control
Controlling a servo is very similar to controlling PWM. The same comments apply to the use of hardware or software servos as for PWM. The biggest difference is that the Raspberry Pi must be specifically put into servo mode (it defaults to pwm mode, so no change is required for pwm). Then, instead of writing to the "duty" file for control, instead the "servo" file is used. The units of the servo file are in steps from 0-32. A setting of 0 will turn the servo to 0 degrees, while a setting of 32 will turn the servo to 180 degrees. The maximum servo value can be changed by modifying the "max_servo" file, but this is not usually necessary.