Using Arduino to Control the Rotation Angle and Speed of a Micro Servo Motor

How to Connect a Micro Servo Motor to Arduino / Visits:11

Micro servo motors have become the go-to choice for hobbyists, roboticists, and makers who need precise, compact, and affordable motion control. These tiny actuators—often weighing just a few grams—can rotate to specific angles with remarkable accuracy, making them ideal for projects ranging from robotic arms and animatronics to camera gimbals and automated doors. When paired with an Arduino, the possibilities expand exponentially.

In this guide, we’ll explore how to control both the rotation angle and the speed of a micro servo motor using an Arduino. We’ll cover the hardware setup, the underlying PWM principles, and practical code examples that you can adapt for your own projects. By the end, you’ll be able to command your servo with precision and smoothness, unlocking new levels of control for your builds.

What Makes Micro Servo Motors Special?

Micro servo motors are a subset of servo motors designed for applications where space and weight are critical. The most popular model, the SG90, weighs only about 9 grams and measures roughly 23 x 12 x 29 mm. Despite their small size, they can deliver a torque of around 1.8 kg·cm at 4.8V—enough to lift small objects or move lightweight linkages.

The key feature of any servo motor is its closed-loop control system. Inside the servo, a potentiometer is attached to the output shaft. As the shaft rotates, the potentiometer’s resistance changes, providing feedback to the control circuit. The circuit compares the actual position with the desired position (set by the input signal) and drives the motor until they match. This internal feedback makes servos self-correcting and highly accurate.

Micro servos typically have a rotation range of 0 to 180 degrees, though some models can rotate continuously (used for continuous rotation servos). For standard micro servos, the input signal is a pulse-width modulated (PWM) wave with a period of 20 milliseconds (50 Hz). The pulse width determines the angle:

  • 1 ms pulse width → 0 degrees
  • 1.5 ms pulse width → 90 degrees (center)
  • 2 ms pulse width → 180 degrees

Understanding this PWM relationship is the foundation for controlling both angle and speed.

Hardware Setup: What You’ll Need

Before diving into code, let’s gather the necessary components. The setup is straightforward and requires only a few items:

  • Arduino board (Uno, Nano, Mega, or any compatible variant)
  • Micro servo motor (e.g., SG90, MG90S, or similar)
  • Jumper wires (female-to-male recommended for easy connection)
  • External power supply (optional but recommended for multiple servos)
  • Breadboard (optional, for prototyping)

Wiring the Micro Servo to Arduino

Micro servos typically have three wires:

  • Brown or Black wire: Ground (GND)
  • Red wire: Power (5V for most micro servos)
  • Orange or Yellow wire: Signal (PWM input)

Connect them as follows:

  1. Power: Connect the red wire to the Arduino’s 5V pin. For a single servo, the Arduino’s onboard 5V regulator can supply enough current (typically 500 mA for the Uno). If you’re using multiple servos, use an external 5V power supply to avoid overloading the Arduino.
  2. Ground: Connect the brown/black wire to any GND pin on the Arduino.
  3. Signal: Connect the orange/yellow wire to a digital PWM-capable pin. On the Arduino Uno, pins 3, 5, 6, 9, 10, and 11 support hardware PWM. We’ll use pin 9 for our examples.

Here’s a simple wiring diagram:

Micro Servo Arduino ----------------- ---------------- Brown (GND) --> GND Red (5V) --> 5V Orange (Signal) --> Pin 9

That’s it. With this setup, you can already control the servo’s angle using the Arduino’s built-in Servo library.

Controlling Rotation Angle with Arduino

The Arduino ecosystem includes a dedicated Servo library that abstracts the low-level PWM timing. This library allows you to attach a servo to a pin and set its angle using a simple function call.

Basic Angle Control Example

Let’s start with a basic sketch that sweeps the servo from 0 to 180 degrees and back.

cpp

include <Servo.h>

Servo myServo; // Create a servo object

int pos = 0; // Variable to store the servo position

