DEV Community

張旭豐
張旭豐

Posted on

5 SG90 Servo Projects That Move With Purpose

5 SG90 Servo Projects That Move With Purpose

Build precision control projects: robot arm, pan-tilt camera, pet feeder, smart door lock, and line-following robot

SG90 Servo Motor Hero

The SG90 micro servo motor is one of the most useful precision actuators in maker projects. It rotates to a specific angle (typically 0-180°) based on a PWM signal from your Arduino. Unlike DC motors, you don't need motor drivers — servos work directly from Arduino pins. In this guide, we'll build five precision control projects that use servo motors to create purposeful, repeatable motion.

Topics covered: Servo library, PWM control, angle calibration, position holding, force measurement, pan-tilt mechanics, gripper design.


What You'll Need

  • SG90 servo motor (×1-4 depending on project)
  • Arduino Nano or Uno (×1)
  • Jumper wires
  • 5V power supply (servo can draw significant current)
  • Potentiometer (for manual control projects)
  • Push button (for trigger projects)

How the SG90 Servo Works

The SG90 uses PWM (pulse width modulation) to set position. A 50Hz signal (20ms period) with pulse widths between 1ms (0°) and 2ms (180°) controls the shaft position. The servo holds its position against resistance thanks to internal gears.

Arduino          SG90 Servo
  Pin 9  ──────  Signal (yellow/orange)
  5V     ──────  VCC (red)
  GND    ──────  GND (brown)
Enter fullscreen mode Exit fullscreen mode

Critical: Never drive the servo directly from the Arduino's 5V pin during continuous operation. Use a separate 5V 1A supply for any servo project.

// WF1 Run #040 - Basic Servo Sweep
#include <Servo.h>

#define SERVO_PIN  9

Servo myServo;

void setup() {
  myServo.attach(SERVO_PIN);
  myServo.write(0);  // Start at 0 degrees
}

