Published 2026-04-05
This guide provides a step‑by‑step method to control a standardservomotor with an ESP32 board using Python. Whether you are building a robotic arm, a pan‑tilt camera mount, or a simple moving prop, you will learn the exact wiring, the Python code, and the calibration steps to make yourservomove precisely. All examples are based on common, real‑world situations so you can immediately apply them to your own projects.
One ESP32 development board (any common variant)
One standard 5Vservomotor (e.g., SG90 or MG995 type)
External 5V power supply (if using a high‑torque servo)
Jumper wires (female‑to‑female)
A computer with MicroPython firmware installed on the ESP32
> Important: Never power a servo directly from the ESP32’s 3.3V pin. Most servos require 5V and can draw more current than the board can safely provide. Use a separate 5V power source for the servo, and connect only the signal wire to the ESP32.
Imagine you are building a simple robotic claw that opens and closes. You have a common MG995 servo. Connect it as follows:
Critical point: The ground of the external power supplymustbe connected to the ESP32 GND. Without this common ground, the signal will be unstable and the servo will jitter or not move.
The ESP32 controls a servo by generating a 50 Hz PWM signal (period = 20 ms). The servo’s position is determined by the pulse width: 0.5 ms for 0°,1.5 ms for 90°, and 2.5 ms for 180°.
Below is a complete, tested MicroPython script. Save it asmain.pyon your ESP32.
from machine import Pin, PWM import time # Use GPIO15 – you can change to any pin that supports PWM SERVO_PIN = 15 # Standard servo frequency: 50 Hz PWM_FREQ = 50 # Duty cycle values for 0°, 90°, 180° (calculated for 50 Hz) # For a 16‑bit PWM resolution (0–65535): # Duty = (pulse_width_ms / 20ms)65535 # 0.5 ms -> 1638 (0°) # 1.5 ms -> 4915 (90°) # 2.5 ms -> 8192 (180°) DUTY_0 = 1638 DUTY_90 = 4915 DUTY_180 = 8192 # Initialize PWM on the servo pin servo = PWM(Pin(SERVO_PIN), freq=PWM_FREQ, duty_u16=DUTY_90) # start at 90° def set_angle(angle): """ Set servo angle (0° to 180°). Linearly maps angle to duty cycle. """ # Clamp angle to valid range angle = max(0, min(180, angle)) # Linear mapping: duty = DUTY_0 + (angle/180)(DUTY_180 - DUTY_0) duty = int(DUTY_0 + (angle / 180) * (DUTY_180 - DUTY_0)) servo.duty_u16(duty) # Example: sweep back and forth while True: for angle in range(0, 181, 10): set_angle(angle) time.sleep_ms(50) for angle in range(180, -1, -10): set_angle(angle) time.sleep_ms(50)
1. Flash MicroPython firmware to your ESP32 (if not already done).
2. Connect the servo as described.
3. Copy the script to the board using a tool likempremoteor Thonny.
4. Run the script. The servo will sweep from 0° to 180° and back repeatedly.
Different servo models have slightly different pulse width ranges. For example, a cheap SG90 might work with 0.5 ms to 2.4 ms, while a high‑torque MG996R uses 0.6 ms to 2.4 ms. The common 0.5–2.5 ms range works for most, but you should always calibrate.
Calibration method(a real‑world case from a robotic arm project):
Set the duty cycle to 1638 and note the actual angle.
If the servo does not reach 0°, increase the duty slightly (e.g., 1700) until it stops moving.
Do the same for 180° by decreasing from 8192.
Use your measured DUTY_MIN and DUTY_MAX in theset_angle()function.
A servo is controlled by pulse width, not by the percentage of duty cycle.The frequency must be exactly 50 Hz (period 20 ms). Changing the pulse width between 0.5 ms and 2.5 ms rotates the servo from 0° to 180°. In MicroPython’sduty_u16()method, the mapping from pulse width to duty value depends on the PWM resolution (always 16‑bit on ESP32). Use the formulas provided or the linear mapping function.
1. Always start with a simple sweep test– it confirms wiring and basic PWM operation.
2. Use a logic analyzer or an oscilloscopeto verify the pulse width if the servo behaves oddly.
3. For battery‑powered projects, add a large capacitor (470 µF or more) across the servo power terminals to absorb voltage drops.
4. When your project requires multiple servos, control each on a separate GPIO pin, but ensure the total current does not exceed your power supply’s rating.
Controlling a servo with ESP32 and Python is straightforward: connect the signal wire to any PWM‑capable GPIO, provide separate 5V power with a common ground, generate a 50 Hz PWM signal, and adjust the duty cycle to set the pulse width between 0.5 ms and 2.5 ms. The provided code works out of the box for most standard servos. If the movement range is incorrect, calibrate the minimum and maximum duty values for your specific servo. Now you are ready to integrate precise motion into your own ESP32‑based projects.
Update Time:2026-04-05
Contact Kpower's product specialist to recommend suitable motor or gearbox for your product.