Understanding the PWM Duty Cycle Formula

Pulse Width Modulation (PWM) Control / Visits:4

If you’ve ever tinkered with a micro servo motor—like the ubiquitous SG90 or MG90S—you’ve likely encountered the term PWM duty cycle. It’s the secret sauce that makes these tiny actuators spin to precise angles, from 0° to 180° and back again. But what exactly is the duty cycle formula, and how does it translate to real-world servo control? In this blog, we’ll unpack the math, the electronics, and the practical nuances of PWM duty cycles as they apply to micro servo motors. Whether you’re a hobbyist building a robot arm or an engineer fine-tuning a gimbal, understanding this formula is your ticket to smooth, accurate motion.

What Is PWM, and Why Do Micro Servos Care?

Pulse Width Modulation (PWM) is a technique for encoding analog signals using digital pulses. Instead of varying the voltage continuously, PWM toggles a signal between HIGH and LOW at a fixed frequency, and the duty cycle—the percentage of time the signal is HIGH—determines the effective power or, in the case of servos, the position.

Micro servo motors, like the classic RC servos, are designed to interpret a specific PWM protocol. Inside the servo, a control circuit reads the incoming pulse width (the duration of the HIGH portion) and compares it to an internal potentiometer that tracks the output shaft’s position. The difference drives a motor to rotate until the feedback matches the commanded pulse width. The result? A precise angular position proportional to the pulse width.

The Standard Micro Servo PWM Parameters

Before we dive into the formula, let’s establish the baseline. Most micro servos operate with:

  • PWM Frequency: 50 Hz (period = 20 milliseconds)
  • Pulse Width Range: Typically 1 ms to 2 ms
  • Corresponding Angle Range: 0° to 180° (or sometimes 0° to 90° or 0° to 270°, depending on the model)

For a standard SG90 micro servo, a 1 ms pulse commands 0°, a 1.5 ms pulse commands 90°, and a 2 ms pulse commands 180°. These values are not arbitrary—they are rooted in the servo’s internal design and the historical RC servo standard.

The Core PWM Duty Cycle Formula

The duty cycle (D) is defined as:

[ D = \frac{T{\text{on}}}{T{\text{period}}} \times 100\% ]

Where: - ( T{\text{on}} ) = pulse width (time the signal is HIGH) - ( T{\text{period}} ) = total period of one PWM cycle (1 / frequency)

For a 50 Hz signal, the period is 20 ms. So, for a 1 ms pulse:

[ D = \frac{1 \text{ ms}}{20 \text{ ms}} \times 100\% = 5\% ]

Similarly, a 2 ms pulse yields a 10% duty cycle. This means that the duty cycle for a micro servo’s full range spans from 5% to 10%—a surprisingly narrow window. But why such a small range? Because the servo’s control circuit is designed to detect changes in the absolute pulse width, not the duty cycle percentage. The duty cycle is just a convenient way to express the pulse width relative to the period.

From Duty Cycle to Angle: The Linear Mapping

The relationship between pulse width and angle is linear for most micro servos. If we assume a perfect linear response, the formula to convert a desired angle (θ) to a pulse width (PW) is:

[ PW = \text{PW}{\text{min}} + \left( \frac{\theta}{\theta{\text{max}}} \times (\text{PW}{\text{max}} - \text{PW}{\text{min}}) \right) ]

Where: - ( \text{PW}{\text{min}} ) = minimum pulse width (e.g., 1 ms for 0°) - ( \text{PW}{\text{max}} ) = maximum pulse width (e.g., 2 ms for 180°) - ( \theta_{\text{max}} ) = maximum angle (e.g., 180°)

For example, to set the servo to 45°:

[ PW = 1 \text{ ms} + \left( \frac{45}{180} \times (2 \text{ ms} - 1 \text{ ms}) \right) = 1.25 \text{ ms} ]

Then, the duty cycle for this pulse width is:

[ D = \frac{1.25 \text{ ms}}{20 \text{ ms}} \times 100\% = 6.25\% ]

So, a 6.25% duty cycle corresponds to 45°. This linear mapping is the backbone of servo control algorithms, from Arduino’s Servo.write() to custom PWM generation on microcontrollers.

Why the Duty Cycle Formula Matters for Micro Servo Performance

You might think, “Just send a 5% to 10% duty cycle, and the servo will follow.” But real-world micro servos are finicky. The duty cycle formula is your anchor, but several factors can throw off the relationship.

Frequency Mismatch and Its Effects

