<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ian Hong</title>
    <description>The latest articles on DEV Community by Ian Hong (@ihong95).</description>
    <link>https://dev.to/ihong95</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3886575%2F678436f5-aaef-4ae2-9b97-2e6c27f77c8a.png</url>
      <title>DEV Community: Ian Hong</title>
      <link>https://dev.to/ihong95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ihong95"/>
    <language>en</language>
    <item>
      <title>Servo Motor Calibration: Does It Matter?</title>
      <dc:creator>Ian Hong</dc:creator>
      <pubDate>Sun, 19 Apr 2026 01:11:31 +0000</pubDate>
      <link>https://dev.to/ihong95/servo-motor-calibration-does-it-matter-1685</link>
      <guid>https://dev.to/ihong95/servo-motor-calibration-does-it-matter-1685</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hobby servos are known for their low price, accessibility, and ease of use. However, it’s no secret that they are not meant for ultra high-precision tasks. What kind of tasks can be categorized as ultra high-precision? I hope to give some insight on the capabilities of these servos so you can decide that for yourself.&lt;/p&gt;

&lt;p&gt;Below are some of the more common servos that are used in many beginner tutorials.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uaxboqaqp8sor7bxitn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uaxboqaqp8sor7bxitn.png" alt="SG90 (blue), MG90S (transparent black), MG996 (opaque black)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Those are very jittery, so we will explore the next step up in quality, the DS3235.&lt;/p&gt;

&lt;p&gt;For applications such as the steering mechanism of an RC car, the jitter and inaccuracy doesn’t matter because you just want to turn some amount in a direction. Where positional accuracy does matter is in applications such as robot arms and pan/tilt camera mechanisms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Operation
&lt;/h2&gt;

&lt;p&gt;Before we dive into the calibration, it’s important to understand the fundamentals of how these servos operate.&lt;/p&gt;

&lt;p&gt;To rotate the servo to a desired position, we use a microcontroller to send a pulse-width modulated (PWM) signal of a certain width (a length of time) to the servo. The servo rotates to an angle based on the width of the pulse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mlba3vzpy6y89zespwc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mlba3vzpy6y89zespwc.png" alt="Basic PWM control of a servo motor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Calibration
&lt;/h2&gt;

&lt;p&gt;Now the question is: how do you know what pulse width to send for each angle? The answer varies wildly by model of servo, and there is even variation between units of the same model. Hence the need for calibration if you want to maximize accuracy.&lt;/p&gt;

&lt;p&gt;The goal of the calibration is to map pulse width values to servo angles, and by attempting to do so we will be able to observe the relationship between PWM signal and servo angle. Is it truly linear? Is it exponential? Is there no clear relationship? We’ll find out!&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Setup
&lt;/h2&gt;

&lt;p&gt;To conduct this test, we need to be able to control the servo with an Arduino with a PCA9685 servo driver and see the servo’s position. The servo’s position is measured using a 3D printed a jig with notches every 15 degrees and an arm with a pointed tip.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyya6ddzu8hfi6ji375ix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyya6ddzu8hfi6ji375ix.png" alt="3D printed jig for servo calibration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Arduino Code
&lt;/h2&gt;

&lt;p&gt;Below is a minimal Arduino code snippet to rotate the servo to a position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Adafruit_PWMServoDriver.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_PWMServoDriver&lt;/span&gt; &lt;span class="n"&gt;servo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Adafruit_PWMServoDriver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#define SERVO_FREQ 60 // Analog servos run at ~50 Hz updates
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;servo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWMFreq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SERVO_FREQ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;servo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPWM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;390&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 390 is the PWM value, this is what you're changing.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Experimentation
&lt;/h2&gt;

&lt;p&gt;The goal is to find the exact PWM value that aligns the servo arm with each notch.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;    Start at one extreme of the servo’s motion.&lt;/li&gt;
&lt;li&gt;    Send different PWM values until the arm aligns as closely as possible with the notch at that extreme.&lt;/li&gt;
&lt;li&gt;    Once the arm is aligned with the notch, record the angle of that notch (remember they are at 15 degree increments) and the corresponding PWM value.&lt;/li&gt;
&lt;li&gt;    Repeat steps 2 and 3 for every notch through the servo’s entire range.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Data Processing
&lt;/h2&gt;

&lt;p&gt;Next, we plot the data we collected to look for a relationship between the pulse width and the servo angle.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzu9f30pcd7x4loacq25a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzu9f30pcd7x4loacq25a.png" alt="Pulse width vs. servo angle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The relationship looks pretty linear! That’s good news, because it means we can easily calculate the pulse width required for any servo angle using the line of best fit (which can be obtained in Excel).&lt;/p&gt;

&lt;p&gt;For some further analysis, we can also look into the variations in the data. If the relationship was perfectly linear, we would observe that the difference in PWM values at any 15 degree servo increment is the same.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2zjfs0997kw4uk0w46t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2zjfs0997kw4uk0w46t.png" alt="PWM differences at each 15 degree increment on the servo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The plot above shows some variation, which could be attributed to the following sources of error:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Measurements done by eye&lt;/li&gt;
&lt;li&gt;    Deadband (minimum PWM change to move the servo)&lt;/li&gt;
&lt;li&gt;    Gear backlash causing hysteresis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Turns out the DS3235 servo is pretty accurate and linear, or at least the one I tested, so you can probably get away with not performing a full calibration as long as you know the pulse width difference between two known positions. Now you know how to calibrate a servo, obtain a relationship between PWM and servo angle, and use that relationship to position the servo accurately.&lt;/p&gt;

&lt;p&gt;Happy experimenting!&lt;/p&gt;

</description>
      <category>robotics</category>
      <category>arduino</category>
      <category>electronics</category>
      <category>hardware</category>
    </item>
  </channel>
</rss>
