Introduction
Servo is a type of gear motor that can only rotate 180 degrees. It is controlled by sending electrical pulses from your board. These pulses tell the servo what position it should move to.
A servo has three wires: the brown wire is GND, the red one is VCC, and the orange one is the signal line.
Newly Added Components
Principle
Servo
A servo is generally composed of the following parts: case, shaft, gear system, potentiometer, DC motor, and embedded board.
It works like this: The microcontroller sends out PWM signals to the servo, and then the embedded board in the servo receives the signals through the signal pin and controls the motor inside to turn. As a result, the motor drives the gear system and then motivates the shaft after deceleration. The shaft and potentiometer of the servo are connected together. When the shaft rotates, it drives the potentiometer, so the potentiometer outputs a voltage signal to the embedded board. Then the board determines the direction and speed of rotation based on the current position, so it can stop exactly at the right position as defined and hold there.
The angle is determined by the duration of a pulse that is applied to the control wire. This is called Pulse width Modulation. The servo expects to see a pulse every 20 ms. The length of the pulse will determine how far the motor turns. For example, a 1.5ms pulse will make the motor turn to the 90 degree position (neutral position).
When a pulse is sent to a servo that is less than 1.5 ms, the servo rotates to a position and holds its output shaft some number of degrees counterclockwise from the neutral point. When the pulse is wider than 1.5 ms the opposite occurs. The minimal width and the maximum width of pulse that will command the servo to turn to a valid position are functions of each servo. Generally the minimum pulse will be about 0.5 ms wide and the maximum pulse will be 2.5 ms wide.
Schematic Diagram
Build the Circuit
Note: Connect the brown to GND, Red to VCC, Orange to pin12 of the control board.
- For C Language Users
Command
1.Go to the folder of the code.
cd /home/pi/electronic-kit/for-raspberry-pi/c/Lesson_16_Servo
2. Compile the code.
gcc 16_Servo.c -lwiringPi
3. Run the executable file.
sudo ./a.out
After the program is executed, the servo will rotate from 0 degrees to 180 degrees, and then from 180 degrees to 0 degrees, circularly.
Code
1.#include <wiringPi.h>
2.#include <softPwm.h>
3.#include <stdio.h>
4.
5.#define servoPin 1
6.long map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
7. return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
8.}
9.void servoWrite(int pin, int angle){ //Specif a certain rotation angle (0-180) for the servo
10. if(angle < 0)
11. angle = 0;
12. if(angle > 180)
13. angle = 180;
14. softPwmWrite(pin,map(angle,0,180,5,25));
15.}
16.
17.int main(void)
18.{
19. int i;
20.
21. if(wiringPiSetup() == -1){ //when initialize wiring faiservo,print message to screen
22. printf("setup wiringPi failed !");
23. return 1;
24. }
25. softPwmCreate(servoPin, 0, 200); //initialize PMW pin of servo
26. while(1){
27. for(i=0;i<181;i++){
28. servoWrite(servoPin,i);
29. delay(1);
30. }
31. delay(500);
32. for(i=181;i>-1;i--){
33. servoWrite(servoPin,i);
34. delay(1);
35. }
36. delay(500);
37. }
38. return 0;
39.}
Code Explanation
6. long map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
7. return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
8. }
Create a map() function to map value in the following code.
9. void servoWrite(int pin, int angle){ //Specif a certain rotation angle (0-180) for the servo
10. if(angle < 0)
11. angle = 0;
12. if(angle > 180)
13. angle = 180;
14. softPwmWrite(pin,map(angle,0,180,5,25));
15. }
Define a function to limit the angle of the servo to 0 to 180 in order to set the angle of servo.
softPwmWrite(pin,map(angle,0,180,5,25));
This function can change the duty cycle of the PWM pin.
To make the servo rotate to 0 ~ 180 °, the pulse width should change within the range of 0.5ms ~ 2.5ms when the period is 20ms; in the function, softPwmCreate(), we have set that the period is 200x100us=20ms, thus we need to map 0 ~ 180 to 5x100us ~ 25x100us.
25.softPwmCreate(servoPin, 0, 200);
The function is to use softwares to create a PWM pin, servoPin, then the initial pulse widths of them are set to 0, and the period of PWM is 200x100us.
27. for(i=0;i<181;i++){
28. servoWrite(servoPin,i);
29. delay(1);
30. }
In a for loop, we want servo to rotate from 0 degrees to 180 degrees.
32. for(i=181;i>-1;i–){
33. servoWrite(servoPin,i);
34. delay(1);
35. }
In a for loop, we want servo to rotate from 180 degrees to 0 degrees.
- For Python Language Users
Command
1.Go to the folder of the code.
cd /home/pi/electronic-kit/for-raspberry-pi/python
2. Run the code.
sudo python3 16_Servo.py
After the program is executed, the servo will rotate from 0 degrees to 180 degrees, and then from 180 degrees to 0 degrees, circularly.
Code
1.import RPi.GPIO as GPIO
2.import time
3.
4.servoPin = 12
5.
6.def map( value, fromLow, fromHigh, toLow, toHigh):
7. return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow
8.
9.def setup():
10. global p
11. GPIO.setmode(GPIO.BOARD)
12. GPIO.setup(servoPin, GPIO.OUT)
13. GPIO.output(servoPin, GPIO.LOW)
14.
15. p = GPIO.PWM(servoPin, 50)
16. p.start(0)
17.
18.def servoWrite(angle): # make the servo rotate to specific angle (0-180 degrees)
19. if(angle<0):
20. angle = 0
21. elif(angle > 180):
22. angle = 180
23. p.ChangeDutyCycle(map(angle,0,180,2.5,12.5))
24.
25.def loop():
26. while True:
27. for i in range(0, 181, 1):
28. servoWrite(i)
29. time.sleep(0.001)
30. time.sleep(0.5)
31. for i in range(180, -1, -1):
32. servoWrite(i)
33. time.sleep(0.001)
34. time.sleep(0.5)
35.
36.def destroy():
37. p.stop()
38. GPIO.cleanup()
39.
40.if __name__ == '__main__': #Program start from here
41. setup()
42. try:
43. loop()
44. except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.
45. destroy()
Code Explanation
6. def map( value, fromLow, fromHigh, toLow, toHigh):
7. return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow
Create a map() function to map value in the following code.
15. p = GPIO.PWM(servoPin, 50)
16. p.start(0)
Set the servoPin to PWM pin, then the frequency to 50hz, and the period to 20ms.
p.start(0): Run the PWM function,and set the initial value to 0.
18. def servoWrite(angle):
19. if(angle<0):
20. angle = 0
21. elif(angle > 180):
22. angle = 180
23. p.ChangeDutyCycle(map(angle,0,180,2.5,12.5))#map the angle to duty cycle and output it
Create a function, servoWrite() to write angle that ranges from 0 to 180 into the servo.
p.ChangeDutyCycle(map(angle,0,180,2.5,12.5))
This function can change the duty cycle of the PWM.
To render a range 0 ~ 180° to the servo, the pulse width of the servo is set to 0.5ms-2.5ms.
In the previous codes, the period of PWM was set to 20ms, thus the duty cycle of PWM is (0.5/20)%-(2.5/20)%, and the range 0 ~ 180 is mapped to 2.5 ~ 12.5.
24. for i in range(0, 181, 1): #make servo rotate from 0 to 180 deg
25. servoWrite(i) # Write to servo
26. time.sleep(0.001)
In a for loop, we want servo to rotate from 0 degrees to 180 degrees.
27.for i in range(180, -1, -1): #make servo rotate from 180 to 0 deg
28.servoWrite(i)
29.time.sleep(0.001)
In a for loop, we want servo to rotate from 180 degrees to 0 degrees.