0
0
Power-electronicsHow-ToBeginner · 4 min read

How to Control Motor Speed Using PWM in Embedded C

To control motor speed using PWM in Embedded C, generate a PWM signal with a variable duty cycle where the duty cycle percentage controls the motor speed. Use a timer peripheral to create the PWM waveform and adjust the duty cycle value in your code to increase or decrease speed.
📐

Syntax

To control motor speed using PWM, you typically configure a timer to generate a PWM signal. The key parts are:

  • Timer setup: Initialize the timer in PWM mode.
  • Duty cycle: Set the timer's compare register to control the ON time of the PWM signal.
  • Output pin: Connect the PWM output pin to the motor driver input.

The duty cycle value ranges from 0 (motor off) to the timer's max value (motor full speed).

c
void PWM_Init(void) {
    // Configure timer registers for PWM mode
    // Set PWM frequency
    // Configure output pin as PWM output
}

void PWM_SetDutyCycle(uint16_t duty) {
    // Set timer compare register to duty
}
💻

Example

This example shows how to initialize PWM and change motor speed by adjusting the duty cycle on a microcontroller timer.

c
#include <stdint.h>
#include <stdio.h>

// Simulated registers for example
uint16_t TIMER_TOP = 1000; // Max timer count for PWM period
uint16_t TIMER_COMPARE = 0; // Compare register for duty cycle

void PWM_Init(void) {
    // Normally hardware setup here
    printf("PWM Initialized with period %d\n", TIMER_TOP);
}

void PWM_SetDutyCycle(uint16_t duty) {
    if (duty > TIMER_TOP) duty = TIMER_TOP;
    TIMER_COMPARE = duty;
    printf("Duty cycle set to %d/%d (%.1f%%)\n", duty, TIMER_TOP, (duty*100.0)/TIMER_TOP);
}

int main() {
    PWM_Init();
    
    // Set motor speed to 25%
    PWM_SetDutyCycle(250);

    // Increase motor speed to 75%
    PWM_SetDutyCycle(750);

    // Stop motor
    PWM_SetDutyCycle(0);

    return 0;
}
Output
PWM Initialized with period 1000 Duty cycle set to 250/1000 (25.0%) Duty cycle set to 750/1000 (75.0%) Duty cycle set to 0/1000 (0.0%)
⚠️

Common Pitfalls

  • Incorrect timer configuration: Not setting the timer in PWM mode or wrong frequency causes no PWM output.
  • Duty cycle out of range: Setting duty cycle higher than timer max causes unexpected behavior.
  • Pin not configured as output: PWM signal won't appear if the pin is not set as output.
  • Ignoring motor driver requirements: Some motors need specific driver circuits; PWM alone may not work.
c
/* Wrong: Duty cycle exceeds timer max */
PWM_SetDutyCycle(2000); // If TIMER_TOP is 1000, this is invalid

/* Correct: Clamp duty cycle to max */
void PWM_SetDutyCycle(uint16_t duty) {
    if (duty > TIMER_TOP) duty = TIMER_TOP;
    TIMER_COMPARE = duty;
}
📊

Quick Reference

StepDescription
1. Initialize TimerSet timer to PWM mode with desired frequency
2. Configure Output PinSet microcontroller pin as PWM output
3. Set Duty CycleAdjust compare register to control motor speed
4. Connect Motor DriverUse PWM output to control motor driver input
5. Adjust SpeedChange duty cycle value to increase/decrease speed

Key Takeaways

Use a timer configured in PWM mode to generate a signal controlling motor speed.
Adjust the PWM duty cycle to change the motor speed smoothly.
Always ensure the duty cycle value stays within the timer's valid range.
Configure the output pin correctly to output the PWM signal.
Check motor driver requirements to ensure proper PWM control.