Using Arduino to Control the Speed and Direction of a Micro Servo Motor
In the vibrant world of electronics and robotics, few components are as simultaneously accessible and powerful as the micro servo motor. These tiny, programmable actuators are the beating heart of countless projects, from animatronic props and robotic arms to camera gimbals and automated plant waterers. Their magic lies in their ability to move to a precise angular position on command. But what if you need more than just position control? What if you want to dictate not just where it points, but how fast and in what direction it sweeps? This is where the synergy of a micro servo and an Arduino microcontroller becomes truly transformative. Let's dive into the practical art of harnessing this duo for complete control over speed and direction.
Why the Micro Servo? Understanding the Core of the Component
Before we write a single line of code, it's crucial to understand what makes a micro servo motor special. Unlike standard DC motors that simply spin when power is applied, a servo is an integrated system. Inside its compact plastic casing, you'll find: * A small DC motor * A gear train to reduce speed and increase torque * A control circuit * A potentiometer attached to the output shaft
This potentiometer is the key. It provides real-time feedback to the control circuit about the shaft's current position. When you send a target position signal, the internal circuit compares it to the current position from the potentiometer and drives the motor in the direction needed to match them. This closed-loop system is why servos are so accurate for positional control.
Key Specifications for Your Project: * Operating Voltage: Typically 4.8V to 6V. Never exceed 7V for most standard micro servos. * Stall Torque: The force it can exert when powered but prevented from moving. Measured in kg-cm or oz-in. Micro servos often range from 1.5 to 3 kg-cm. * Speed: Usually listed as the time to move 60 degrees (e.g., "0.12 sec/60°" at 4.8V). This is a fixed characteristic under load.
The critical takeaway? Standard servo control is about setting a position, not a speed. To control speed, we must think differently.
The Hardware Setup: Building the Foundation
For this guide, we'll use the ubiquitous SG90 micro servo and an Arduino Uno. The principles apply to any standard hobby servo.
What You'll Need
- Arduino Uno (or Nano, Mega, etc.)
- SG90 Micro Servo Motor
- Jumper wires (Male-to-Male)
- A breadboard (optional, but helpful)
- USB cable for Arduino
- External 5V power supply (recommended for more than one servo)
Circuit Connections: Getting Wired Up
The wiring is beautifully simple. A standard 3-wire servo has: 1. Brown or Black Wire: GROUND. Connect this to the Arduino's GND pin. 2. Red Wire: POWER (VCC). Connect to the Arduino's 5V pin for testing. Warning: Drawing too much current through the Arduino's regulator can damage it. For robust operation or multiple servos, use an external 5V supply connected to the breadboard's power rail. 3. Orange or Yellow Wire: SIGNAL. This is the control line. Connect it to a Pulse Width Modulation (PWM)-capable pin on the Arduino (marked with a ~ on the Uno, like pins 3, 5, 6, 9, 10, 11).
Pro Tip: Always connect the grounds of the Arduino and any external power supply together. A common ground is non-negotiable for proper signal reference.
The Heart of Control: Demystifying the Servo Signal
Arduino doesn't send a voltage level to a servo; it sends a pulse train. This is the core concept.
- The servo expects a pulse every ~20 milliseconds (50 Hz frequency).
- The width of that pulse determines the angle.
- A 1.5 ms pulse typically centers the servo (e.g., 90°).
- A 1.0 ms pulse drives it to one extreme (e.g., 0°).
- A 2.0 ms pulse drives it to the other extreme (e.g., 180°).
These pulse widths can vary slightly between models, which is why calibration is useful. The Arduino's Servo library handles this timing with remarkable precision, freeing us from low-level timer code.
Software Strategies: From Basic Sweep to Controlled Motion
Now, let's translate theory into code. We'll explore three progressive methods.
Method 1: The Built-in Servo.h Library (Position Control)
This is the absolute starting point. It gives us direct position control.
cpp
include <Servo.h>
Servo myServo; // Create a servo object int servoPin = 9; int pos = 0; // Variable to store the servo position
void setup() { myServo.attach(servoPin); // Attaches the servo on pin 9 }
void loop() { // Sweep from 0 to 180 degrees for (pos = 0; pos <= 180; pos += 1) { myServo.write(pos); // Command the position delay(15); // Wait for the servo to reach the position } // Sweep back from 180 to 0 degrees for (pos = 180; pos >= 0; pos -= 1) { myServo.write(pos); delay(15); } } Here, the delay(15) indirectly controls speed. Increasing it slows the sweep; decreasing it speeds it up. However, this method blocks all other code execution during the delay(). It's simple but inefficient for complex projects.
Method 2: Simulating Speed Control with write() and millis()
To gain independent speed control without blocking, we ditch delay() and use time-based movement.
cpp
include <Servo.h>
Servo myServo; int servoPin = 9;
int targetPos = 180; int currentPos = 0; unsigned long previousMillis = 0; int speedDelay = 20; // Lower value = faster speed. Time between each 1-degree step.
void setup() { myServo.attach(servoPin); myServo.write(currentPos); }
void loop() { unsigned long currentMillis = millis();
// Check if it's time to move the servo if (currentMillis - previousMillis >= speedDelay) { previousMillis = currentMillis;
if (currentPos < targetPos) { currentPos++; } else if (currentPos > targetPos) { currentPos--; } myServo.write(currentPos); }
// Example: Change target and speed based on a condition // The rest of your non-blocking code can run here! if (currentPos == targetPos) { targetPos = (targetPos == 180) ? 0 : 180; speedDelay = (speedDelay == 20) ? 5 : 20; // Change speed dynamically } } This is a major leap forward. The servo moves one degree every speedDelay milliseconds. The loop() continues cycling, allowing you to read sensors, handle serial commands, or control other components simultaneously. You now have programmable speed.
Method 3: Advanced - Direct Pulse Writing with writeMicroseconds()
For ultimate control, especially for calibrating or using servos as continuous rotation drives, we can bypass the angle mapping.
cpp
include <Servo.h>
Servo myServo; int servoPin = 9;
void setup() { myServo.attach(servoPin); // Calibration: Find your servo's true stop pulse for continuous rotation // myServo.writeMicroseconds(1500); // Typical stop for many servos }
void loop() { // Controlled Clockwise Rotation at varying speeds for (int pulse = 1300; pulse >= 700; pulse -= 10) { myServo.writeMicroseconds(pulse); delay(1000); // Run at each "speed" for 1 second }
// Controlled Counter-Clockwise Rotation for (int pulse = 1700; pulse <= 2300; pulse += 10) { myServo.writeMicroseconds(pulse); delay(1000); } } The writeMicroseconds() function sends the raw pulse width. This is essential for converting a standard positional servo into a continuous rotation servo (often done by physically removing the potentiometer's stop and modifying the gear train). In this mode, a pulse near 1500µs stops the motor, smaller pulses command full speed in one direction, and larger pulses command full speed in the other, with variable speed in between.
Project Idea: A Non-Blocking, Sensor-Controlled Servo System
Let's synthesize everything into a practical example: a servo that smoothly follows a potentiometer (as a manual input) but has its speed limited based on the reading from a distance sensor (simulating a safety governor).
cpp
include <Servo.h>
Servo governedServo; const int servoPin = 9; const int potPin = A0; const int trigPin = 10; const int echoPin = 11;
int currentServoPos = 90; int targetServoPos = 90; int maxSpeedStep = 5; // Governor: max degrees to move per cycle unsigned long lastMoveTime = 0; int governorDelay = 50; // Base update time
void setup() { governedServo.attach(servoPin); governedServo.write(currentServoPos); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); Serial.begin(9600); }
long getDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration = pulseIn(echoPin, HIGH); return duration * 0.034 / 2; // Convert to cm }
void loop() { unsigned long currentMillis = millis();
// 1. Read the target from the potentiometer (0-1023 to 0-180) int potValue = analogRead(potPin); targetServoPos = map(potValue, 0, 1023, 0, 180);
// 2. Read the distance sensor and set the speed governor long distance = getDistance(); if (distance < 10) { // Object very close maxSpeedStep = 1; // Creep very slowly governorDelay = 100; } else if (distance < 30) { maxSpeedStep = 2; // Move slowly governorDelay = 75; } else { maxSpeedStep = 5; // Move at normal speed governorDelay = 50; }
// 3. Non-blocking, governed movement towards the target if (currentMillis - lastMoveTime >= governorDelay) { lastMoveTime = currentMillis;
int error = targetServoPos - currentServoPos; int moveStep = constrain(error, -maxSpeedStep, maxSpeedStep); currentServoPos += moveStep; currentServoPos = constrain(currentServoPos, 0, 180); governedServo.write(currentServoPos); // Serial monitoring for debugging Serial.print("Target: "); Serial.print(targetServoPos); Serial.print(" | Current: "); Serial.print(currentServoPos); Serial.print(" | Distance: "); Serial.print(distance); Serial.print(" | Step: "); Serial.println(moveStep); } } This project demonstrates professional-grade control: responsive input, sensor-based adaptive behavior, and butter-smooth, non-blocking motion—all with a few dollars worth of components.
Troubleshooting Common Pitfalls
- Jittering/Jerking Servo: This is often a power issue. The servo draws a surge of current when it starts moving. Use a capacitor (e.g., 100µF electrolytic) across the power and ground rails near the servo. Always use an external power supply for more than one servo.
- Servo Doesn't Move/Resets Arduino: A classic symptom of insufficient power. The servo is pulling so much current that the Arduino's voltage regulator browns out. Disconnect the servo's power wire from the Arduino's
5Vand use a dedicated supply. - Limited Range of Motion: Your servo might not be a 180° model. Use
writeMicroseconds()to find its actual minimum and maximum pulse widths (often between 500µs and 2500µs). UsemyServo.attach(servoPin, 500, 2500);to calibrate the library. - Noisy Operation: Ensure your code isn't sending a new position command millions of times a second in a tight loop. The servo expects 50Hz commands. The
Servolibrary manages this, but if you're writing pulses manually, adhere to the 20ms frame.
The journey from making a micro servo sweep back and forth to integrating it as a responsive, intelligently governed component in a larger system is what makes physical computing so rewarding. With your Arduino as the brain and the micro servo as a precise muscle, you are now equipped to build not just gadgets, but truly interactive machines. Grab your components, fire up the IDE, and start turning your ideas into controlled, physical motion.
Copyright Statement:
Author: Micro Servo Motor
Source: Micro Servo Motor
The copyright of this article belongs to the author. Reproduction is not allowed without permission.
Recommended Blog
- Using Arduino to Control the Rotation Angle, Speed, and Direction of a Micro Servo Motor
- Using Potentiometers to Control Micro Servo Motors with Arduino
- How to Calibrate Your Micro Servo Motor with Arduino
- How to Use the Arduino Servo Library to Control Micro Servos
- Using Arduino to Control the Position of a Micro Servo Motor
- Integrating Micro Servo Motors into Your Arduino Projects
- How to Connect a Micro Servo Motor to Arduino MKR WAN 1300
- Controlling Multiple Micro Servo Motors Simultaneously with Arduino
- Creating a Servo-Controlled Camera Pan System with Arduino
- How to Connect a Micro Servo Motor to Arduino MKR WAN 1300
About Us
- Lucas Bennett
- Welcome to my blog!
Hot Blog
- How to Connect a Servo Motor to Raspberry Pi Using a Servo Motor Driver Module
- Closed Loop vs Open Loop Control of Micro Servo Motors in Robots
- Micro Servo Motors in Medical Devices: Innovations and Challenges
- The Use of PWM in Signal Filtering: Applications and Tools
- How to Implement Torque and Speed Control in Packaging Machines
- How Advanced Manufacturing Techniques are Influencing Micro Servo Motors
- The Impact of Motor Load on Heat Generation
- Diagnosing and Fixing RC Car Battery Connector Corrosion Issues
- How to Build a Remote-Controlled Car with a Servo Motor
- The Role of Pulse Timing in Micro Servo Function
Latest Blog
- Understanding the Basics of Motor Torque and Speed
- Creating a Gripper for Your Micro Servo Robotic Arm
- Load Capacity vs Rated Torque: What the Specification Implies
- Micro Servo Motors in Smart Packaging: Innovations and Trends
- Micro vs Standard Servo: Backlash Effects in Gearing
- Understanding the Microcontroller’s Role in Servo Control
- How to Connect a Micro Servo Motor to Arduino MKR WAN 1310
- The Role of Micro Servo Motors in Smart Building Systems
- Building a Micro Servo Robotic Arm with a Servo Motor Controller
- Building a Micro Servo Robotic Arm with 3D-Printed Parts
- The Role of Micro Servo Motors in Industrial Automation
- Troubleshooting Common Servo Motor Issues with Raspberry Pi
- The Influence of Frequency and Timing on Servo Motion
- Creating a Servo-Controlled Automated Gate Opener with Raspberry Pi
- Choosing the Right Micro Servo Motor for Your Project's Budget
- How to Use Thermal Management to Improve Motor Performance
- How to Build a Remote-Controlled Car with a GPS Module
- How to Optimize PCB Layout for Cost Reduction
- How to Repair and Maintain Your RC Car's Motor Timing Belt
- Top Micro Servo Motors for Robotics and Automation