Servo Motor with Raspberry Pi Pico using MicroPython

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.

Servo Motor with Raspberry Pi Pico using MicroPython

You may like to read dc motor and stepper motor interfacing with Raspberry Pi Pico:

Prerequisites

In order to start, make sure you have performed the following procedures already:

  1. Downloaded and installed the latest version of Python 3 on your PC.
  2. Downloaded and installed the latest version of Thonny IDE.
  3. 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.

Servo motor S0009

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.

SG90 servo motor pinout

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 motorPossible colors of each wire
Vcc pinRed
GND pinBlack, 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

PWM signal
Different Duty Cycles PWM 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.

Raspberry Pi Pico pinout diagram
GPIO01234567891011121314151617181920212223242526272829
PWM Channel0A0B1A1B2A2B3A3B4A4B5A5B6A6B7A7B0A0B1A1B2A2B3A3B4A4B5A5B6A6B

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.

  1. Firstly, we have to choose the PWM pin.
  2. Next, we set a particular frequency for our digital signal. For servo motor we use 50Hz frequency.
  3. 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.

Raspberry Pi Pico with servo motor connection diagram
Raspberry Pi Pico with servo motor connection diagram

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.

Raspberry Pi Pico with servo motor

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:

Related servo motor tutorials and projects:

1 thought on “Servo Motor with Raspberry Pi Pico using MicroPython”

  1. 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?

    Reply

Leave a Comment