Arduino with Sensors and Actuators

Introduction to Servo Motors and control with Arduino

by Omar Draidrya

Servo motors play a crucial role in robotics and automation. These compact and powerful devices provide precise motion control, making them ideal for a wide range of applications, from simple hobbyist projects to complex industrial robots. This comprehensive article looks at the inner workings of servo motors, especially when combined with Arduino microcontrollers, providing a valuable resource for hobbyists and experienced engineers alike.

Servo motor

Gaining a grasp on Servo Motors

A servo motor is specifically engineered to provide precise control over angular or linear position, velocity, and acceleration. Unlike regular motors that rotate constantly, servo motors are controlled by an electrical pulse of varying width sent through the control wire. This pulse determines the motor’s movement angle or position.

Servo motor intact and disassembled, internal view

Important Elements of a Servo Motor

A hobby servo motor is made up of various important components:

The DC motor is the main component of the servo system, capable of operating at high speeds while delivering moderate torque.
Attached to the motor, the gearbox modifies the motor’s high speed to a lower speed while significantly increasing its torque. This adjustment is extremely important for the motor’s applications, as it requires highly controlled and precise movements.
The potentiometer measures the position of the output shaft by detecting the voltage generated by the shaft’s rotation. This feedback is essential for ensuring precise servo positioning.
The control circuit serves as the central hub for the servo motor. It takes the desired position as input and regulates the motor’s output by adjusting the power according to the feedback from the potentiometer.

Servo motor disassembled; internal view

How Does a Servo Motor Work?

Servo motors operate on the principle of negative feedback, where the control circuit adjusts the motor output to match the input command. Here’s a step-by-step look at this process:

  1. Input Signal: The Arduino sends a PWM signal to the servo. The width of this pulse typically ranges between 0.5ms and 2.5ms, corresponding to the servo’s range of movement (commonly 0 to 180 degrees).
  2. Error Detection: The potentiometer measures the current angle of the servo’s output shaft and generates a voltage that represents this position. The control circuit compares this voltage (actual position) with the voltage corresponding to the input pulse (desired position).
  3. Adjustment: If there is a discrepancy between the desired and actual positions, the control circuit calculates the required adjustment and sends the appropriate signals to correct the motor’s position.
  4. Feedback Loop: This process of adjustment based on feedback continues until the actual position matches the desired position.
    This mechanism, known as a closed-loop control system, is depicted in the diagram below:

Understanding PWM Signal in Servo Motor Control

Closed-loop control system diagram for servo motor positioning

Pulse Width Modulation (PWM) is a technique used to generate analog signals from digital sources by controlling the duration of the pulse within a fixed time frame or period. This method is particularly effective in controlling the motion of servo motors, where the width of the electrical pulse dictates the angle to which the servo arm will rotate.

The PWM signal for servo motors consists of a series of pulses. Each pulse occurs within a specific period, typically 20 milliseconds (ms) for standard hobby servos, corresponding to a frequency of 50 Hz. The crucial aspect of PWM in servo control is the duration of the “high” time in each pulse. This duration, known as the pulse width, determines the position of the servo’s output shaft.

Here’s how a typical PWM signal looks when controlling a servo motor:

PWM signal waveform for servo control, 50 Hz

PWM Signal Table for Servo Positioning

The following table illustrates how different pulse widths, within the typical range, correspond to specific positions of the servo arm:

Pulse Width Servo Position
1.0 ms
0 degrees
1.5 ms
90 degrees
2.0 ms
180 degrees
  1. 0 degrees position: A pulse width of 1.0 ms causes the servo motor to align the arm at 0 degrees. This is the minimum pulse width that can be applied for movement.
  2. 90 degrees position: A pulse width of 1.5 ms moves the servo arm to a neutral or middle position at 90 degrees. This is often considered the default position for calibration.
  3. 180 degrees position: A pulse width of 2.0 ms extends the servo to its maximum rotational limit at 180 degrees.

SG90 Micro and MG996R Servo

Torque, operating voltage, current consumption and size are key considerations for servo motors.

SG90 Micro Servo and MG996R are the most popular servo models:

SG90 Micro Servo MG996R Servo
Stall Torque
1.2 kg·cm @ 4.8V, 1.6 kg·cm @ 6V
11 kg·cm @ 4.8V, 13 kg·cm @ 6V
Operating Voltage
3.5 – 6V
4.8 – 7.2V
No Load Current
100 mA
220 mA @ 4.8V, 250 mA @ 6V
Stall Current
650 mA
650 mA
Max Speed
60 degrees in 0.12s
60 degrees in 0.20s
Weight
9g
55g

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.

Pin Signal Color
1
Ground
Black
2
Power
Red
3
Control
Yellow

Servo testers

Servo testers are essential tools for efficiently evaluating and calibrating servo motors. These devices are generally inexpensive, with basic models available for just a few dollars, making them accessible to hobbyists and professionals alike.

Servo tester module

Setting up your Arduino for servo control project 1: Sweep

Connecting a servo motor to an Arduino is easy and doesn’t require a lot of wiring. Here’s a simple guide to get you started on your first servo project with Arduino:

Hardware requirements:

Arduino board (any model)
SG90 Micro Servo or similar
Independent power source for the servo

Arduino connection setup:

Connect the ground wire of the servo (usually brown or black) to both the ground of the external power supply and the ground of the Arduino.
Connect the servo’s power wire (red) to the positive terminal of the external power supply.
Connect the servo’s control wire (usually orange or yellow) to one of the Arduino’s PWM capable pins; pin 9 is often used.

Wiring diagram for "Project 1: Sweep" – Arduino Servo Control

Program the Arduino:

To control the servo, we’ll use the Sweep example provided in the Arduino IDE. This script commands the servo to move from 0 to 180 degrees and back, demonstrating basic servo operations.

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

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

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable ‘pos’
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable ‘pos’
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
}

Setting up your Arduino for servo control project 2: Knob

Connecting a servo motor to an Arduino to control it with a potentiometer is easy and doesn’t require any complex wiring. Here’s how to get started with your first servo project using the “Knob” program:

Hardware requirements:

Arduino board (any model)
SG90 Micro Servo or similar
Independent power source for the servo
A potentiometer

Arduino connection setup:

Connect the ground wire of the servo (usually brown or black) to both the ground of the external power supply and the ground of the Arduino.
Connect the servo’s power wire (red) to the positive terminal of the external power supply.
Connect the servo’s control wire (usually orange or yellow) to one of the Arduino’s PWM capable pins; pin 9 is often used.
Attach the potentiometer: Connect one of the outer pins to 5V and the other outer pin to ground. The middle pin (the wiper) should be connected to an analogue input on the Arduino, such as A0.

Wiring diagram for "Project 2: Knob" – Arduino Servo Control

Program the Arduino:

To control the servo using the potentiometer, we’ll use the “Knob” example provided in the Arduino IDE. This script reads the position of the potentiometer and commands the servo to move accordingly, demonstrating interactive servo operation. As you adjust the potentiometer, the servo will move through its range of 0 to 180 degrees, matching the position to the angle dictated by the knob’s setting.

 