void setup() { myServo.attach(9); // Attach the servo on pin 9 }

void loop() { // Sweep from 0 to 180 degrees for (pos = 0; pos <= 180; pos += 1) { myServo.write(pos); // Tell servo to go to position in variable 'pos' delay(15); // Wait 15 ms for the servo to reach the position }

// Sweep from 180 to 0 degrees for (pos = 180; pos >= 0; pos -= 1) { myServo.write(pos); delay(15); } }

This code works, but it has a limitation: the delay() function blocks the entire program. While the servo is moving, the Arduino cannot do anything else. For simple tests, this is fine, but for real-world projects, you’ll want non-blocking code.

Non-Blocking Angle Control

A better approach uses the millis() function to track time without blocking. This allows the Arduino to perform other tasks while the servo moves.

cpp

include <Servo.h>

Servo myServo; int targetAngle = 0; int currentAngle = 0; unsigned long lastMoveTime = 0; const int moveInterval = 15; // Time between angle steps in ms

void setup() { myServo.attach(9); myServo.write(0); // Start at 0 degrees currentAngle = 0; targetAngle = 180; }

void loop() { unsigned long now = millis();

if (now - lastMoveTime >= moveInterval) { lastMoveTime = now;

// Move one step towards the target if (currentAngle < targetAngle) {   currentAngle++;   myServo.write(currentAngle); } else if (currentAngle > targetAngle) {   currentAngle--;   myServo.write(currentAngle); } else {   // Reached target; swap direction for continuous sweeping   targetAngle = (targetAngle == 0) ? 180 : 0; } 

}

// Other non-blocking tasks can go here }

This non-blocking version achieves the same sweeping motion but leaves the processor free to handle sensor readings, serial communication, or other tasks.

Controlling Rotation Speed: The Fine Art of Ramping

Controlling the angle is straightforward—just call write(angle). But controlling the speed requires a different approach. The servo’s internal controller will always try to reach the commanded position as fast as possible. To slow it down, we need to gradually change the target angle over time, effectively ramping the servo to a desired position.

Speed control is essential for applications where sudden movements would be jarring or unsafe, such as in robotic arms handling fragile objects, or in animatronics where smooth motion is more lifelike.

The Ramping Technique

The idea is simple: instead of commanding the servo to jump directly to the final angle, we break the movement into small steps, with a delay between each step. The smaller the delay, the faster the movement. By varying the delay, we control the speed.

Here’s a function that moves the servo to a target angle at a specified speed:

cpp

include <Servo.h>

Servo myServo; int currentAngle = 90; // Start at center

void setup() { myServo.attach(9); myServo.write(currentAngle); Serial.begin(9600); }

void loop() { // Example: move to 0 degrees slowly, then to 180 degrees quickly moveToAngle(0, 50); // Speed = 50 (slow) delay(1000); moveToAngle(180, 10); // Speed = 10 (fast) delay(1000); moveToAngle(90, 30); // Speed = 30 (medium) delay(1000); }

// Function to move servo to target angle at a given speed // Speed: delay in milliseconds between each degree step // Lower values = faster movement void moveToAngle(int target, int speed) { if (target > currentAngle) { for (int pos = currentAngle; pos <= target; pos++) { myServo.write(pos); delay(speed); } } else { for (int pos = currentAngle; pos >= target; pos--) { myServo.write(pos); delay(speed); } } currentAngle = target; }

In this example, speed is the delay in milliseconds between each degree step. A speed of 50 means the servo takes 50 ms to move each degree, so moving 180 degrees would take 180 × 50 = 9000 ms (9 seconds). A speed of 10 would take 1.8 seconds.

Dynamic Speed Control with Acceleration Profiles

For even smoother motion, you can implement acceleration and deceleration profiles. Instead of moving at a constant speed, the servo starts slowly, accelerates to a maximum speed, then decelerates as it approaches the target. This mimics natural movement and reduces mechanical stress.

Here’s an example using a simple linear acceleration profile:

cpp

include <Servo.h>

Servo myServo; int currentAngle = 90;

void setup() { myServo.attach(9); myServo.write(currentAngle); }

void loop() { // Move with acceleration and deceleration moveWithProfile(0, 180, 20, 5); // maxSpeed=20, accelSteps=5 delay(1000); moveWithProfile(180, 0, 20, 5); delay(1000); }

void moveWithProfile(int start, int end, int maxDelay, int accelSteps) { int totalSteps = abs(end - start); int direction = (end > start) ? 1 : -1;

for (int step = 0; step <= totalSteps; step++) { int pos = start + direction * step; myServo.write(pos);

// Calculate delay based on acceleration profile int delayTime; if (step < accelSteps) {   // Accelerating: decrease delay from max to min   delayTime = map(step, 0, accelSteps, maxDelay, 1); } else if (step > totalSteps - accelSteps) {   // Decelerating: increase delay from min to max   delayTime = map(step, totalSteps - accelSteps, totalSteps, 1, maxDelay); } else {   // Constant speed phase   delayTime = 1;  // Fastest speed }  delay(delayTime); 

}

currentAngle = end; }

This function calculates a delay that decreases during the first few steps (acceleration) and increases during the last few steps (deceleration). The result is a smooth, natural-looking motion.

Advanced Speed Control Using Custom PWM

For ultimate control over speed and angle, you can bypass the Servo library and generate the PWM signal manually. This gives you direct control over the pulse width and allows for finer adjustments.

Manual PWM Generation

The Arduino’s analogWrite() function is not suitable for servos because it generates a fixed-frequency PWM (usually 490 Hz or 980 Hz), whereas servos expect 50 Hz. However, you can use the pulseIn() and pulseOut() functions, or better yet, use the Timer1 library to generate precise 50 Hz PWM.

Here’s an example using the Timer1 library to control both angle and speed:

cpp

include <TimerOne.h>

define SERVO_PIN 9

define MIN_PULSE 1000 // 1 ms for 0 degrees

define MAX_PULSE 2000 // 2 ms for 180 degrees

int targetPulse = 1500; // Start at 90 degrees int currentPulse = 1500;

void setup() { pinMode(SERVOPIN, OUTPUT); Timer1.initialize(20000); // 20 ms period (50 Hz) Timer1.pwm(SERVOPIN, currentPulse); }

void loop() { // Example: ramp from 0 to 180 degrees over 5 seconds rampToPulse(1000, 5000); // 1000 = 0 deg, 5000 ms = 5 seconds delay(2000); rampToPulse(2000, 3000); // 2000 = 180 deg, 3000 ms = 3 seconds delay(2000); }

void rampToPulse(int target, unsigned long durationMs) { int startPulse = currentPulse; int pulseDiff = target - startPulse; unsigned long startTime = millis(); unsigned long elapsed = 0;

while (elapsed < durationMs) { elapsed = millis() - startTime; float progress = (float)elapsed / durationMs; if (progress > 1.0) progress = 1.0;

currentPulse = startPulse + (int)(pulseDiff * progress); Timer1.setPwmDuty(SERVO_PIN, currentPulse);  delay(10);  // Update every 10 ms 

}

currentPulse = target; }

This approach gives you precise control over the pulse width in microseconds, allowing you to fine-tune the servo’s angle beyond the standard 0-180 range if needed. Some servos can rotate slightly beyond 180 degrees, and manual PWM lets you exploit that.

Practical Considerations for Micro Servo Projects

When working with micro servos, keep the following points in mind to ensure reliable performance:

Power Supply and Current Draw

A single micro servo can draw 100-200 mA when idle and up to 700-800 mA under load or stall. The Arduino’s 5V pin can supply about 500 mA from USB, so a single servo is usually fine. However, if you’re using two or more servos, or if your servo will be under heavy load, use an external 5V power supply with at least 2A capacity. Common options include:

  • 5V 2A wall adapter
  • 4x AA battery pack (6V, but check your servo’s voltage tolerance)
  • 5V BEC (Battery Eliminator Circuit) from a LiPo battery

Always connect the servo’s ground to the Arduino’s ground, even when using an external power supply.

Mechanical Stalling

If your servo cannot reach the commanded position because of mechanical resistance, it will stall. Prolonged stalling can overheat the servo and damage the internal gears. To prevent this, implement stall detection in your code by monitoring the current draw (using a current sensor) or by checking if the servo has reached its target within a timeout period.

Choosing the Right Micro Servo

Not all micro servos are created equal. Consider these factors when selecting one for your project:

  • Torque: Measured in kg·cm or oz·in. Higher torque handles heavier loads but draws more current.
  • Speed: Measured in seconds per 60 degrees. Faster servos are good for dynamic projects, slower for precision.
  • Gear material: Plastic gears (SG90) are cheap but wear out quickly. Metal gears (MG90S) are more durable but heavier.
  • Voltage range: Most micro servos operate at 4.8V to 6V. Some can handle up to 7.2V for higher speed and torque.

Real-World Project Ideas

To inspire your own builds, here are a few projects that leverage the angle and speed control techniques we’ve covered:

Robotic Gripper with Variable Grip Speed

Use two micro servos to open and close a gripper. Control the closing speed to handle fragile objects gently versus robust items quickly. The ramping technique ensures smooth, controlled grasping.

Pan-Tilt Camera Mount

A pan-tilt mechanism uses two servos to aim a camera. By controlling the speed, you can create smooth tracking movements for surveillance or photography. Acceleration profiles prevent jerky camera movement.

Animatronic Eyes

Micro servos are perfect for animating robot eyes. Control the gaze direction (angle) and blink speed (rapid movement) to create lifelike expressions. Combine with a third servo for eyelid movement.

Automated Window Blind

Mount a micro servo to rotate a window blind’s control rod. Use angle control to set the blind position and speed control to simulate a natural, gradual adjustment rather than a sudden snap.

Troubleshooting Common Issues

Even with careful setup, you might encounter problems. Here are solutions to common issues:

Servo Jittering or Twitching

  • Cause: Insufficient power or unstable voltage.
  • Fix: Add a 470 µF capacitor between the servo’s power and ground pins to smooth out voltage spikes. Use a dedicated power supply.

Servo Not Moving to Full Range

  • Cause: The pulse width range doesn’t match the servo’s specifications.
  • Fix: Adjust the MIN_PULSE and MAX_PULSE values in your code. Most servos accept 1000-2000 µs, but some may need 500-2500 µs or 600-2400 µs. Experiment to find the exact range.

Servo Overheating

  • Cause: Continuous load or stalling.
  • Fix: Reduce the load, add a heat sink, or implement a timeout in your code to stop the servo if it hasn’t reached its target after a certain time.

Inconsistent Speed

  • Cause: The delay() function is affected by other code running on the Arduino.
  • Fix: Use non-blocking timing with millis() or a timer interrupt for more consistent speed control.

Final Thoughts on Mastering Micro Servo Control

Controlling the rotation angle and speed of a micro servo motor with an Arduino is a fundamental skill that opens the door to countless interactive and robotic projects. The techniques we’ve covered—from basic angle control with the Servo library to advanced speed ramping and custom PWM—give you the tools to create precise, smooth, and responsive motion.

The key takeaway is that angle control is about where the servo goes, while speed control is about how it gets there. By combining both, you can create movements that are not only accurate but also graceful and intentional. Whether you’re building a simple robotic arm or a complex animatronic face, mastering these concepts will elevate your projects from good to great.

Now it’s your turn. Hook up a micro servo to your Arduino, experiment with the code examples, and see what you can create. The only limit is your imagination—and maybe the torque of your servo.

Copyright Statement:

Author: Micro Servo Motor

Link: https://microservomotor.com/how-to-connect-a-micro-servo-motor-to-arduino/control-micro-servo-rotation-angle-speed-arduino.htm

Source: Micro Servo Motor

The copyright of this article belongs to the author. Reproduction is not allowed without permission.

About Us

Lucas Bennett avatar
Lucas Bennett
Welcome to my blog!

Tags