Embedded C Program to Fade LED Using PWM
for (int duty=0; duty<=255; duty++) { set_pwm_duty(duty); delay(); }.Examples
How to Think About It
Algorithm
Code
#include <avr/io.h> #include <util/delay.h> void pwm_init() { DDRB |= (1 << PB1); // Set PB1 as output (OC1A pin) TCCR1A |= (1 << COM1A1) | (1 << WGM10); // PWM, Phase Correct, 8-bit TCCR1B |= (1 << CS11); // Prescaler 8 } void set_pwm_duty(uint8_t duty) { OCR1A = duty; // Set duty cycle } int main(void) { pwm_init(); while (1) { for (uint8_t duty = 0; duty <= 255; duty++) { set_pwm_duty(duty); _delay_ms(10); } for (uint8_t duty = 255; duty > 0; duty--) { set_pwm_duty(duty); _delay_ms(10); } } return 0; }
Dry Run
Let's trace the fading loop increasing duty cycle from 0 to 3 for simplicity.
Initialize PWM
PWM hardware set, PB1 pin output enabled
Set duty cycle to 0
OCR1A = 0, LED off
Increase duty cycle to 1
OCR1A = 1, LED slightly on
Increase duty cycle to 2
OCR1A = 2, LED brighter
Increase duty cycle to 3
OCR1A = 3, LED brighter still
| Duty Cycle (OCR1A) | LED Brightness |
|---|---|
| 0 | Off |
| 1 | Dim |
| 2 | Brighter |
| 3 | Brighter |
Why This Works
Step 1: PWM Initialization
We set the timer to PWM mode and configure the output pin so the hardware can generate PWM signals automatically.
Step 2: Duty Cycle Control
Changing the OCR1A register changes the duty cycle, which controls how long the LED stays on in each PWM cycle.
Step 3: Fading Effect
By increasing and decreasing the duty cycle slowly with delays, the LED brightness appears to fade smoothly.
Alternative Approaches
#include <avr/io.h> #include <util/delay.h> #define LED_PIN PB0 void software_pwm(uint8_t duty) { PORTB |= (1 << LED_PIN); _delay_us(duty * 10); PORTB &= ~(1 << LED_PIN); _delay_us((255 - duty) * 10); } int main(void) { DDRB |= (1 << LED_PIN); while(1) { for(uint8_t duty=0; duty<=255; duty++) { software_pwm(duty); } for(uint8_t duty=255; duty>0; duty--) { software_pwm(duty); } } return 0; }
// Pseudocode: output analog voltage to LED via DAC // Increase DAC output gradually to fade LED // Decrease DAC output gradually to dim LED
Complexity: O(n) time, O(1) space
Time Complexity
The program runs a loop increasing and decreasing duty cycle with fixed delay steps, so time grows linearly with the number of steps.
Space Complexity
Uses a few variables and hardware registers, so space usage is constant.
Which Approach is Fastest?
Hardware PWM is fastest and most efficient, software PWM wastes CPU cycles and is less precise.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Hardware PWM | O(n) | O(1) | Smooth, efficient fading |
| Software PWM | O(n) | O(1) | Simple hardware, less efficient |
| DAC Analog Output | O(n) | O(1) | Smooth analog control, complex hardware |