/*
 Controlling a servo position using a potentiometer (variable resistor)
 by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>

 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin = A0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 180);     // scale it for use with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there
}

Servo driver board PCA9685

Controlling servos directly from an Arduino is easy, but you may run into limitations, especially if your project involves multiple servos or other PWM-dependent components. Using all available PWM pins or potential library conflicts over timer resources are common challenges that can hinder the scalability of your designs.

To efficiently manage multiple servos without overloading the Arduino, integrating a dedicated servo driver board, such as one equipped with the PCA9685 chip, is an excellent strategy. This board uses I2C communication, which simplifies connections to just two wires – CL (clock) and SDA (data) – regardless of the number of servos being controlled. It supports control of up to 16 servos per board, and can be daisy-chained with other PCA9685 boards. This setup allows up to 992 servos to be controlled by cascading multiple boards, ideal for large projects.

Each board has simple connections:

GND: Ground connection.
OE: Output enable, usually left unconnected to keep all outputs enabled.
SCL: Clock line for I2C communication.
SDA: Data signal for I2C communication.
VCC: Logic supply at +5 volts.
V+: Power for the servomotors, which can also be supplied via a protected connector on the top of the board for greater protection against reverse polarity.
The board features sets of 3-pin connectors for each servo motor, greatly simplifying the wiring process and providing a robust solution for projects requiring extensive servo control without taxing the resources of the primary controller. This approach not only increases the reliability of the project, but also streamlines the development process, allowing you to focus on higher-level programming and design tasks.

Servo driver board PCA9685​

To effectively manage and control 16 servo motors using a PCA9685-based driver with your Arduino, follow these detailed steps to correctly set up and wire the components:

Connecting to the Arduino
The PCA9685 servo driver uses I2C communication and requires only four connections to your Arduino. Here’s how to connect it depending on your Arduino model:

Classic Arduino (Uno, etc.)
+5V -> VCC (powers the PCA9685 chip, not the servos)
GND -> GND
Analog 4 -> SDA
Analog 5 -> SCL

Powering the servos:

VCC on the PCA9685 board only powers the chip itself. To power the servos you must also connect the V+ pin, which can handle up to 6V even if VCC is at 3.3V.
A polarised terminal block is recommended for connecting the servo power.
As servos can draw considerable current, especially under load, you should consider these power sources:
5V 2A switching power supply for smaller or fewer servos.
4xAA battery holder – Provides 6V from alkaline cells or 4.8V from NiMH cells.

Connecting the servos:

Connect each servo to the PCA9685 board using its standard 3-pin socket. Ensure that the ground wire (usually black or brown) matches the bottom row of pin headers on the board and that the signal wire (usually yellow or white) matches the top row.

Setting up your Arduino for a dual servo control project using PCA9685 and potentiometers

Controlling two servos with an Arduino Uno and a PCA9685 driver board using two potentiometers is an excellent project for understanding the mechanics of servo movement and the principles of analogue input processing. This guide will walk you through setting up the hardware, connecting the components, and programming the Arduino for precise servo control.

Hardware requirements:

Arduino Uno: The core microcontroller board for the project.
PCA9685 servo driver board: Allows you to control up to 16 servos.
Two SG90 Micro Servos (or similar): These are the actuators for the project.
Two potentiometers: These provide the input for controlling the servo positions.
Independent power supply for the servos: Preferably 5V or 6V, enough to drive several servos.
Jumper wires: To make connections between components.
Arduino connection setup:

Power connections:

Arduino 5V to PCA9685 VCC: Powers the logic on the PCA9685.
External power (5V or 6V) to PCA9685 V+: Powers the servos.
GND from both power sources to Arduino GND: Provides common ground.
I2C connections for PCA9685:
SDA on Arduino to SDA on PCA9685
SCL on Arduino to SCL on PCA9685
These connectors allow communication over the I2C bus.

Servo connections:

Connect the two servos to channels (e.g. 0 and 15) on the PCA9685. Ensure that the orientation of the ground, power and signal wires matches the PCA9685 pinout.
Potentiometer connections:
Connect the outer pins of each potentiometer to the Arduino’s 5V and GND.
Connect the middle pin (wiper) of one potentiometer to A0 and the other to A1 on the Arduino. This will provide the variable input to control the servos.

Wiring diagram for a dual servo control project using PCA9685 and potentiometers

Programming the Arduino:

To control the two servos based on the potentiometer inputs, you will need to write a program that reads the analogue values from the potentiometers and converts them to servo positions.

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// Initialize the PCA9685 using the default address (0x40).
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

void setup() {
  Serial.begin(9600);
  pwm.begin();
 
  // Set the frequency to 60 Hz, good for servo control
  pwm.setPWMFreq(60);
 
  // Setup the analog pins as input
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
}

void loop() {
  // Read the potentiometers
  int potVal0 = analogRead(A0);  // Read the first potentiometer
  int potVal1 = analogRead(A1);  // Read the second potentiometer

  // Map the potentiometer values to servo pulse lengths
  int servoPos0 = map(potVal0, 0, 1023, 150, 600); // Change values 150 to 600 depending on your servo specifications
  int servoPos1 = map(potVal1, 0, 1023, 150, 600);

  // Set the servo positions
  pwm.setPWM(0, 0, servoPos0);  // Set servo on channel 0
  pwm.setPWM(15, 0, servoPos1); // Set servo on channel 15

  delay(20);  // Small delay to reduce jitter
}