I have this MG90S small servo motor. It is supposed to go from 0° to 180°.
Because of their low cost, they have a short range which is less than 180°. Some go to 135°, 100° or 150°.
PWM signal required by servo to move.
Frequency = 50Hz
Time Period = 0.02 Second or 20 mili second
Pulse width range: 500us to 2500us
Properties of pulse width
At 500us pulse width the servo position will be 0°
At 2500us pulse width the servo position will be 180°
It is a good habit to check the servo controls before putting it in a project and make the adjustments in code or in hardware.
Hardware Connections
Raspberry Pi Pico | Servo Motor |
---|---|
GND | GND (Brown color wire) |
Vsys | VCC (Red color wire) |
GP9 | Signal (Orange color wire) |
Most small and micro Servo operate from 5V to 6V.
If a servo is designed to operate at 3.3V always check it’s datasheet carefully.
Calculations
Raspberry pi pico has a 16 bit PWM controller.
This means we set its frequency to 50Hz bypwm.freq(50)
This means that one oscillation has 65535 steps
65535 steps = 20 ms
First we convert angles to pulse width time
pulse width = angle/90 + 0.5
then we convert pulse width to step count
steps count = ( 65535 * pulse width ) / 20
Code
import machine
import utime
Led_pin = 25
LED = machine.Pin(Led_pin, machine.Pin.OUT)
# Configure the GPIO pin for PWM
pwm_pin = machine.Pin(9)
pwm = machine.PWM(pwm_pin)
# Set the PWM frequency to 50 kHz
pwm.freq(50)
# Debug Message Print
debug = 0
time_delay = 1/10
increment_step = 100
decrement_step = -200
'''
# Function: deg_to_time
# Parameters: deg : degree (0 - 180)
# Description: This function takes the degree and translates them
to Pulse Width time.
For a servo motor we have to use a pulse width of 500us to 2500us
'''
def deg_to_time(deg):
temp = ((deg/90)+0.5)
if debug:print("deg ",deg," to timems: ",temp)
return temp
'''
# Function: timems_to_duty
# Parameters: timems : pulse width time in milli second
# Description: This function takes pulse width duration of 500us to 2500us.
and generates a duty cycle value.
'''
def timems_to_duty(timems):
temp = 20/timems
temp1 = 65535/temp
if debug:print("timems to duty: ",temp1)
return temp1
'''
# Function: set_pwm
# Parameters: duty : duty cycle value (0 - 65535)
# Description: This function takes a duty cycle value and set it for the PWM.
'''
def set_pwm(duty):
pwm.duty_u16(int(duty))
if debug:print("duty cycle: ",duty)
def angle_to_pwm(angle):
set_pwm(int(timems_to_duty(deg_to_time(angle))))
while(1):
# sweep from 0 to 180
for _ in range(0,180,1):
angle_to_pwm(_)
utime.sleep(time_delay)
# sweep from 180 to 0
for _ in range(180,0,-1):
angle_to_pwm(_)
utime.sleep(time_delay)
Leave a Reply