Learn
Controlling an SG90 Micro Servo with a Raspberry Pi 4B
Wire an SG90 micro servo to a Raspberry Pi 4B GPIO pin and sweep it through a range of angles with real PWM in Python — no hardware required.
Try this directly in the free Raspberry Pi 4B simulator — no hardware or signup required. New to the GPIO header? Start with the interactive pinout guide.
What you’ll need
- Raspberry Pi 4B
- SG90 Micro Servo
Step by step
- Drag Raspberry Pi 4B onto the Canvas.
- Drag the SG90 Micro Servo onto the Canvas (it won't mount into a breadboard — that's expected, real servos connect via loose wires, not legs).
- Hover over the servo's 3 pins to confirm their labels: Signal, V+, GND.
- Wire it up: Servo V+ → Pi's 5V pin. Servo GND → Pi's GND pin. Servo Signal → a GPIO pin (e.g. pin 37).
- Go to the Code tab and write a test script that sweeps through a few angles:
import RPi.GPIO as GPIOimport asyncio signalPin = 37 GPIO.setmode(GPIO.BOARD)GPIO.setup(signalPin, GPIO.OUT) pwm = GPIO.PWM(signalPin, 50) # 50Hz, standard for servospwm.start(0) def angle_to_duty(angle): # Converts a 0-180 degree angle into the duty cycle percentage the servo expects return 2.5 + (angle / 180) * 10 # roughly 2.5% (0°) to 12.5% (180°) async def move_to(angle): print(f"Moving to {angle} degrees") pwm.ChangeDutyCycle(angle_to_duty(angle)) await asyncio.sleep(1) await move_to(0)await move_to(90)await move_to(180)await move_to(90) pwm.stop()GPIO.cleanup()- Click Start. You should see the servo horn visually rotate: starting near one end, sweeping to center, continuing to the other end, then returning to center — each position held for about a second before moving to the next.
What you'll see in the Console:
Moving to 0 degreesMoving to 90 degreesMoving to 180 degreesMoving to 90 degreesEach line should print right as the servo visually starts moving toward that position — that's your confirmation the script's intent and the servo's actual motion are in sync, not just coincidentally similar.
One extra check worth doing: if the print appears but the servo doesn't move (or moves to a clearly wrong position), that tells you the script → PWM channel path is working correctly, but the PWM channel → visual rotation path is where the problem actually is. Worth mentioning that distinction if you ever need to report a bug, since it narrows down which half of the pipeline to look at first.
What “working correctly” looks like
- The servo horn visually rotates: starting near one end, sweeping to center, continuing to the other end, then returning to center — each position held for about a second before moving to the next.
- Each Console line (“Moving to N degrees”) prints right as the servo visually starts moving toward that position, not noticeably before or after.
More component tutorials are in Learn.