Skip to content
Home » Embedded Systems » PWM (Pulse Width Modulation) in Embedded Systems

PWM (Pulse Width Modulation) in Embedded Systems

PWM Pulse Width Modulation featured image with dark green background, HARDWARE badge, PWM icon in green circle, and LED Dimming Motors and Servo Control subtitle by nerdyelectronics.com
Embedded Systems Learning Path
Part 56 of 129View Full Path →

KEY TAKEAWAYS

  • PWM generates a square wave with variable duty cycle to control average power delivered to a load
  • Applications include motor speed control, LED dimming, servo positioning, and audio generation
  • Duty cycle (0-100%) determines the output level; frequency determines the switching rate
  • Hardware PWM peripherals in microcontrollers generate precise waveforms without CPU overhead

What is PWM?

Pulse Width Modulation (PWM) is a technique that creates a square wave signal where the proportion of ON time (high) versus OFF time (low) is controlled precisely. This ratio is called the duty cycle.
    100% Duty Cycle (Always ON):
    ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

    75% Duty Cycle:
    ‾‾‾‾‾‾‾‾‾‾‾‾|____|‾‾‾‾‾‾‾‾‾‾‾‾|____|

    50% Duty Cycle:
    ‾‾‾‾‾‾‾‾|________|‾‾‾‾‾‾‾‾|________|

    25% Duty Cycle:
    ‾‾‾‾|____________|‾‾‾‾|____________|

    0% Duty Cycle (Always OFF):
    _________________________________
Duty Cycle = (ON time / Total period) x 100%A GPIO pin can only be HIGH (3.3V/5V) or LOW (0V). It cannot output 1.5V directly. But by rapidly switching between HIGH and LOW, the average voltage equals the duty cycle percentage of the supply voltage.
Average Voltage = Duty Cycle x V_supply

Examples (3.3V supply):
  25% duty cycle = 0.825V average
  50% duty cycle = 1.65V average
  75% duty cycle = 2.475V average

PWM Parameters

Frequency

The PWM frequency determines how many ON-OFF cycles occur per second. It is measured in Hertz (Hz).
ApplicationTypical Frequency
LED dimming500 Hz – 5 kHz (above flicker perception)
Servo motors50 Hz (20ms period)
DC motor speed10 kHz – 50 kHz (above audible range)
Audio generationVaries with tone
Switching regulators100 kHz – 2 MHz
If the frequency is too low for motors, you hear an audible whine. If it is too low for LEDs, you see flickering.

Resolution

PWM resolution determines how finely you can control the duty cycle. With 8-bit resolution, you have 256 steps (0-255). With 16-bit, you have 65,536 steps.

Common PWM Applications

1. LED Brightness Control

// Arduino example
#define LED_PIN 9

void setup() {
    pinMode(LED_PIN, OUTPUT);
}

void loop() {
    // Fade in
    for (int brightness = 0; brightness <= 255; brightness++) {
        analogWrite(LED_PIN, brightness);
        delay(5);
    }
    // Fade out
    for (int brightness = 255; brightness >= 0; brightness--) {
        analogWrite(LED_PIN, brightness);
        delay(5);
    }
}

2. DC Motor Speed Control

PWM controls motor speed by varying the average voltage. A motor driver (like L298N or L293D) is needed between the MCU and the motor.
// Motor speed control
#define MOTOR_PWM_PIN  5
#define MOTOR_DIR_PIN  6

void set_motor_speed(uint8_t speed, uint8_t direction) {
    digitalWrite(MOTOR_DIR_PIN, direction);
    analogWrite(MOTOR_PWM_PIN, speed);  // 0 = stop, 255 = full speed
}

// Run motor at half speed forward
set_motor_speed(128, HIGH);

// Run motor at full speed reverse
set_motor_speed(255, LOW);

3. Servo Motor Control

Servo motors expect a specific PWM signal:
  • Period: 20ms (50 Hz)
  • Pulse width: 1ms (0 degrees) to 2ms (180 degrees)
Servo position is determined by pulse width:

  0 degrees:    |‾|_____________________|  (1ms pulse in 20ms period)
  90 degrees:   |‾‾‾|___________________|  (1.5ms pulse)
  180 degrees:  |‾‾‾‾‾|_________________|  (2ms pulse)

4. Buzzer / Tone Generation

By varying the PWM frequency, you can generate different musical tones:
// Generate a 440 Hz tone (note A4)
tone(BUZZER_PIN, 440);
delay(500);
noTone(BUZZER_PIN);

// Simple melody
int notes[] = {262, 294, 330, 349, 392, 440, 494, 523};
for (int i = 0; i < 8; i++) {
    tone(BUZZER_PIN, notes[i]);
    delay(300);
}
noTone(BUZZER_PIN);

5. PWM as a Poor Man’s DAC

With a low-pass filter (RC circuit), you can convert PWM to a smooth analog voltage:
  MCU PWM Pin ──[1K Resistor]──┬── Analog Output
                               |
                             [10uF]
                               |
                              GND
The resistor and capacitor smooth out the rapid switching into a steady DC voltage proportional to the duty cycle. This is useful on MCUs without a built-in DAC.

Hardware PWM vs Software PWM

FeatureHardware PWMSoftware PWM
ImplementationBuilt-in timer peripheralGPIO toggling in code/ISR
CPU usageZero (runs independently)High (CPU must toggle pin)
PrecisionVery precise, jitter-freeCan have jitter from interrupts
PinsOnly specific pinsAny GPIO pin
ChannelsLimited by hardware timersUnlimited (but CPU cost)
Always prefer hardware PWM when available. Use software PWM only when you need more channels than the hardware provides.

PWM on Different Platforms

Arduino:
analogWrite(pin, value);  // value: 0-255 (8-bit)
ESP32 (LEDC peripheral):
ledcAttach(pin, frequency, resolution);
ledcWrite(pin, dutyCycle);
STM32 (HAL):
HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_1, pulse_value);

Summary

PWM is one of the most versatile tools in embedded systems:
  • Control LED brightness by varying the duty cycle
  • Control DC motor speed through a motor driver
  • Position servo motors with specific pulse widths
  • Generate audio tones by varying frequency
  • Approximate analog output when no DAC is available
The key parameters are frequency (how fast it switches) and duty cycle (the ratio of ON to OFF time). Choose the right frequency for your application, prefer hardware PWM over software PWM, and remember that the average voltage equals the duty cycle times the supply voltage.

Leave a Reply

Your email address will not be published. Required fields are marked *