Skip to content

How to Control a Servo Motor with Raspberry Pi Pico using MicroPython: Complete Guide

Neopixel LED

Table of Contents

Abstract

Servo motors are essential components in robotics, automation, and DIY electronics projects due to their precise angular control and compact size. In this tutorial, you will learn how to interface a standard SG90 servo motor with a Raspberry Pi Pico microcontroller using MicroPython. By the end, you will be able to control servo position from 0° to 180°, understand PWM signal fundamentals, and integrate servo control into your own embedded projects.

🧭 Pre-Request

  • OS : Windows / Linux / Mac / Chrome
  • Thonny IDE.
  • MicroPython firmware in Raspberry Pi Pico / Pico 2 / Pico W / Pico 2W.

Hardware Required

🛠️
Get the right hardware kit
Raspberry Pi Pico, Arduino, sensors, and IoT maker essential Kits—perfectly matched for your learning.
Explore Hardware →
  • Raspberry Pi Pico / Pico 2 / Pico W / Pico 2W.
  • Servo Motor (SG90 or MG90).
  • BreadBoard.
  • Micro USB Cable.
  • Connecting wires.
  • 5V DC power supply (optional)
Components Purchase Link
Raspberry Pi Pico link
Raspberry Pi Pico 2 link
Raspberry Pi Pico W link
Raspberry Pi Pico 2W link
Servo Motor SG90 : MG90
BreadBoard large : small
Connecting Wires link
Micro USB Cable link

Don't own a hardware 😢

No worries,

Still you can learn using simulation. check out simulation part 😃.


⚡ Understanding Servo Motors & PWM Control

The SG90 is a popular hobby servo motor controlled via Pulse Width Modulation (PWM). Unlike standard DC motors, servos rotate to precise angular positions (typically 0°–180°) based on the width of an incoming PWM pulse.

🔹 How PWM Controls Servo Position

Pulse Width Servo Angle Duty Cycle (50Hz) RP2040 duty_u16 Value
~0.5 ms ~2.5% ~1638
~1.45 ms 90° ~7.25% ~4751
~2.4 ms 180° ~12% ~7864

PWM Frequency

Servo motors require a 50Hz PWM signal (20ms period). The Raspberry Pi Pico's hardware PWM peripheral can generate this signal reliably on any GPIO pin.

Power Considerations

Small servos like the SG90 can be powered from the Pico's 5V (VBUS) pin. However, for multiple servos or high-torque models, use an external 5V supply and connect its GND to the Pico's GND to avoid brownouts or regulator damage.


🧷 Connection / Wiring Guide (Raspberry Pi Pico to SG90 Servo)

🔥 Pin Mapping Table

Servo Wire Color Raspberry Pi Pico Pin Description
GND Brown GND Common ground
VCC Red 5V (VBUS, Pin 40) or External 5V Power Supply Power supply
Signal Orange/Yellow GP16 or any PWM-capable GPIO PWM control signal

PWM-Capable Pins

All GPIO pins on the Raspberry Pi Pico support hardware PWM output. You can use any pin — just update the pin number in your code accordingly.

Circuit Diagram

fig-Connection Diagram

📂 Code

from machine import Pin, PWM
from time import sleep

# Initialize PWM on GPIO 16
servo_pin = Pin(16)
servo = PWM(servo_pin)

########## NOTE #################
# Pulse range varies with manufacturer.
# Check data sheet for the same

# PWM Configuration for SG90 Servo
FREQUENCY = 50  # 50Hz standard for servos
MIN_DUTY = 1638  # ~0.5ms pulse → 0°
MAX_DUTY = 7864  # ~2.4ms pulse → 180°

servo.freq(FREQUENCY)

def servo_angle(angle):
    """Map angle (0-180) to duty cycle (1638-7864)"""
    angle = max(0, min(180, angle))  # Clamp to valid range
    duty = MIN_DUTY + (angle / 180) * (MAX_DUTY - MIN_DUTY)
    servo.duty_u16(int(duty))

