Arduino
servo library: Why is the output not between
1000us and 2000us? - and how to fix it. Find out what to download to make the library
work and how to get super accurate Servo positioning. Find out what to do if you're already using Timer 1 for something else.
The Arduino servo library can generate up to twelve servo signals on most Arduino boards,
that you can output from any pin (including analogue pins e.g. A0). They
are generated using a single 16 bit timer - Timer 1.
If you need more servo outputs use an Arduino Mega - 48 Servos, or Arduino Due - 60 Servos.
You can see that a servo only has three wires and two of them provide
power and ground. The third is a control signal that is a PWM modulated waveform.
Note: The Arduino Servo library does not use the PWM timer capabilities.
This control signal, needs to be a
50 Hz PWM voltage waveform varying in mark to space pulse width from 1~2 ms out of a
20 ms total period, with 5V high and 0V low levels. This conveys
sub-millisecond positional commands to the servo motor.
The length of the "on-time" part of the signal conveys the positional
information, and 1ms mark time sets the servo to 0 Degrees, while a 2ms mark time sets
the servo to 180 Degrees. You can set the position of the servo between
these limits by changing the servo on-time.
The main requirement is that the signal must continuously generated at the
control signal pin. You cannot set the position of the servo and then
turn off the control signal because it is actually an analogue system
that requires constant refresh to maintain the position of the output
shaft.
Installing the Arduino Servo library
The code for the Arduino servo library is already integrated into the Arduino
IDE environment so there is no "Arduino servo library download" needed.
So you don't need to install servo library Arduino code.
All you do is include the library using the include operation at the
top of your program and then use the Servo functions (as below).
How to use the Arduino Servo library
Here's a very simple program that shows how to use the Servo library:
#include <Servo.h>
ServomyServo;
voidsetup(){
myServo.attach(9); // See WARNING below}
voidloop(){
// Control servo using write()for(intpos=0;pos<=180;pos+=4){
myServo.write(pos);
delay(15);
}
for(intpos=180;pos>=0;pos-= 4){
myServo.write(pos);
delay(15);
}
// Control servo using writeMicroseconds()
for(intpulse=500;pulse<=2500;pulse+= 20){
myServo.writeMicroseconds(pulse);
delay(15);
}
for(intpulse=2500;pulse>=500;pulse-= 20){
myServo.writeMicroseconds(pulse);
delay(15);
}
}
Just for demonstration purposes, the code above uses both functions
'write()' and 'writeMicroseconds()'. Both these function allow
controlling the servo position by specifying the angle (for the former
function) and pulse width in microseconds for the latter function. The
typical servo pulse widths are:
So this added code sweeps the pulse from 500 to 2500 μs and back,
which moves the servo from one extreme position to the other. It does
this alternating between functions 'write' and 'writeMicroseconds'
You would expect exactly the same output from both but the pulse lengths will be different: Find out why below:
Warning on myServo.attach(pin)
Warning: If you use the above code output pulses you observe will be wrong, specifically when you use myServo.write(angle).
The default output pulses, when you only specify an attach pin, here
pin '9', (with no other parameters) are 544us (angle of 0°) 2400us (for
an angle of 180°). See below for more details
Arduino Servo library: Initialisation and functions
There are two ways to initialise an Arduino Servo library object:
servo.attach(pin)
servo.attach(pin, min, max)
There are two ways to control a servo signal (two member functions in the Servo class):
TIP: Use writeMicroseconds() for very fine control over the Servo position.
Since you can specify the pulse width to within a microsecond using the functionwriteMicroseconds(). This is the function to use if you want fine control over the signal
sent to the servo. If you use the write function you can specify integer
degrees values only which result in multiple microsecond steps.
Arduino library Servo results
Measuring the pulse width for various servo outputs (on pin 9) when
using the initialisation function without min and max values:
Angle requested
pulse out (us)
0
548
45
1012
90
1476
135
1940
180
2400
Well, that looks completely wrong the minimum (at 0°) should be 1000us and the
maximum (at 180°) should be 2000us. Investigating this further it is a deliberate default state set by the Servo library.
If you use the first initialisation function 'write(pin)' i.e. without
specifying (min and max values), then you will see different pulse
width
output periods than the ones you expect (they are not 1ms ~ 2ms!).
Warning: Default servo outputs are wrong with no initialisation.
You can set the minimum and maximum pulse width output by the library
when you use the attach command. The default values if you don't
explicitly write them in are 544us and 2400us.
Here's the relevant section of the Arduino reference:
servo.attach(pin)
servo.attach(pin, min, max)
min (optional): the pulse width, in microseconds, corresponding to the minimum (0 degree) angle on the servo (defaults to 544).
max (optional): the pulse width, in microseconds, corresponding to the maximum (180 degree) angle on the servo (defaults to 2400).
These default values have probably been set to ensure that your servo
will go to its fullest limits, since servos are not the most
angle-accurate devices. The other reason is that it allows you to
individually tune each servo to the minimum and maximum angles (servos
can be different even for the same batch).
Warning: The default min and max pulses are odd values of 544us and 2400us; these are not 1000us and 2000us that you expect! (You can changes these values in initialisation).
Sketch that outputs 1ms to 2ms pulses
To fix the odd pulse length outputs simply initialise the attach
function with the minimum and maximum output pulse length that you need
for 0° and 180°.
Here's an example Arduino Servo library program with correct pulse outputs:
#include <Servo.h>
#define MIN_PULSE 1000
#define MAX_PULSE 2000
ServomyServo;
voidsetup(){
myServo.attach(9,MIN_PULSE,MAX_PULSE);}
voidloop(){
// Sweep from 0 to 180 degrees
for(intangle=0;angle<=180;angle += 4){
myServo.write(angle);
delay(15);
}
// Sweep from 180 to 0 degrees
for(intangle=180;angle>=0;angle -= 4){
myServo.write(angle);
delay(15);
}
}
Code locations
Here are the arduino servo library github locations
servo.h - the class include file (that you include in your file):
If you are already using Timer 1 for something else, for example another library is using Timer1,
and you still want to control servos, then the built-in Arduino Servo
library is not going to be of any use.
Fortunately there is another library that you can use that only uses Timer 2.
Download the zip and install to IDE - Menu>Sketch>Include
library >Add .ZIP library
Note: The library notes for Servotimer2 say you can use up to 8 servos on an Arduino.
What to do if you don't want T1 or T2?
If you have other code that uses Timer1 and Timer2 there is one other
possibilty and that is to directly control PWM output using the
millisecond timer - millis(). Note that there is an extra twist -
you can't just use the millis() timer. Find out how to do it in this
link : Arduino control servo without library.
Written by John Main who has a degree in Electronic Engineering.
Note: Parts of this page were written using claude instant a research assistant.
How to get accurate DHT22 digital humidity sensor readings with an Arduino. Did you know it also measures temperature as Well? Find out why, in this page...
A PIR sensor lets your Arduino sense movement without contact. This tutorial covers PIR sensor basics, connecting one to an Arduino board and coding a motion detector.
Arduino Hall Effect Sensor: Add magnetic sensing superpowers to your Arduino projects with an easy-to-use hall effect sensor. With full code and layout...
Comments
Have your say about what you just read! Leave me a comment in the box below.
Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.