void loop() {
  // Sweep from 0 to 180 degrees
  for (int angle = 0; angle <= 180; angle += 1) {
    myServo.write(angle);
    delay(15);  // Allow servo to reach position
  }
  delay(1000);

  // Sweep back from 180 to 0 degrees
  for (int angle = 180; angle >= 0; angle -= 1) {
    myServo.write(angle);
    delay(15);
  }
  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Project 1: Robot Arm Pick and Place

Goal: A 4-DOF (degree of freedom) robot arm that can pick up a small object from one location and place it in another.

Robot Arm

Hardware

  • 4× SG90 servo motors
  • Arduino Mega (for enough PWM pins)
  • 5V 3A power supply
  • Acrylic or 3D printed arm parts
  • Small gripper/clamp at end

Code

// WF1 Run #040 - Project 1: Robot Arm
#include <Servo.h>

#define BASE_SERVO    2
#define SHOULDER_SERVO 3
#define ELBOW_SERVO   4
#define GRIPPER_SERVO 5

#define GRIP_OPEN  0
#define GRIP_CLOSE 60

Servo base, shoulder, elbow, gripper;

void moveServo(Servo s, int targetAngle, int stepDelay = 20) {
  int current = s.read();
  int step = (targetAngle > current) ? 1 : -1;
  while (current != targetAngle) {
    current += step;
    s.write(current);
    delay(stepDelay);
  }
}

void setup() {
  base.attach(BASE_SERVO);
  shoulder.attach(SHOULDER_SERVO);
  elbow.attach(ELBOW_SERVO);
  gripper.attach(GRIPPER_SERVO);

  gripper.write(GRIP_CLOSE);  // Start gripper closed
  delay(500);

  // Home position
  moveServo(base, 90);
  moveServo(shoulder, 90);
  moveServo(elbow, 90);
}

void loop() {
  // Pick position
  moveServo(base, 30);
  moveServo(shoulder, 120);
  moveServo(elbow, 60);
  gripper.write(GRIP_OPEN);
  delay(500);

  // Descend and grip
  moveServo(elbow, 30);
  gripper.write(GRIP_CLOSE);
  delay(500);

  // Lift and rotate
  moveServo(elbow, 60);
  moveServo(base, 150);
  moveServo(shoulder, 90);

  // Release
  gripper.write(GRIP_OPEN);
  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Project 2: Pan-Tilt Camera Mount

Goal: A camera mount that automatically tracks a moving person using a PIR sensor, or can be manually aimed with a joystick.

Pan-Tilt Camera

Hardware

  • 2× SG90 servo motors (pan + tilt)
  • Arduino Nano
  • HC-SR501 PIR sensor (for motion tracking)
  • Joystick module (for manual control)
  • ESP32-CAM or webcam

Code

// WF1 Run #040 - Project 2: Pan-Tilt Camera
#include <Servo.h>

#define PAN_SERVO   9
#define TILT_SERVO  10
#define PIR_PIN     7
#define JOYSTICK_X  A0
#define JOYSTICK_Y  A1

#define PAN_MIN   0
#define PAN_MAX   180
#define TILT_MIN  30
#define TILT_MAX  120

Servo panServo;
Servo tiltServo;
int panAngle = 90;
int tiltAngle = 60;
bool autoMode = true;

void setup() {
  panServo.attach(PAN_SERVO);
  tiltServo.attach(TILT_SERVO);
  panServo.write(panAngle);
  tiltServo.write(tiltAngle);
  pinMode(PIR_PIN, INPUT);
  Serial.begin(115200);
}

void loop() {
  int xRead = analogRead(JOYSTICK_X);
  int yRead = analogRead(JOYSTICK_Y);

  // Joystick threshold to avoid drift
  if (xRead < 400) {
    panAngle = max(PAN_MIN, panAngle - 2);
    autoMode = false;
  } else if (xRead > 600) {
    panAngle = min(PAN_MAX, panAngle + 2);
    autoMode = false;
  }

  if (yRead < 400) {
    tiltAngle = max(TILT_MIN, tiltAngle - 2);
    autoMode = false;
  } else if (yRead > 600) {
    tiltAngle = min(TILT_MAX, tiltAngle + 2);
    autoMode = false;
  }

  panServo.write(panAngle);
  tiltServo.write(tiltAngle);

  // If no manual input for 5 seconds, return to auto mode
  if (!autoMode) {
    delay(5000);
    autoMode = true;
  }

  delay(50);
}
Enter fullscreen mode Exit fullscreen mode

Project 3: Automatic Pet Feeder

Goal: A timed pet feeder that dispenses a portion of food at set times each day, with a manual feed button.

Pet Feeder

Hardware

  • SG90 servo motor
  • Arduino Nano
  • DS3231 RTC module
  • Push button
  • LED indicator
  • Food hopper (3D printed or repurposed container)

Code

// WF1 Run #040 - Project 3: Automatic Pet Feeder
#include <Servo.h>
#include <Wire.h>
#include <RTClib.h>

#define SERVO_PIN     9
#define BUTTON_PIN    7
#define FEED_LED      8

#define FEED_HOUR_1   8   // 8:00 AM
#define FEED_HOUR_2   18  // 6:00 PM
#define SERVO_OPEN    90
#define SERVO_CLOSE    0

RTC_DS3231 rtc;
Servo feederServo;
bool alreadyFed1 = false;
bool alreadyFed2 = false;

void dispenseFood() {
  Serial.println("Dispensing food...");
  feederServo.write(SERVO_OPEN);
  delay(3000);  // Open for 3 seconds
  feederServo.write(SERVO_CLOSE);
  delay(500);
}

void setup() {
  Serial.begin(115200);
  feederServo.attach(SERVO_PIN);
  feederServo.write(SERVO_CLOSE);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(FEED_LED, OUTPUT);

  if (!rtc.begin()) {
    Serial.println("RTC not found");
  }
  // Set time: rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
  DateTime now = rtc.now();

  // Timed feeding
  if (now.hour() == FEED_HOUR_1 && !alreadyFed1) {
    dispenseFood();
    alreadyFed1 = true;
  } else if (now.hour() != FEED_HOUR_1) {
    alreadyFed1 = false;
  }

  if (now.hour() == FEED_HOUR_2 && !alreadyFed2) {
    dispenseFood();
    alreadyFed2 = true;
  } else if (now.hour() != FEED_HOUR_2) {
    alreadyFed2 = false;
  }

  // Manual button feed
  if (digitalRead(BUTTON_PIN) == LOW) {
    dispenseFood();
    digitalWrite(FEED_LED, HIGH);
    delay(500);
    digitalWrite(FEED_LED, LOW);
  }

  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Project 4: Smart Door Lock

Goal: A door lock that can be triggered by a keypad code or RFID card, with servo-driven deadbolt and status LED.

Smart Door Lock

Hardware

  • SG90 servo motor (high torque version recommended)
  • Arduino Nano
  • 4×4 keypad
  • RFID RC522 module (optional)
  • Red/Green LED indicators
  • 3D printed lock mechanism

Code

// WF1 Run #040 - Project 4: Smart Door Lock
#include <Servo.h>
#include <Keypad.h>

#define SERVO_PIN    9
#define GREEN_LED   10
#define RED_LED     11

#define LOCKED_ANGLE   0
#define UNLOCKED_ANGLE 90

#define CODE_LENGTH  4
const char correctCode[] = {'1', '2', '3', '4'};

Servo lockServo;
char enteredCode[CODE_LENGTH];
int codeIndex = 0;

const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, 8, 9};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void unlockDoor() {
  lockServo.write(UNLOCKED_ANGLE);
  digitalWrite(GREEN_LED, HIGH);
  digitalWrite(RED_LED, LOW);
  Serial.println("UNLOCKED");
  delay(5000);  // Auto-lock after 5 seconds
  lockServo.write(LOCKED_ANGLE);
  digitalWrite(GREEN_LED, LOW);
  digitalWrite(RED_LED, HIGH);
  Serial.println("LOCKED");
}

void setup() {
  Serial.begin(115200);
  lockServo.attach(SERVO_PIN);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  lockServo.write(LOCKED_ANGLE);
  digitalWrite(RED_LED, HIGH);
}

void loop() {
  char key = keypad.getKey();

  if (key) {
    Serial.print("Key: ");
    Serial.println(key);

    if (key == '#') {
      // Check code
      bool correct = true;
      for (int i = 0; i < CODE_LENGTH; i++) {
        if (enteredCode[i] != correctCode[i]) {
          correct = false;
          break;
        }
      }
      if (correct) {
        unlockDoor();
      } else {
        Serial.println("WRONG CODE");
        digitalWrite(RED_LED, HIGH);
        delay(500);
      }
      codeIndex = 0;
    } else if (key == '*') {
      // Clear
      codeIndex = 0;
      Serial.println("Cleared");
    } else {
      if (codeIndex < CODE_LENGTH) {
        enteredCode[codeIndex++] = key;
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Project 5: Line-Following Robot Steering

Goal: A small robot car that steers using a servo motor to follow a black line on a white surface.

Line-Following Robot

Hardware

  • SG90 servo motor (for steering)
  • Arduino Nano
  • 2× IR infrared line sensors
  • 2× DC motors (for rear wheels)
  • Motor driver module (L298N)
  • Robot car chassis

Code

// WF1 Run #040 - Project 5: Line-Following Robot
#include <Servo.h>

#define STEERING_SERVO  9
#define LEFT_MOTOR      10
#define RIGHT_MOTOR     11
#define IR_LEFT         A0
#define IR_RIGHT        A1

#define LINE_BLACK      LOW   // IR sensor reads LOW on black line
#define STEER_LEFT      30
#define STEER_CENTER    90
#define STEER_RIGHT     150
#define MOTOR_SPEED     150

Servo steeringServo;

void setup() {
  steeringServo.attach(STEERING_SERVO);
  steeringServo.write(STEER_CENTER);

  pinMode(LEFT_MOTOR, OUTPUT);
  pinMode(RIGHT_MOTOR, OUTPUT);
  pinMode(IR_LEFT, INPUT);
  pinMode(IR_RIGHT, INPUT);

  Serial.begin(115200);
}

void loop() {
  int leftIR = digitalRead(IR_LEFT);
  int rightIR = digitalRead(IR_RIGHT);

  Serial.print("L:");
  Serial.print(leftIR);
  Serial.print(" R:");
  Serial.println(rightIR);

  if (leftIR == LINE_BLACK && rightIR == LINE_BLACK) {
    // On the line — go straight
    steeringServo.write(STEER_CENTER);
    analogWrite(LEFT_MOTOR, MOTOR_SPEED);
    analogWrite(RIGHT_MOTOR, MOTOR_SPEED);
  } else if (leftIR == LINE_BLACK) {
    // Line is to the left — steer left
    steeringServo.write(STEER_LEFT);
    analogWrite(LEFT_MOTOR, MOTOR_SPEED / 2);
    analogWrite(RIGHT_MOTOR, MOTOR_SPEED);
  } else if (rightIR == LINE_BLACK) {
    // Line is to the right — steer right
    steeringServo.write(STEER_RIGHT);
    analogWrite(LEFT_MOTOR, MOTOR_SPEED);
    analogWrite(RIGHT_MOTOR, MOTOR_SPEED / 2);
  } else {
    // Lost the line — stop and search
    analogWrite(LEFT_MOTOR, 0);
    analogWrite(RIGHT_MOTOR, 0);
  }

  delay(10);
}
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

Problem Cause Fix
Servo jitters or oscillates Insufficient power Use a dedicated 5V supply with at least 1A current
Servo won't rotate fully Mechanical obstruction Check for cable interference or gear binding
Servo gets hot Continuous strain Don't hold max-load position for long periods; use torque-appropriate servo
Servo makes grinding noise on startup Initial position mismatch Move to 90° before attaching horn
IR sensor gives wrong readings Ambient IR interference Shield sensors from direct sunlight

Start Here

Affiliate disclosure: As an Amazon Associate, I earn from qualifying purchases.

The right parts make the difference:

SG90 Micro Servo Motor — Affordable and reliable for most projects.

Arduino Mega 2560 — Enough PWM pins for multi-servo projects.

SG90 High Torque Version — Metal gears and more torque for heavier loads.

4x4 Matrix Keypad — For door lock and menu projects.


Next Step: From Scene to Sensor, Without Writing Code

If this guide gave you ideas for your own setup — but you're not sure which sensors and outputs work best for your specific space — I can help you map that out.

I offer a personalized interactive device design guide at Fiverr:

👉 https://www.fiverr.com/phd_hfchang/generate-an-arduino-interactive-prototypef

What you get:

  • A custom guide based on your actual scene (not generic recommendations)
  • Sensor selection matched to user behavior and physical constraints
  • Interaction logic without needing to write code from scratch
  • Testing methodology with pass/fail criteria for each output

Tags: Arduino SG90 Servo Motor Control Robotics Arduino Projects Automation

Top comments (0)