A ₹1,010 rig that finds out what your servo really does. Two buttons nudge the pulse width up and down, you read the angle off a protractor, and the sketch saves the pulse widths for 0°, 90° and 180° in EEPROM. The values then go straight into any robot arm or gripper sketch, so the angles on screen match the angles in the world.
Scope: beginner. This is a design worksheet with illustrative costs. It has not been bench-tested by this site. The table was computed by script from the common assumption of 500 to 2,500 µs for 0 to 180°, which is a loose convention: many hobby servos use about 1,000 to 2,000 µs for a smaller range, and cheap ones vary from unit to unit. That variation is exactly why the rig exists. Do not drive a servo past its mechanical stop; stop pushing when it buzzes.
How it works
A hobby servo reads a pulse every 20 ms and turns to match the pulse width. If 500 to 2,500 µs covered 0 to 180°, each microsecond would be 0.09° of travel, and 1,500 µs would be the 90° centre. Real servos often reach their end stops before 500 or 2,500 µs, or need more than that, so a command that is too far makes the servo hum against the stop.
The rig steps the pulse by 10 µs per press, with a long press repeating. You step to the physical 0° mark, press a save button, repeat for 90° and 180°, and the three pulse widths are stored. Later sketches read them and use a straight line between them, with an optional correction for the 90° point if the servo is not linear.
Bill of materials
| Part | Qty | Unit | Total |
|---|---|---|---|
| Arduino Uno R3 (or compatible) | 1 | ₹550 | ₹550 |
| Micro servo (SG90) for testing | 1 | ₹120 | ₹120 |
| Push buttons | 1 | ₹10 | ₹10 |
| Protractor or printed angle scale | 1 | ₹20 | ₹20 |
| External 5 V supply for the servo (optional) | 1 | ₹200 | ₹200 |
| Breadboard | 1 | ₹60 | ₹60 |
| Jumper wires | 1 | ₹50 | ₹50 |
| Parts total | ₹1,010 | ||
Scroll the table sideways to see every column.
Prices checked Nov 2026. Shipping and tools are not included.
Prices are illustrative figures for Indian sellers in November 2026, before shipping, and have not been checked against current listings.
The numbers
| Pulse width | Angle if 500 to 2,500 µs = 0 to 180° |
|---|---|
| 500 µs | 0° |
| 1000 µs | 45° |
| 1500 µs | 90° |
| 2000 µs | 135° |
| 2500 µs | 180° |
If your measured 0° and 180° pulses are a and b microseconds, a later sketch maps an angle θ to a pulse with pulse = a + (b − a) × θ / 180. For example if 0° needs 600 µs and 180° needs 2,350 µs, 90° is 1,475 µs, not 1,500. This takes one line of code and removes the error.
Power and wiring
| Part | Connects to | Note |
|---|---|---|
| Servo signal | D9 | |
| Servo power | 5V from a separate supply if it resets the Uno | Common GND |
| Up button | D2 to GND | Internal pull-up |
| Down button | D3 to GND | Internal pull-up |
| Save button | D4 to GND | Internal pull-up |
The sketch
// Servo end-point calibration rig: Uno + servo + 3 buttons + EEPROM
// Design worksheet: find the pulse widths for 0, 90 and 180 degrees.
#include <Servo.h>
#include <EEPROM.h>
const int SERVO_PIN = 9, UP = 2, DOWN = 3, SAVE = 4;
const int STEP_US = 10;
const int MIN_US = 400, MAX_US = 2600; // hard limits for safety
const int ADDR = 0; // three ints stored from here
Servo s;
int pulse = 1500;
int stage = 0; // 0: 0 deg, 1: 90, 2: 180
int saved[3] = {500, 1500, 2500};
void setup() {
pinMode(UP, INPUT_PULLUP); pinMode(DOWN, INPUT_PULLUP); pinMode(SAVE, INPUT_PULLUP);
Serial.begin(9600);
s.attach(SERVO_PIN);
s.writeMicroseconds(pulse);
Serial.println("Step to the 0 degree mark, then press SAVE");
}
void loop() {
bool moved = false;
if (digitalRead(UP) == LOW) { pulse = min(pulse + STEP_US, MAX_US); moved = true; }
if (digitalRead(DOWN) == LOW) { pulse = max(pulse - STEP_US, MIN_US); moved = true; }
if (moved) { s.writeMicroseconds(pulse); Serial.println(pulse); delay(120); }
if (digitalRead(SAVE) == LOW) {
delay(30);
if (digitalRead(SAVE) == LOW) {
saved[stage] = pulse;
Serial.print("Saved stage "); Serial.print(stage); Serial.print(": "); Serial.println(pulse);
stage++;
if (stage == 3) {
for (int i = 0; i < 3; i++) EEPROM.put(ADDR + i * sizeof(int), saved[i]);
Serial.println("All saved to EEPROM");
stage = 0;
} else {
Serial.println(stage == 1 ? "Now the 90 degree mark" : "Now the 180 degree mark");
}
while (digitalRead(SAVE) == LOW) {}
}
}
}To use the stored values in another sketch, read three ints with EEPROM.get from the same addresses and map the angle to a pulse with the formula above. EEPROM has a limited number of writes (commonly listed at about 100,000 per cell), which is plenty here because it is written only when you finish a calibration. The sketch has been proofread but not compiled on this site.
Test plan
- Centre check: see where 1,500 µs actually points.
- Zero mark: step down until the horn lines up with 0° and note the pulse.
- End stops: step toward each end and stop the moment you hear the servo strain.
- Repeat: calibrate twice and compare the pulses.
- Second servo: repeat with a different servo and compare.
- Readback: reboot and print the stored values from EEPROM.
What usually goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| Servo hums at the end | Pulse beyond its mechanical stop | Back off 20 to 30 µs and save that |
| Jumps when attached | Starting position differs | Write the pulse before attaching |
| Different each time | Backlash in the gears | Approach each mark from the same side |
| Values lost | Saved before all three stages | Complete all three presses |
| Arduino resets on move | Servo draws too much from USB | Use an external 5 V supply |
Upgrades
- Per-joint table: store a calibration for each servo of a robot arm.
- Serial menu: select the servo number and save over Serial.
- Limits: use the end values as software limits.
- Feedback servo: use a servo with a position output to automate this.
Cost and parts notes
The ₹1,010 total is an illustration and does not include shipping. Use the cost calculator to compare sellers.
Common questions
Why is 90° not always 1,500 µs?
Real servos differ from the 1,500 µs convention, sometimes by tens of microseconds.
Does this work for continuous-rotation servos?
No. Those turn at a speed set by the pulse, not to an angle.
Why a hard limit of 400 and 2,600 µs?
To stop a held button from driving the servo far past its stop.
How many times can EEPROM be written?
Datasheets commonly list about 100,000 writes per cell; this rig writes rarely.
Last reviewed: November 2026. This is a design worksheet with illustrative costs. It has not been bench-tested by this site; library names, pins and limits must be checked against your board and the current library versions, and measurements from your build are welcome.