If your PWM frequency deviates from 50 Hz, the period changes, and the same pulse width will yield a different duty cycle. For instance, at 100 Hz (period = 10 ms), a 1 ms pulse gives a 10% duty cycle. But the servo still expects a 1 ms pulse to command 0°. The duty cycle percentage is irrelevant to the servo—it only cares about the absolute pulse width. However, if you’re generating PWM with a microcontroller timer, you need to ensure the frequency is correct, or the pulse width calculation might be off.

Example: On an Arduino Uno, the analogWrite() function operates at 490 Hz (or 980 Hz on some pins). Using it to drive a servo directly would produce pulse widths that are too short relative to the 50 Hz standard, causing erratic behavior. That’s why the Arduino Servo library uses a dedicated timer to generate precise 50 Hz pulses.

Duty Cycle Resolution and Jitter

Micro servos have finite resolution. A typical 8-bit PWM generator (256 steps) over a 20 ms period gives a step size of about 78 µs. With a pulse width range of 1 ms, that’s roughly 12.8 steps for the full 180°—about 14° per step. This is coarse and leads to visible jitter or stepping. Higher-resolution PWM (e.g., 16-bit) reduces this to sub-degree precision.

The duty cycle formula here helps you calculate the smallest incremental angle you can command:

[ \text{Step Angle} = \frac{\theta_{\text{max}}}{\text{Resolution in steps}} ]

For a 12-step resolution over 180°, each step is 15°. If you need smoother motion, you must increase the PWM resolution or use a dedicated servo controller with microsecond-level precision.

Non-Linearity at the Extremes

Not all micro servos behave linearly at the edges of their range. Some servos have a dead band near 0° and 180° where the pulse width response flattens. The duty cycle formula assumes a perfect line, but in practice, you might need to calibrate the PW_min and PW_max values. For example, an SG90 might actually respond from 0.5 ms to 2.5 ms, or the center may drift with temperature. Always check the datasheet or experimentally determine the usable pulse width range.

Practical Applications: Tuning the Duty Cycle for Micro Servos

Let’s move from theory to hands-on. Here are three scenarios where understanding the duty cycle formula directly impacts your project.

Scenario 1: Driving a Servo with a Custom Microcontroller

Suppose you’re using an STM32 or ESP32 and want to generate PWM manually. You need to set the timer’s auto-reload value (ARR) and compare value (CCR) to produce the correct pulse width.

For a 50 Hz signal on a timer running at 80 MHz: - Timer prescaler = 80 (to get 1 MHz timer clock) - ARR = 20,000 (to get 20 ms period) - For a 1.5 ms pulse (90°): CCR = 1500

The duty cycle in this context is:

[ D = \frac{CCR}{ARR} \times 100\% = \frac{1500}{20000} \times 100\% = 7.5\% ]

But more importantly, you’ve directly set the pulse width to 1.5 ms. The duty cycle formula is just a sanity check—the real work is in the timer configuration.

Scenario 2: Using a PWM Driver Like the PCA9685

The PCA9685 is a 16-channel, 12-bit PWM driver popular for controlling multiple micro servos. It operates at a default frequency of 200 Hz, but you can adjust it to 50 Hz by setting the prescale register. The driver uses a 12-bit counter (0 to 4095) for each channel.

To get a 1 ms pulse at 50 Hz: - Period = 20 ms - Counter range = 4096 steps - Steps for 1 ms = (1 ms / 20 ms) × 4096 = 204.8 ≈ 205

So, you write 205 to the ON and OFF registers. The duty cycle is:

[ D = \frac{205}{4096} \times 100\% \approx 5\% ]

This matches the 5% duty cycle we calculated earlier. The PCA9685 abstracts away the timer math, but the duty cycle formula remains the foundation.

Scenario 3: Soft PWM with Bit-Banging

In resource-constrained systems, you might bit-bang PWM using delay loops. For example, on an 8-bit PIC or AVR without hardware PWM, you can toggle a pin HIGH, wait for the pulse width, then toggle LOW and wait for the remainder of the period.

The duty cycle formula becomes a timing guide: - Set pin HIGH - Delay for pulse_width microseconds - Set pin LOW - Delay for (20000 - pulse_width) microseconds (for 50 Hz)

If your delay function is inaccurate, the duty cycle drifts, and the servo responds erratically. This is where the formula helps you verify timing with an oscilloscope.

Advanced Considerations: Beyond the Basic Formula

Once you master the simple duty cycle-to-angle mapping, you can explore more sophisticated control strategies.

Using Duty Cycle for Speed Control

