Understanding SG90 Servo Motors and PWM Control Implementation

Introduction to SG90 Servo Motors

The SG90 is a compact positional servo motor designed for applications requiring precise angular positioning and holding capabilities. Servo mechanisms, derived from the Greek word for "slave," are systems that follow external commands to achieve desired motion parameters including position, velocity, and torque.

There are two main types of servo motors available:

  • Digital Servos: These consist of a motor, reduction gears, and control circuitry. They maintain their position after receiving a single PWM signal.
  • Analog Servos: Traditional servos that require continuous PWM signals to maintain position and control rotation speed.

SG90 Technical Specifications

  • Recommended operating voltage: 5V
  • Rotation range: 0° to 180°
  • Operating weight: 9g
  • Operating speed: 0.12 sec/60° at 4.8V
  • Stall torque: 1.8 kgf·cm at 4.8V

Working Principle

Inside the servo, a reference voltage is established. When a PWM signal from a microcontroller enters through the signal line, it creates a DC bias voltage that compares with the internal reference voltage. The resulting voltage difference drives the motor driver chip, determining rotation direction. As the motor rotates, it turns a potentiometer through reduction gears, nullifying the voltage difference and stopping the motor at the desired position.

Wiring Configuration

The SG90 servo has three wires:

  • Brown (or black): Ground (GND)
  • Red: Power supply (5V)
  • Orange (or yellow): Control signal (connected to microcontroller GPIO)

PWM Control Method

The SG90 is controlled using a PWM signal with a 20ms period. The pulse width varies from 0.5ms to 2.5ms, corresponding to a 0° to 180° rotation range. The relationship between pulse width and angle is linear.

Important note: Servos require time to reach their target position, with larger angular changes requiring more time. If commands are sent too quickly, the servo will respond to the latest command from its current position rather than completing the previous movement.

Pulse Width (ms) Angle (°)
0.5 0
1.0 45
1.5 90
2.0 135
2.5 180

Implementation Code

The following code demonstrates how to control the SG90 servo using an STM32 microcontroller. A timer generates a 20ms PWM signal, and the angle is mapped to the corresponding pulse width.

servo_driver.h

#ifndef SERVO_DRIVER_H
#define SERVO_DRIVER_H

void initializeServo(void);
void setServoPosition(float position);

#endif

servo_driver.c

#include "stm32f10x.h"

void initializeServo(void)
{
    // Enable peripheral clocks
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    // Configure GPIO pin for alternate function push-pull
    GPIO_InitTypeDef gpioConfig;
    gpioConfig.GPIO_Mode = GPIO_Mode_AF_PP;
    gpioConfig.GPIO_Pin = GPIO_Pin_0;
    gpioConfig.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpioConfig);
    
    // Configure timer for internal clock
    TIM_InternalClockConfig(TIM2);
    
    // Set up timer base configuration
    TIM_TimeBaseInitTypeDef timerConfig;
    timerConfig.TIM_ClockDivision = TIM_CKD_DIV1;
    timerConfig.TIM_CounterMode = TIM_CounterMode_Up;
    timerConfig.TIM_Period = 20000 - 1;     // Auto-reload value for 20ms period
    timerConfig.TIM_Prescaler = 72 - 1;      // Prescaler for 1MHz clock
    timerConfig.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &timerConfig);
    
    // Configure PWM mode
    TIM_OCInitTypeDef pwmConfig;
    TIM_OCStructInit(&pwmConfig);
    pwmConfig.TIM_OCMode = TIM_OCMode_PWM1;
    pwmConfig.TIM_OCPolarity = TIM_OCPolarity_High;
    pwmConfig.TIM_OutputState = TIM_OutputState_Enable;
    pwmConfig.TIM_Pulse = 0;                 // Initial duty cycle
    TIM_OC1Init(TIM2, &pwmConfig);
    
    // Enable timer
    TIM_Cmd(TIM2, ENABLE);
}

void setServoPosition(float position)
{
    // Map angle (0-180) to pulse width (500-2500 microseconds)
    TIM_SetCompare1(TIM2, (position / 180 * 2000) + 500);
}

main.c

#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
#include "servo_driver.h"

float currentAngle;

int main(void)
{
    OLED_Init();
    initializeServo();
    
    while (1)
    {
        OLED_ShowNum(1, 1, currentAngle, 3);
        setServoPosition(currentAngle);
        currentAngle += 30;
        
        if (currentAngle > 180)
        {
            currentAngle = 0;
        }
        
        Delay_ms(500);
    }
}

Controlling 360° Continuous Rotation Servos

In addition to the 180° positional servo, there's also a 360° continuous rotation variant. Unlike the 180° servo, the 360° version cannot be positioned at specific angles. Instead, it controls rotation direction and speed. It also uses a 20ms PWM signal, but with different pulse width interpretations:

Pulse Width (ms) Rotation Behavior
0.5-1.5 Forward rotation, decreasing speed
1.5 Stopped
1.5-2.5 Reverse rotation, increasing speed

Tags: SG90 Servo PWM STM32 microcontroller

Posted on Sun, 24 May 2026 17:31:06 +0000 by tibiz