Servo Motor Control with Arduino (0°–180°): Wiring, PWM Theory & Advanced Guide

Learn how to control an SG90 servo motor using Arduino with 0°–180° precision. This advanced guide explains PWM theory, servo internals, wiring, timing diagrams, control techniques, and working Arduino codes with diagrams.

1. Introduction

Servo motors are among the most commonly used electro-mechanical actuators in robotics, RC vehicles, automation, and embedded systems. The SG90 micro servo is lightweight, inexpensive, and capable of rotating approximately 0°–180° with good accuracy.

Controlling a servo with an Arduino seems simple, but understanding what happens internally—and how the PWM control signal actually works—lets you build more stable, precise, and responsive systems.

In this article, we go beyond the typical beginner-level wiring and code. You’ll learn:

  • How the SG90 servo works internally
  • True PWM theory for servo control
  • Why Arduino’s Servo library doesn’t use standard PWM
  • Timing diagrams and pulse-width explanation
  • Control strategies for smooth and stable movement
  • Wiring diagram (included)
  • Basic and advanced Arduino codes

2. How an SG90 Servo Motor Works Internally

The SG90 is a closed-loop position control actuator built with:

DC Motor

Small brushed DC motor providing rotation.

Gearbox

Plastic gear train reduces speed and increases torque.

Rotary Potentiometer

Connected to output shaft; provides real-time angular feedback.

Control PCB

Contains:

  • Error amplifier
  • PID-like control loop
  • H-bridge driver for motor direction
  • Pulse-width decoder

Output Shaft (0°–180° range)

Mechanically limited; cannot rotate 360°.

inside servo motor
Internal View and parts of servo motor
servo motor control mechanism and feedback
Servo motor control mechanism

3. How Servos Understand PWM (Pulse-Width Modulation)

Important:

Servos do not use frequency modulation; they use pulse width modulation at a fixed frequency.

Signal Specs (SG90):

  • Frequency: 50 Hz (period = 20 ms)
  • Pulse width:
    • 1.0 ms → 0°
    • 1.5 ms → 90°
    • 2.0 ms → 180°

📊 Pulse Timing Table

PositionPulse Width
~1.0 ms
45°~1.25 ms
90°~1.5 ms
135°~1.75 ms
180°~2.0 ms
servo pulse timing and angle

Arduino PWM vs Servo PWM: Key Difference

The Arduino’s built-in PWM pins output 490/980 Hz, which is not suitable for servo control.

That is why the Servo.h library uses internal timers (Timer1) to generate the correct 50 Hz servo pulses.

4. Wiring Diagram (SG90 to Arduino UNO)

Connections

SG90 ServoArduino UNO
Brown (GND)GND
Red (VCC)5V
Orange (Signal)D9

⚠️ Use separate power supply for multiple servos.

servo motor wire and pins
Pins of servo motor wire
Servo motor with external power supply
Servo motor with external power supply and potentiometer
components for servo operations
Components Needed for Demonstration

5. Basic Arduino Code (0°–180° Sweep)

#include <Servo.h>

Servo myservo;

void setup() {
  myservo.attach(9);  // Signal connected to pin D9
}

void loop() {
  for (int pos = 0; pos <= 180; pos++) {
    myservo.write(pos);
    delay(15);
  }

  for (int pos = 180; pos >= 0; pos--) {
    myservo.write(pos);
    delay(15);
  }
}
circuit connection of servo with arduino
Circuit connection of servo with Arduino

6. Advanced PWM Timing Code (No Servo Library)

This code manually generates the 1ms–2ms pulses.

int servoPin = 9;

void setup() {
  pinMode(servoPin, OUTPUT);
}

void writeServo(int angle) {
  int pulseWidth = map(angle, 0, 180, 1000, 2000);  // microseconds
  digitalWrite(servoPin, HIGH);
  delayMicroseconds(pulseWidth);
  digitalWrite(servoPin, LOW);
  delay(20 - pulseWidth/1000); // complete 20ms frame
}

void loop() {
  for (int pos=0; pos<=180; pos++) {
    writeServo(pos);
  }
  for (int pos=180; pos>=0; pos--) {
    writeServo(pos);
  }
}

This manually implements servo PWM timing. Useful when:

  • You need custom timing
  • You avoid conflicts with Servo library timers
  • You want deeper control

7. Smoother Motion (Interpolation Control)

For robotics/arms, jumping directly between angles causes jitter.
Use eased motion:

void smoothMove(int startPos, int endPos, int speedDelay) {
  if (startPos < endPos) {
    for (int p = startPos; p <= endPos; p++) {
      myservo.write(p);
      delay(speedDelay);
    }
  } else {
    for (int p = startPos; p >= endPos; p--) {
      myservo.write(p);
      delay(speedDelay);
    }
  }
}

8. Common SG90 Servo Issues & Fixes

1. Jitter / Vibration

Cause:

  • Weak power supply
  • USB-only powering

Fix:

  • Use 5V 1A supply
  • Add 100–470 µF capacitor across VCC–GND

2. Servo moves but doesn’t reach 180°

Cause:

  • Mechanical limits vary
  • Pulse width range differs slightly

Fix:

myservo.writeMicroseconds(500);   // try min  
myservo.writeMicroseconds(2500);  // try max

3. Servo gets hot

Cause:

  • Stall position / overloaded
    Fix:
  • Reduce load
  • Avoid keeping servo commanded at extreme ends

9. Component Recommendations (Affiliate-Friendly, Discreet)

Recommended Components

ComponentLink
SG90 Servo MotorBuy
Arduino UNOBuy
Jumper WiresBuy
5V Power SupplyBuy
100–470 µF CapacitorBuy

Leave a Comment