Some micro servos support continuous rotation if you send a specific pulse width (e.g., 1.5 ms for stop, <1.5 ms for one direction, >1.5 ms for the other). The duty cycle formula still applies, but now the pulse width controls speed and direction rather than position. For a continuous rotation servo, the duty cycle range might be 5% to 10%, but the mapping is non-linear—closer to the center yields slower speeds.

Duty Cycle and Torque

The duty cycle also affects the servo’s holding torque. At the extremes (near 0° or 180°), the internal feedback loop may struggle to maintain position, especially under load. The duty cycle formula doesn’t directly model torque, but it’s related to the pulse width’s ability to drive the motor. A wider pulse (higher duty cycle) generally provides more power, but the servo’s internal current limit and gear ratio are the real constraints.

Temperature Drift and Calibration

Over time, the servo’s internal potentiometer can drift, shifting the pulse width-to-angle relationship. You might find that a 1.5 ms pulse no longer centers the servo at 90°. To compensate, you can adjust the PW_min and PW_max values in your code. The duty cycle formula remains valid, but the constants change. A calibration routine that sweeps the servo and measures the actual angle can update these values dynamically.

Common Pitfalls When Using the Duty Cycle Formula

Even experienced engineers trip up on these details.

Pitfall 1: Confusing Duty Cycle with Pulse Width

The duty cycle is a percentage, but the servo cares about the absolute pulse width. If you change the PWM frequency, the duty cycle for the same pulse width changes. Always think in terms of microseconds, not percentages, when programming.

Pitfall 2: Ignoring the Servo’s Internal Dead Band

Most micro servos have a dead band—a small range of pulse widths where the servo doesn’t respond. For an SG90, this might be ±5 µs around the target. The duty cycle formula gives you a theoretical value, but the actual servo might need a slightly different pulse to overcome the dead band. Adding a small offset (e.g., 10 µs) can improve accuracy.

Pitfall 3: Overlooking Power Supply Limitations

Micro servos draw significant current during motion (200-500 mA for an SG90). If your PWM signal is generated from a microcontroller pin, the duty cycle formula is fine, but the servo’s power supply must be separate. A common mistake is to power the servo from the microcontroller’s 5V pin, causing brownouts that corrupt the PWM signal. The duty cycle calculation is correct, but the hardware implementation fails.

Real-World Example: Building a Multi-Servo Arm

Let’s tie everything together with a practical example. You’re building a robotic arm with three micro servos: shoulder, elbow, and wrist. Each servo needs a different pulse width for a given arm position. Using the duty cycle formula, you can compute the required PWM values.

  1. Determine the angle for each joint. For the shoulder, you want 30°; for the elbow, 60°; for the wrist, 90°.
  2. Convert angles to pulse widths. Using the linear mapping:
    • Shoulder: PW = 1 ms + (30/180) × 1 ms = 1.1667 ms
    • Elbow: PW = 1 ms + (60/180) × 1 ms = 1.3333 ms
    • Wrist: PW = 1 ms + (90/180) × 1 ms = 1.5 ms
  3. Convert pulse widths to duty cycles (assuming 50 Hz):
    • Shoulder: D = (1.1667 / 20) × 100% = 5.8335%
    • Elbow: D = (1.3333 / 20) × 100% = 6.6665%
    • Wrist: D = (1.5 / 20) × 100% = 7.5%

Now, when you program your microcontroller, you set the timer compare values to these pulse widths. The duty cycle formula confirms that your values are within the 5-10% range. If you’re using a library like Servo.h, you can directly write the angle, and the library handles the math internally. But understanding the formula lets you debug when the arm doesn’t move as expected—for example, if the shoulder servo jitters, you might check if the pulse width is too close to the dead band.

Final Thoughts on the PWM Duty Cycle Formula

The PWM duty cycle formula is more than just a calculation—it’s the bridge between digital logic and physical motion. For micro servo motors, mastering this formula means you can predict, tune, and troubleshoot your control system with confidence. Whether you’re dealing with a single servo on an Arduino or a dozen on a PCA9685, the principles remain the same: know your pulse width range, respect the frequency, and always account for real-world non-idealities.

So next time you hook up a micro servo, take a moment to appreciate the math behind the motion. That 5% to 10% duty cycle window holds the key to precise, repeatable angular control—and now you know exactly how to unlock it.

Copyright Statement:

Author: Micro Servo Motor

Link: https://microservomotor.com/pulse-width-modulation-pwm-control/pwm-duty-cycle-formula.htm

Source: Micro Servo Motor

The copyright of this article belongs to the author. Reproduction is not allowed without permission.

About Us

Lucas Bennett avatar
Lucas Bennett
Welcome to my blog!

Tags