In this tutorial, we will learn how to interface and control SG-90 servo motor with Raspberry Pi Pico. Firstly, we will see an introduction of the servo motor. After that, we will look at how to interface it with Raspberry Pi Pico and use PWM signals to control its movement.
You may like to read dc motor and stepper motor interfacing with Raspberry Pi Pico:
- 28BYJ-48 Stepper Motor with Raspberry Pi Pico using MicroPython
- Control DC Motor using L298N Driver with Raspberry Pi Pico and MicroPython
Prerequisites
In order to start, make sure you have performed the following procedures already:
- Downloaded and installed the latest version of Python 3 on your PC.
- Downloaded and installed the latest version of Thonny IDE.
- Set up MicroPython in Raspberry Pi Pico.
If you want to know how to perform the above steps, you can follow this step by step guide:
If you are using uPyCraft IDE, you can check this getting started guide:
SG-90 Servo Motor
SG90 is a low cost and high output power servo motor. It can rotate up to 180 degrees and each step can be of maximum 90 degrees. Moreover, it is small enough that it can easily fit into your robotics ARM or obstacle avoidance robotics projects. On top of that, it requires only one output pulse signal to control its movement.
The following figure shows the pinout diagram of SG90 servo motor. It consists of three pins only such as PWM, ground and Vcc pin. Brown, orange and red wires are GND, Vcc and PWM pins respectively. Details and functionality of each pin is listed in the next section.
Pin Configuration Details
Vcc and ground, as their name suggests, are the power supply pins which are used to power servo motor. Only 5 volts of power signal is required to power this motor. Mostly microcontrollers or development boards have onboard 5 volts supply which we can use to power SG90 servos.
This table briefly describes all three pins:
Wire of motor | Possible colors of each wire |
---|---|
Vcc pin | Red |
GND pin | Black, or brown |
Control Signal / PWM pin | Yellow, orange, or white |
PWM Introduction
PWM means pulse width modulation. It is a type of signal which is obtained from a microcontroller in our case the Raspberry Pi Pico board. The output signal is a square waveform which at a particular instance is either high or low. If we are using a 3.3V power supply then the PWM signal would be either high which is 3.3V or low which is 0V. The ‘on time is the duration till which the signal stays high and the ‘off time’ is the duration till which it stays low. In order to better understand the concepts of PWM in our board we need to know about the following two terms which are closely associated with the digital signal:
What is Duty Cycle?
Duty cycle is the percentage of time in which the PWM signal is ‘on time’ meaning it remains High. For example if the signal is always OFF it is 0% duty cycle and if it is always ON it is 100% duty signal. The special feature about this is that the user can control the ‘on time’ by controlling the duty cycle. The formula for duty cycle is shown in following expression:
Duty Cycle = ON time of signal / Time period of signal
Frequency
The frequency of a PWM signal is the number of cycles per second and it defines how quickly a PWM signal completes one cycle (Period). That means the Period of a PWM signal is the sum of the ON and OFF time of a PWM signal. For example, if the time period of a signal is 20ms, its frequency will be 50Hz where Hz is the unit of frequency. This formula is used to calculate the frequency:
Frequency = 1/Time Period
Time Period = ON time + OFF time
PWM Pins Raspberry Pi Pico
Raspberry Pi Pico microcontroller contains 8 PWM blocks and each PWM block provides two PWM signals. That means each slice can drive up to two PWM signals. Hence, there is a total of 16 PWM signal output available on Raspberry Pi Pico. All GPIO pins can be configured to get any PWM signal output.
GPIO | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
PWM Channel | 0A | 0B | 1A | 1B | 2A | 2B | 3A | 3B | 4A | 4B | 5A | 5B | 6A | 6B | 7A | 7B | 0A | 0B | 1A | 1B | 2A | 2B | 3A | 3B | 4A | 4B | 5A | 5B | 6A | 6B |
How to Control SG-90 in MicroPython for Raspberry Pi Pico
We are going to follow the steps stated below in order to configure PWM in our Raspberry Pi Pico.
- Firstly, we have to choose the PWM pin.
- Next, we set a particular frequency for our digital signal. For servo motor we use 50Hz frequency.
- Raspberry Pi Pico has 12 bit resolution but in MicroPython it is scaled to 16 bits. Hence the duty cycle is set from 0-65535 which corresponds to 0-100%. However, for SG-90 servo motor we will pass values between 1000-9000 microseconds which corresponds to 0-180 degree position movement of the arm inside the PWM.duty_u16() method.
Interfacing Raspberry Pi Pico and SG-90 servo motor
The following schematic diagram shows the connections between the two devices.
For the servo motor, we have connected the control signal pin with GP1. You can use any suitable PWM pin of your board. The VCC and GND pins are in common with the Raspberry Pi Pico 5V and GND pins. You can however, use an external 5V power supply to power the servo motor as well.
MicroPython Control Servo Motor Script
The following MicroPython sketch moves the servo motor arm from 0 to 180 then from 180 to 0 degrees continuously.
from time import sleep
from machine import Pin, PWM
pwm = PWM(Pin(1))
pwm.freq(50)
while True:
for position in range(1000,9000,50):
pwm.duty_u16(position)
sleep(0.01)
for position in range(9000,1000,-50):
pwm.duty_u16(position)
sleep(0.01)
How Code Works?
Now I will explain the steps in which the program code is working.
Importing PWM and Pin Classes
Firstly, in order to interact with the PWM module, we will import the PWM class from the machine module of MicroPython. In order to create a PWM pin to read input/output GPIOs, we will also import the PWM class. We will import the machine module that contains classes to interact with the GPIOs. The sleep module is also imported for use in delays.
from time import sleep
from machine import Pin, PWM
Create PWM Pin Object
Next we create a PWM pin object called ‘pwm’ to pass the pwm pin as a parameter. The parameter shows where the pin is connected in our case GP1.
pwm = PWM(Pin(1))
Then we will set up the frequency of the PWM signal.
pwm.freq(50)
Generate Variable Duty Cycle PWM
For SG-90 servo motor we will pass values between 1000-9000 microseconds which corresponds to 0-180 degree position movement of the arm inside the pwm.duty_u16() method
Inside the infinite loop, we will generate two ‘for’ loops. The first loop which increases the position by 50 in each loop and moves the servo’s arm from 0 to 180 degrees. The second loop which decreases the position by 50 in each loop and moves the servo’s arm from 180 to 0 degrees. This is achieved by the range() function which is used to initiate the start, stop, and step. The range() function has three parameters and written as follows: range(start, stop, step).
- Start: This shows the starting value for the duty cycle. In our case, we start with position 1000 (corresponds to 0 degree) in the first loop and position 9000 (corresponds to 180 degree) in the second for loop.
- Stop: This shows the stopping value for the duty cycle range. In our case, we stop at position 9000 (corresponds to 180 degree) in the first loop and position 1000 (corresponds to 0 degree) in the second for loop.
- Step: This shows the incrementation value. We are incrementing by 50 in the first loop and -50 in the second loop. This will determine the speed of the rotation.
while True:
for position in range(1000,9000,50):
pwm.duty_u16(position)
sleep(0.01)
for position in range(9000,1000,-50):
pwm.duty_u16(position)
sleep(0.01)
During each iteration of for loop, we set the pwm duty cycle to the current position value:
pwm.duty_u16(position)
Demonstration
To see the demo of above code, copy this code to Thonny IDE. Also, attach the servo motor with Raspberry Pi Pico as shown in the connection diagram above. You will see the servo motor’s arm rotating from 0-180 and 180-0 degrees continuously as shown in the video below:
You may also like to read other Raspberry Pi Pico tutorials:
- HC-05 Bluetooth Interfacing with Raspberry Pi Pico – Control Outputs
- Control DC Motor using L298N Driver with Raspberry Pi Pico and MicroPython
- DS18B20 Temperature Sensor with Raspberry Pi Pico using MicroPython
- DHT11 DHT22 with Raspberry Pi Pico using MicroPython
- HC-SR04 Ultrasonic Sensor with Raspberry Pi Pico using MicroPython
- I2C LCD Interfacing with Raspberry Pi Pico Display Text and Custom Characters
- BME280 with Raspberry Pi Pico using MicroPython
Related servo motor tutorials and projects:
- Interface MG995 Servo Motor with Arduino – Example Code
- CCPM Servo Consistency Master/Servo Motor Tester
- SG-90 Servo Motor Interfacing with TM4C123 Launchpad
- ESP32 Web Server Control Servo motor with Arduino IDE
- Web Controlled Servo Motor using Arduino and esp8266
- servo motor interfacing with 8051 using keil compiler
- Joystick based servo motor control using arduino
I do not understand why “SG-90 servo motor we will pass values between 1000-9000 microseconds which corresponds to 0-180 degree position movement”. In the SG-90 datasheet, if 1500us, the position is 90deg, if less than 1500us, then it will be CW. If more than 1500us, it will be CCW. It is different from yours 1000us~9000us. Why? Did I understand incorrectly?