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
| Step | Description |
|---|---|
| 1. Initialize Timer | Set timer to PWM mode with desired frequency |
| 2. Configure Output Pin | Set microcontroller pin as PWM output |
| 3. Set Duty Cycle | Adjust compare register to control motor speed |
| 4. Connect Motor Driver | Use PWM output to control motor driver input |
| 5. Adjust Speed | Change 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.