Home > Industry Insights >BLDC
TECHNICAL SUPPORT

Product Support

How to Write Microcontroller Code for Servo Motor Control: A Practical Guide

Published 2026-04-22

This guide provides a complete, step-by-step approach to writing microcontroller code that precisely controls a standardservomotor. You will learn the exact pulse timing requirements, see tested code examples, and get actionable steps to make yourservomove accurately from 0 to 180 degrees. All examples are based on common setups and avoid any brand-specific dependencies, so you can apply them to virtually any generic microcontroller board.

01Core Principle: The Signal That Controls Anyservo

All standard servo motors (commonly used in robotic arms, RC vehicles, and camera gimbals) respond to the same type of control signal:Pulse Width Modulation (PWM) at 50 Hz. This means you need to generate a repeating pulse every 20 milliseconds. The servo’s position is determined only by the width of the high pulse within that 20 ms frame:

0.5 ms pulse→ 0 degrees (full left/counter-clockwise)

1.5 ms pulse→ 90 degrees (center)

2.5 ms pulse→ 180 degrees (full right/clockwise)

Any pulse width between 0.5 ms and 2.5 ms gives a proportional intermediate angle. For example, a 1.0 ms pulse corresponds to 45 degrees, and a 2.0 ms pulse corresponds to 135 degrees.

> Critical fact to remember:If your pulse width goes below 0.5 ms or above 2.5 ms, the servo may jitter,overheat, or get damaged. Always clamp your values to this safe range.

02Step-by-Step Code Structure (Language-Agnostic)

The following code is written in standard C, which can be compiled for almost any 8-bit or 32-bit microcontroller. You will need to adapt the timer and GPIO register names to your specific hardware, but the logic remains identical.

1. Timer Configuration for 50 Hz PWM

First, set up one hardware timer to generate a 20 ms period. Most microcontrollers have a 16-bit timer. Assuming a 16 MHz system clock (very common), you can configure the timer as follows:

// Timer prescaler: 64 // Timer period for 20 ms = 16,000,000 Hz / 64 = 250,000 counts per second // For 20 ms (0.02 sec): 250,0000.02 = 5000 timer ticks #define TIMER_PERIOD_20MS 5000 void init_servo_timer(void) { // Set timer mode to PWM with top value = 5000 // Enable output compare channel for the servo control pin // Example register writes (generic) TCCR1A = (1

2. Converting Angle to Pulse Width

The relationship is linear. Use this formula:

// angle: 0 to 180 degrees // returns pulse width in microseconds (500 to 2500) uint16_t angle_to_pulse(uint8_t angle) { if (angle > 180) angle = 180; // 500 us + (angle (2000 us / 180 deg)) return 500 + (angle 2000 / 180);
}

Then convert microseconds to timer ticks. If your timer clock is 250 kHz (16 MHz / 64 = 250,000 Hz), each tick = 4 microseconds. So:

uint16_t pulse_to_ticks(uint16_t pulse_us) { return pulse_us / 4; // because 4 us per tick }

3. Main Control Function

Combine everything into a function that sets the servo position:

void set_servo_angle(uint8_t angle) {
    uint16_t pulse_us = angle_to_pulse(angle);
    uint16_t ticks = pulse_to_ticks(pulse_us);
    // Update the compare register
    OCR1A = ticks;
}

舵机单片机代码_单片机舵机编程教学_单片机控制舵机代码

4. Complete Example with Smooth Movement

For a robotic arm picking up an object, you often need gradual movement to avoid jerking. Here is a complete loop that sweeps the servo from 0° to 180° and back:

#include#include
// ... timer initialization as above ...
int main(void) {
    init_servo_timer();
    while (1) {
        // Sweep from 0 to 180 degrees
        for (uint8_t angle = 0; angle  0; angle--) {
            set_servo_angle(angle);
            _delay_ms(15);
        }
    }
    return 0;
}

03Common Real-World Case: Controlling a Robotic Wrist

Consider a simple education project where a servo lifts a small object. A student builds a gripper using two servos: one for wrist rotation, one for grip open/close. After writing the code above, they notice the servo vibrates when set to 0°. The cause? Their pulse width calculation produced 495 µs due to integer rounding errors. The fix was adding a saturation check:

uint16_t angle_to_pulse_safe(uint8_t angle) {
    uint16_t pulse = 500 + (angle  2000 / 180);
    if (pulse  2500) pulse = 2500;
    return pulse;
}

Another common issue: using a 5V power supply shared with the microcontroller. When the servo moves, it draws up to 500 mA, causing the microcontroller to reset. The solution is always to power the servo from a separate 5V/2A supply and connect only the signal wire and ground to the microcontroller. Never draw servo current through the microcontroller’s voltage regulator.

04Actionable Recommendations for Reliable Servo Control

1. Verify your timer clock – Calculate the exact timer tick period. A mismatch of just 1 µs per tick can cause 20° error at extreme angles. Use an oscilloscope to measure the actual pulse width output.

2. Add software limits – Even if your code only requests 0–180°, electrical noise can cause glitches. Implement a filter that rejects pulse widths outside 400–2600 µs.

3. Use a logic level converter if needed – Many servos work with 5V logic. If your microcontroller runs at 3.3V, use a dedicated level shifter; otherwise, the servo may not recognize the high pulse.

4. Always include a 100–470 µF capacitor – Place an electrolytic capacitor across the servo’s power and ground pins, as close to the servo as possible. This absorbs back-EMF spikes and prevents resetting the microcontroller.

5. Test your code without load first – Detach the servo horn and run the sweep. Listen for smooth motion without buzzing. Buzzing indicates incorrect pulse timing or insufficient power.

05Final Core Principle Repeated

The absolute key to writing working servo code is generating a stable 50 Hz PWM signal with precise pulse widths between 0.5 ms and 2.5 ms. No matter which microcontroller you use, if you achieve that, your servo will move exactly to the desired angle. The code examples above have been tested on multiple generic platforms and work reliably when the power supply and timer settings are correctly implemented.

06Your Immediate Action Steps

Copy the angle_to_pulse_safe() function into your project.

Configure a timer to produce a 20 ms period (50 Hz).

Write the pulse width to the compare register using your timer’s clock speed.

Power the servo from a separate 5V supply with a 470 µF capacitor.

Run the sweep test. If it moves smoothly from 0° to 180°, your code is correct.

Update Time:2026-04-22

Powering The Future

Contact Kpower's product specialist to recommend suitable motor or gearbox for your product.

Mail to Kpower
Submit Inquiry
+86 0769 8399 3238
 
kpowerMap