Why Your Servo Motor Drifts and How to Fix It
You write the code. The servo moves to 90 degrees. You watch it hold position. You walk away for five minutes. You come back and it has drifted 15 degrees off target.
You add more code. You try PID. You adjust the parameters. The drift gets worse. You assume the servo is defective. You buy a new one. The new servo drifts the same way.

Servo internals — the potentiometer feedback loop creates a dead zone that causes position drift.
Servo drift is not a defect. It is a characteristic of how hobby servos work, and understanding this characteristic changes how you approach any position-control project.
How a Hobby Servo Actually Works
A standard hobby servo (SG90, MG995, MG996, etc.) is not a closed-loop position controller in the engineering sense. It is a closed-loop speed controller with a position feedback signal that tells the internal circuit whether to keep driving the motor.
The potentiometer inside the servo outputs a voltage proportional to the output shaft angle. The internal circuit compares this voltage to the target voltage derived from your PWM signal. If the potentiometer voltage is lower than target, the circuit drives the motor forward. If it is higher, it drives the motor backward. When they match, the motor stops.
The problem: the potentiometer has a dead zone. In most hobby servos, this dead zone is 1-3 degrees. Within this range, the internal circuit considers the position "close enough" and stops driving the motor. But "close enough" is not "exact."
External forces can push the servo arm outside the dead zone without the internal circuit reacting. Gravity can pull a horizontal arm downward. A spring mechanism can push against the arm. The weight of a connected linkage can create torque that the servo is not actively correcting.
When an external torque exceeds the servo's holding torque, the arm moves. It will only correct when it has drifted far enough for the potentiometer voltage to exit the dead zone on the other side.
Why Adding Code Does Not Fix Drift
Your PWM signal tells the servo where to go. The internal circuit does the rest. From the outside, the servo looks like a position actuator. But it is actually a position sensor with a speed controller inside, and the PWM is a setpoint, not a continuous position command.
When you send a 1500µs pulse (center/neutral), the servo drives to whatever position corresponds to 1500µs. It holds that position within the dead zone. If an external force pushes it out of the dead zone, it corrects back to the center of the dead zone, not to the exact 1500µs position.
This is why PID control in your code rarely helps with hobby servos. The PID algorithm runs on your microcontroller, which sends PWM signals. But the servo is already running its own internal PID on the potentiometer feedback. You are adding an outer loop on top of an inner loop, and the inner loop's dead zone dominates the behavior.
If you need precise position holding against variable external loads, you need a real servo with external position feedback: a servo with a rotary encoder instead of a potentiometer, driven by a microcontroller that reads the encoder and runs the full PID loop.
The Three Real Fixes
Fix 1: Add mechanical constraint. If the external force is predictable (gravity pulling always down), add a physical stop or counter spring that removes the load from the servo when it is supposed to hold position. The servo should not be fighting gravity. It should only be controlling motion.
Fix 2: Use a continuous rotation servo with encoder feedback. A continuous rotation servo (like the modified FS90R) has its output potentiometer replaced with a feedback mechanism. Combined with an external rotary encoder on the output shaft, you can implement true closed-loop position control in your code. The Arduino reads the encoder. Your PID loop outputs PWM. The servo receives PWM and drives the motor. This is how industrial servo systems work.
Fix 3: Choose the right servo for the load. Holding torque ratings on hobby servos are peak torques at rated voltage. The actual holding torque varies with supply voltage, temperature, and manufacturing tolerance. If your application requires the servo to hold position against 1.5kg·cm of torque, buy a servo rated for at least 3kg·cm. Margin matters.
When Servo Drift Is Actually a Mechanical Problem
If your servo is new, driven correctly, and still drifts, the problem might be mechanical:
The gear train has backlash. When the servo corrects direction, it must take up the slack in the gear teeth before the output shaft moves. During this backlash window, the potentiometer is not reading motion, so the internal circuit does not know the output shaft has not moved yet. When the external load pushes the arm during the backlash window, the output shaft moves without the potentiometer sensing it.
Solution: reduce mechanical load on the output shaft, use a servo with metal gears (less backlash), or increase the gear ratio so the motor has more mechanical advantage and less backlash at the output.
The potentiometer is worn. Potentiometers are analog components with physical wiper contacts. Over time, the wiper surface degrades, causing inconsistent voltage output. This manifests as inconsistent holding, dead zone asymmetry, and drift that changes with temperature.
Solution: replace the servo. Potentiometer wear is not repairable in hobby servos.
The Practical Diagnostic Sequence
Before you blame the servo or the code:
- Remove the load from the servo arm. Does it hold position without drifting? If yes, the load is exceeding holding torque.
- Measure the supply voltage at the servo connector under load. Is it stable at the rated voltage? Voltage droop under load causes reduced holding torque.
- Try a different servo with the same code and load. If the new servo does not drift, the original servo has a hardware problem.
- Verify PWM signal with an oscilloscope or logic analyzer. Is the pulse width actually what you think it is? Software timing errors can cause subtle position offsets that look like drift.
Why This Matters for Interactive Art
Most interactive installations use servos for joint control: turning a head, tilting a platform, adjusting a display angle. When the servo drifts, the installation "breathes" — it slowly moves away from its intended position and the viewer sees the mechanism exhale.
This is why museum installations use stepper motors or servo systems with encoder feedback for any position that must hold against gravity. A stepper motor provides holding torque without feedback by design. A servo with encoder feedback provides it through software.
For budget installations where hobby servos are acceptable, the mechanical design must account for the drift characteristic. Use counterweights, springs, or mechanical stops so the servo only does the moving, not the holding.
The servo is not broken. It is doing exactly what it was designed to do. The fix is in the mechanical design, not the code.
For reliable position holding:
MG996R Metal Gear Servo — Higher holding torque than SG90, metal gear train for durability. Use for joints that must hold against gravity. (Amazon)
FS5103B Continuous Rotation Servo + Rotary Encoder Kit — For projects requiring true closed-loop position control with encoder feedback. (Amazon)
NEMA 17 Stepper Motor with Driver — When you need holding torque without drift and do not need high speed. (Amazon)
I earn from qualifying purchases.
Article #011, 2026-04-18. Content Farm pipeline, Run #011.
Top comments (0)