Introduction to PWM
Pulse Width Modulation (PWM) is a technique by which the width of a pulse is varied while keeping the frequency constant.
Why do we need to do this? Let’s take an example of controlling DC motor speed, more the Pulse width more the speed. Also, there are applications like controlling light intensity by PWM.
A period of a pulse consists of an ON cycle (5V) and an OFF cycle (0V). The fraction for which the signal is ON over a period is known as the duty cycle.
Duty Cycle (In %) =
E.g. Consider a pulse with a period of 10ms which remains ON (high) for 2ms.The duty cycle of this pulse will be
D = 2ms / 10ms = 20%
Through the PWM technique, we can control the power delivered to the load by using the ON-OFF signal.
Pulse Width Modulated signals with different duty cycle are shown below
AVR ATmega PWM
ATmega has an inbuilt PWM unit. As we know, ATmega has 3 Timers T0, T1, and T2 which can be used for PWM generation. Mainly there are two modes in PWM.
- Fast PWM
- Phase correct PWM
We need to configure the Timer Register for generating PWM. PWM output will be generated on the corresponding Timer’s output compare pin (OCx).
Configuring Timer0 for PWM generation
It is simple to configure PWM mode in Timer. We just need to set some bits in the TCCR0 register.
TCCR0: Timer Counter Control Register 0
Bit 7- FOC0: Force compare match
Write only bit, which can be used while generating a wave. Writing 1 to this bit will force the wave generator to act as if a compare match has occurred.
Bit 6, 3 - WGM00, WGM01: Waveform Generation Mode
WGM00 | WGM01 | Timer0 mode selection bit |
---|---|---|
0 | 0 | Normal |
0 | 1 | CTC (Clear timer on Compare Match) |
1 | 0 | PWM, Phase correct |
1 | 1 | Fast PWM |
Bit 5:4 - COM01:00:
- When WGM00: WGM01= 11 i.e. Fast PWM. Compare Output Mode
waveform generator on OC0 pin
COM01 | COM00 | Mode Name | Description |
---|---|---|---|
0 | 0 | Disconnected | The normal port operation, OC0 disconnected |
0 | 1 | Reserved | Reserved |
1 | 0 | Non-inverted | Clear OC0 on compare match, set OC0 at TOP |
1 | 1 | Inverted PWM | Set OC0 on compare match, clear OC0 at TOP |
2. When WGM00: WGM01= 10 i.e. Phase correct PWM. Compare Output Mode
waveform generator on OC0 pin
COM01 | COM00 | Description |
---|---|---|
0 | 0 | The normal port operation, OC0 disconnected |
0 | 1 | Reserved |
1 | 0 | Clear OC0 on compare match when up-counting, set OC0 on compare match when down-counting |
1 | 1 | Set OC0 on compare match when up-counting, Clear OC0 on compare match when down-counting |
Bit 2:0 - CS02:CS00: Clock Source Select
These bits are used to select a clock source. When CS02: CS00 = 000, then timer is stopped. As it gets a value between 001 to 101, it gets a clock source and starts as the timer.
CS02 | CS01 | CS00 | Description |
---|---|---|---|
0 | 0 | 0 | No clock source (Timer / Counter stopped) |
0 | 0 | 1 | clk (no pre-scaling) |
0 | 1 | 0 | clk / 8 |
0 | 1 | 1 | clk / 64 |
1 | 0 | 0 | clk / 256 |
1 | 0 | 1 | clk / 1024 |
1 | 1 | 0 | External clock source on T0 pin. clock on falling edge |
1 | 1 | 1 | External clock source on T0 pin. clock on rising edge. |
Fast PWM mode
To set Fast PWM mode, we have to set WGM00: 01= 11. To generate a PWM waveform on the OC0 pin, we need to set COM01:00= 10 or 11.
COM01:00= 10 will generate Noninverting PWM output waveform and COM01:00= 11 will generate Inverting PWM output waveform. See fig.
void PWM_init()
{
/*set fast PWM mode with non-inverted output*/
TCCR0 = (1<<WGM00) | (1<<WGM01) | (1<<COM01) | (1<<CS00);
DDRB|=(1<<PB3); /*set OC0 pin as output*/
}
Setting Duty cycle: we have to load value in the OCR0 register to set the duty cycle.
255 value for 100% duty cycle and 0 for 0% duty cycle. Accordingly, if we load value 127 in OCR0, the Duty cycle will be 50%.
The advantage of using PWM mode in AVR is that it is an inbuilt hardware unit for waveform generation and once we set the PWM mode and duty cycle, this unit starts generating PWM and the controller can do other work.
Example
Control LED brightness using Fast PWM.
/*
AVR ATmega16 PWM to control LED brightness
http://www.electronicwings.com
*/
#define F_CPU 8000000UL
#include "avr/io.h"
#include <util/delay.h>
void PWM_init()
{
/*set fast PWM mode with non-inverted output*/
TCCR0 = (1<<WGM00) | (1<<WGM01) | (1<<COM01) | (1<<CS00);
DDRB|=(1<<PB3); /*set OC0 pin as output*/
}
int main ()
{
unsigned char duty;
PWM_init();
while (1)
{
for(duty=0; duty<255; duty++)
{
OCR0=duty; /*increase the LED light intensity*/
_delay_ms(8);
}
for(duty=255; duty>1; duty--)
{
OCR0=duty; /*decrease the LED light intensity*/
_delay_ms(8);
}
}
}
Phase correct PWM mode
To set Phase correct PWM, we just have to set the TCCRO register as follows.
We can set the output waveform as inverted or non-inverted. See fig.
TCCR0 = (1<<WGM00) | (1<<COM01) | (1<<CS00);
Similarly, we can set PWM output on the other three OCx pins using Timer1 and Timer2.
PWM output is somehow close to the Analog output. We can use it as analog output for generating sine wave, audio signals, etc. it is also referred to as DDS.
Video
Components Used |
||
---|---|---|
ATmega 16 ATmega 16 |
X 1 | |
Atmega32 Atmega32 |
X 1 | |
LED 5mm LED 5mm |
X 1 | |
Breadboard Breadboard |
X 1 |