try:
    while True:
        # Sweep: 0° → 90° → 180° → 90° → 0°
        for angle in [0, 90, 180, 90, 0]:
            servo_angle(angle)
            sleep(1)

except KeyboardInterrupt:
    print("\nStopping servo...")
    servo.deinit()  # Disable PWM output

Code Explanation

👉 Imports

from machine import Pin, PWM
from time import sleep
  • time module for creating delay.

👉 Initialize Servo Motor.

servo_pin = Pin(16) # Any gpio pin with PWM feature can be used.
servo = PWM(servo_pin)
  • GPIO 16 is connected to Signal of Servo Motor.

👉 PWM Configuration.

# PWM Configuration for SG90 Servo
FREQUENCY = 50  # 50Hz standard for servos
MIN_DUTY = 1638  # ~0.5ms pulse → 0°
MAX_DUTY = 7864  # ~2.4ms pulse → 180°

servo.freq(FREQUENCY)
  • Sets 50Hz frequency (20ms period), standard for hobby servos
  • Pico has 16-bit PWM resolution (0–65535)
  • Values 1638 and 7864 correspond to ~0.5ms and ~2.4ms pulse widths respectively.

👉 Setting the color.

def servo_angle(angle):
    """Map angle (0-180) to duty cycle (1638-7864)"""
    angle = max(0, min(180, angle))  # Clamp to valid range
    duty = MIN_DUTY + (angle / 180) * (MAX_DUTY - MIN_DUTY)
    servo.duty_u16(int(duty))
  • Function to calculate duty_u16 value for the specified angle between 0 to 180 deg

👉 Sweep through the angle.

    while True:
        # Sweep: 0° → 90° → 180° → 90° → 0°
        for angle in [0, 90, 180, 90, 0]:
            servo_angle(angle)
            sleep(1)
Continuously sweep through the set angle as per the list. ([0, 90, 180, 90, 0])

Simulation

Not able to view the simulation

  • Desktop or Laptop : Reload this page ( Ctrl+R )
  • Mobile : Use Landscape Mode and reload the page

🛠️
Get the right hardware kit
Raspberry Pi Pico, Arduino, sensors, and IoT maker essential Kits—perfectly matched for your learning.
Explore Hardware →
  • Pico Iot Spark Kit

  • Pico Iot Explorer Kit


🛑 Troubleshooting (Common Issues & Fixes)

Issue 1: Servo doesn't move or jitters

Causes: - Incorrect PWM frequency (must be 50Hz) - Weak power supply causing voltage drops - Signal wire connected to non-PWM pin (rare on Pico)

Fix:

servo.freq(50)  # Ensure 50Hz
- Use a stable 5V supply for servos drawing >200mA. - Add a 100µF capacitor between servo VCC and GND near the motor.

Issue 2: Servo buzzes at 0° or 180°

Cause: - Pulse width values outside servo's mechanical range.

Fix:

# Adjust these values incrementally
MIN_DUTY = 1600  # Was 1638
MAX_DUTY = 7900  # Was 7864
- Test with smaller angle ranges first (e.g., 10°–170°).

Issue 3: Raspberry Pi Pico resets during servo motion

Cause: - Servo current spike exceeds Pico's regulator capacity (~300mA).

Fix: - Power servo from external 5V supply. - Connect external supply GND to Pico GND (common ground). - Keep signal wire connection intact.


🏁 Conclusion

You have successfully interfaced an SG90 servo motor with a Raspberry Pi Pico using MicroPython 🎉. You now understand:

  • How PWM signals control servo angular position
  • How to calculate duty cycle values for precise motion
  • Best practices for power management and troubleshooting

With this foundation, you can build interactive projects like: - 🤖 Robotic arm controllers - 🚗 RC car steering systems - 📡 Pan-tilt camera mounts - 🎮 Game controller feedback mechanisms

Next Steps

Combine servo control with sensors (ultrasonic, potentiometer) or communication modules (WiFi, Bluetooth) to create smart, responsive embedded systems. Explore the Raspberry Pi Pico MicroPython documentation for advanced PWM features.


Extras

Components details