Posted by on Jan 7, 2012 in Atmel AVR, Microcontrollers | 163 comments

# AVR Timers – PWM Mode – Part II

Hello folks! Long time no see! :)

In my previous post, we have discussed the basic concepts of PWM. Let’s summarize it first:

• PWM stands for Pulse Width Modulation.
• It can be generated by comparing predetermined waveform with a reference voltage level or by making simple analog circuits.
• Duty Cycle of a PWM waveform is given by the following relation.
• There are three modes of PWM operation – Fast PWM, Phase Correct PWM and Frequency and Phase Correct PWM
• How to choose timer, operation mode and compare output mode for generating the desired PWM.
So now, without much hassle, let’s see how to implement it using the AVR microcontrollers. Before we proceed, I suggest you to go through my previous posts on Timers and PWM.

# Problem Statement

Let us take a problem statement. We need to generate a 50 Hz PWM signal having 45% duty cycle.

### Analysis

Given that

Frequency = 50 Hz

In other words, the time period, T

T = T(on) + T(off) = 1/50 = 0.02 s = 20 ms

Also, given that

Duty Cycle = 45%

Thus, solving according to equation given above, we get

T(on)  = 9 ms
T(off) = 11 ms

Now, this can be achieved in two ways:

1. Use Timer in CTC Mode
2. Use Timer in PWM Mode

# Methodology – CTC Mode

Okay, so I won’t be writing any code here (just the pseudo code). I assume that after reading my previous posts, you are smart enough to write one yourself! We will discuss only the concepts.

Firstly, choose a suitable timer. For this application, we can choose any of the three timers available in ATMEGA32. Choose a suitable prescaler. Then set up the timer and proceed as usual. The catch lies here is that you need to update the compare value of OCRx register everytime. One such way is discussed in the pseudo code given below.

This is analogous to the traditional LED flasher, except the fact that the on and off times are different.

### Pseudo Code

#include <avr/io.h>
#include <avr/interrupt.h>

uint8_t count = 0;               // global counter

// initialize timer, interrupt and variable
void timerX_init()
{
// set up timerX with suitable prescaler and CTC mode
// initialize counter
// initialize compare value
// enable compare interrupt
// enable global interrupts
}

// process the ISR that is fired
ISR (TIMERx_COMPA_vect)
{
// do whatever you want to do here
// say, increment the global counter
count++;

// check for the global counter
// if count == odd, delay required = 11 ms
// if count == even, delay required = 9 ms
// thus, the value of the OCRx should be constantly updated
if (count % 2 == 0)
OCRx = 9999;      // calculate and substitute appropriate value
else
OCRx = 10999;     // calculate and substitute appropriate value
}

int main(void)
{
// initialize the output pin, say PC0
DDRC |= (1 << 0);

// initialize timerX
timerX_init();

// loop forever
while(1)
{
// do nothing

}
}

Now this is one method. And it’s very inefficient. You can increase its efficiency by writing a better C code (syntax-wise), however the concept remains the same. If you have any other method/concept, you are most welcome to share it here! :)

UPDATE: One of the readers of maxEmbedded, “coolpales” has written this code, and it worked for him.

Please note that this code not tested yet! So, if any of you is trying it out, do post your results here, I would be happy to see them! :)

# Methodology – PWM Mode

Okay, so now lets learn about the PWM mode. The PWM Mode in AVR is hardware controlled. This means that everything, by everything I mean “everything”, is done by the AVR CPU. All you need to do is to initialize and start the timer, and set the duty cycle! Cool, eh?! Let’s learn how!

Here, I have used Timer0 of ATMEGA32 for demonstration. You can choose any other other timer or AVR microcontroller as well. Now let’s have a look at the registers.

## TCCR0 – Timer/Counter0 Control Register

We have come across this register in my Timer0 tutorial. Here, we will learn how to set appropriate bits to run the timer in PWM mode.

TCCR0 Register

We will discuss only those bits which are of interest to us now.

• Bit 6,3 – WGM01:0 – Waveform Generation Mode – These bits can be set to either “00” or “01” depending upon the type of PWM you want to generate. Here’s the look up table.

Waveform Generation Mode Bit Description

• Bit 5,4 – COM01:0 – Compare Match Output Mode – These bits are set in order to control the behavior of Output Compare pin (OC0, pin 4 in ATMEGA32) in accordance with the WGM01:0 bits. The following look up table determine the operations of OC0 pin for Fast PWM mode.

Compare Output Mode, Fast PWM Mode

Now lets have a look at the Fast PWM waveforms. Detailed explanation can be found in my previous tutorial.

Fast PWM

Now let me remind you that the AVR PWM is fully hardware controlled, which means that even the timer compare operation is done by the AVR CPU. All we need to do is to tell the CPU what to do once a match occurs. The COM01:0 pins come into play here. We see that by setting it to “10” or “11”, the output pin OC0 is either set or cleared (in other words, it determines whether the PWM is in inverted mode, or in non-inverted mode).

Similarly for Phase Correct PWM, the look up table and the waveforms go like this.

Compare Output Mode, Phase Correct PWM Mode

Phase Correct PWM

Even here, setting COM01:0 to “10” or “11” determines the behavior of OC0 pin. As shown in the waveforms, there are two instances – one during up-counting, and other during down-counting. The behavior is clearly described in the look up table.

Please note that OC0 is an output pin. Thus, the effects of WGM and COM won’t  come into play unless the DDRx register is set properly. Refer this tutorial for more info.

• Bit 2:0 – CS02:0 – Clock Select Bits – These bits are already discussed in Timer0 tutorial.

## OCR0 – Output Compare Register

We have come across even this register in my Timer0 tutorial. We use this register to store the compare value. But when we use Timer0 in PWM mode, the value stored in it acts as the duty cycle (obviously!). In the problem statement, its given that the duty cycle is 45%, which means

OCR0 = 45% of 255 = 114.75 = 115

And that’s it! Now we are ready to write a code for it! :)

## Edit: Note

The following code discusses how to create a PWM signal of a desired duty cycle. If you wish to change its frequency, you need to alter the TOP value, which can be done using the ICRx register (which is not supported by 8-bit timers). For 16-bit Timer1, it can be varied using ICR1A. I will discuss about this soon when we discuss about servo control.

## Code

So here goes the code. To learn about I/O port operations in AVR, view this. To know about bit manipulations, view this. To learn how to use AVR Studio 5, view this. To learn how this code is structured, view the previous TIMER0 post.

#include <avr/io.h>
#include <util/delay.h>
void pwm_init()
{
// initialize TCCR0 as per requirement, say as follows
TCCR0 |= (1<<WGM00)|(1<<COM01)|(1<<WGM01)|(1<<CS00);

// make sure to make OC0 pin (pin PB3 for atmega32) as output pin
DDRB |= (1<<PB3);
}

void main()
{
uint8_t duty;
duty = 115;       // duty cycle = 45% of 255 = 114.75 = 115

// initialize timer in PWM mode
pwm_init();

// run forever
while(1)
{
OCR0 = duty;
}
}

# Problem Statement

So now, let’s take another problem statement. This one is going to be a more of a practical stuff unlike the previous one!

Let’s take the traditional LED flasher where we need to blink an LED at a particular frequency. But hey, wait, didn’t we discuss it long back in this post (scroll down towards the end)? Hmm, so let’s modify it so as to incorporate PWM. Unlike the traditional LED flasher (where LEDs are either ON or OFF), lets make it glow at the maximum brightness, and then slowly decrease its brightness till it reaches zero, and then again increase its brightness slowly till it becomes maximum.

### Analysis and Code

So how do we do it? Yes, you guessed it right! Decrease the duty cycle slowly from 255 to zero, and then increase it from zero to 255. Depending upon the duty cycle, the voltage applied to the LED varies, and thus the brightness. The following formula gives the relation between voltage and duty cycle.

So here goes the code. I won’t explain it, you can decode it yourself. To learn about I/O port operations in AVR, view this. To know about bit manipulations, view this. To learn how to use AVR Studio 5, view this. To learn how this code is structured, view the previous TIMER0 post.

// program to change brightness of an LED
// demonstration of PWM

#include <avr/io.h>
#include <util/delay.h>

// initialize PWM
void pwm_init()
{
// initialize timer0 in PWM mode
TCCR0 |= (1<<WGM00)|(1<<COM01)|(1<<WGM01)|(1<<CS00);

// make sure to make OC0 pin (pin PB3 for atmega32) as output pin
DDRB |= (1<<PB3);
}

void main()
{
uint8_t brightness;

// initialize timer0 in PWM mode
pwm_init();

// run forever
while(1)
{
// increasing brightness
for (brightness = 0; brightness < 255; ++brightness)
{
// set the brightness as duty cycle
OCR0 = brightness;

// delay so as to make the user "see" the change in brightness
_delay_ms(10);
}

// decreasing brightness
for (brightness = 255; brightness > 0; --brightness)
{
// set the brightness as duty cycle
OCR0 = brightness;

// delay so as to make the user "see" the change in brightness
_delay_ms(10);
}

// repeat this forever
}
}

So here ends my another much awaited and long tutorial! Next up.. Serial Communication! See you around!! :)

And yeah, if you have any suggestions, doubts, constructive criticisms, etc, you are most welcome to drop a note  below! Subscribe to my blog or grab the RSS Feeds to stay updated!

1. Is it possible to use timer in PWM mode 14/15 to make pulse of duty cycle other than 50%.

• What do you mean by ‘PWM mode 14/15’?

• As mention above in your tutorial, there are total 15 waveform generation mode. Is it possible to use either mode 14 or mode 15 to generate pulses of duty cycle other than 50%?

• It should be in a while, but I can’t guarantee that it’ll be anytime soon. We are a little overwhelmed these days with the amount of work that needs to be done here.

2. Sir,
i have trying to genrate pwm for led…using ur above example code…in which we assign the ocr0 timer register….but when i run the programme…only voltage is varies….due to brightness of led changes….but i thought that led will blink becoz it has on time and off time…but this is not happening…led is continuously running…why this is so???
thank u

• Dear Shrikant,
What are the ON and OFF time periods of the LED?

PS. Next time, try writing grammatically correct and full english sentences instead of SMS language. Thanks!

3. i have studied keiluvison-3 compiler & have used it for 8051 micro controller. There is logic analyzer option in this compiler where we can see the o/p waveform on the desired port pin. But can you tell me whether we have same option for avr studio as well? i searched it i could not find.
Or my question is how to debug our o/p is exactly working at the required delay as per the program(i do not have oscilloscope).

• Well I don’t think that there’s any such option in Atmel Studio, not that I am aware of. If you could describe your application, may be I could suggest some way out.

4. PLEASE GIVE ME THE CODE OF PWM FOR 32KHZ FREQUENCY IN ASSEMBLY LANGUAGE FOR ATmega16 AVR MICRO CONTROLLER, ALSO SOME BODY HELP ME ON 12VOL DC TO 313 DC BOOSTER CONVERTER CIRCUIT WITH FULL SURETY IT IS ON WORK.. THANK U..

• NOPE. GO GET IT YOURSELF. And please learn some cyber etiquette.

5. is it possible to set baud rate to 4000 baud in atmega 32 if its clocked at 14745600hz. i want use it as a accelerometer mouse

• Nope. Baud rate of 4000 is not a standard baud rate. You can’t have that.

• It IS possible to have a baud rate of 4000 or a baud of 5837 if you want. Just look at the USART section of the datasheet on how to set the prescaler. However, you need 2 devices with the same baud rate.

6. I’m not the one to point finger but the final example code to change the brightness of LED is very much similiar to the one found on http://extremeelectronics.co.in/avrtutorials/code/pwm.c, Just a hint.. the person running that website is not one would call an cool headed person.. you can view his harsh comments on his visitors on his website.

• Thanks for letting us know. I didn’t realize it until now that the code is almost the same. Just like LED blinking is a standard hello world example for microcontroller programming, this is also one of the standard examples for demonstrating PWM application, and can be found on a lot of other websites. It’s a coincidence that our codes are very much similar. If the person has any concerns, let him email me and we’ll deal accordingly. Thank you! :)

7. SIR I NEED A PROGRAM FOR BRIGHTNESS CONTROLLING OF LED USING TIMER1 IN FAST PWM MODE. I need it urgently please help me

WE DO NOT ENTERTAIN SUCH QUESTIONS. Thank you.

8. sir i am using RGB led and i want to create millions of colours using fast pwm mode. so i need 3 timers for 3 pins but i am getting the output for 2 timers(TIMER0,TIMER2) only. i am trying to control the TIMER! but i m not getting output. sir i will send you the code please check it once what the mistake i have done.
Code: http://pastebin.com/EF4tuEz4

thank u.

• You need to be more specific when asking questions. We are busy people and don’t have time to sit and look into your entire code. Thanks and sorry.

9. Dear sir,

I have just read this tutorial and found it interesting. Currently i am working on project which requires to generate PWM signals of different Duty cycle. But i need frequency of 2MHz with variable duty cycle. As per this tutorial i can have only one frequency as my timer will keep counting up to TOP value. So by this method it is impossible to achieve 2Mhz frequency on output pin because i can’t use external crystal due to small size PCB requirement. Could you suggest me any other way to do this? I would really appreciate your suggestions.

• Dear Chandresh,
Try looking into the ICRx register. I didn’t cover about it in this tutorial. I wanted to tell about it in my next servo motor tutorial, but never got a chance to get back to it. Thanks!

10. Great tutorial. It worked the way you explained. So I tried some other stuff to explore more. I tried to generate some specific frequencies. So I tried to use “PWM Phase Correct” mode (mode 10) for Timer 1 (in ATmega328). It says, the TOP value should be ICR1. It supposed to be a simple task, but for some reason my code is not working. My pin stayed low. I know I am doing some silly mistake but couldn’t figure it out yet. Here is the code:

/* I am using 16MHz crystal with prescaler of 64.*/
// 16M/64/2 = 125000;
// 125000/333 = 375;

TCCR1A |= (1<<COM1A1)|(1<<WGM11); // Non-inverted PWM
TCCR1B |= (1<<WGM13)|(1<<CS11)|(1<<CS10);// Prescale 64
TCNT1 = 0;
ICR1 = 375; // TOP value for 333Hz
OCR1A = 170; // Arbitrary duty cycle

/*****************************************************/

Any help would be very much appreciated.

If this is your complete code, then I’m afraid you forgot to direct the Timer’s Hardware pin as an output using DDR.

Hope this helps!

11. is it possible to generate a delay of 500 nano seconds??

• Yes… It depends on the frequency of timers. There are some microcontrollers which can generate up to 70Mhz timer frequency by using PLL.

• Depends upon the frequency. If you use a 16MHz oscillator, then each clock tick will take 62.5 ns, yes you can.

12. Hi sir,
Good morning. I am trying to do interfacing TLC5940NT with Atmega32. I read the TLC5940NT datasheet. And i tried to do program in atmel studio 6.2. In my application i want to setting bits for LED brightness control through hyper-terminal. I don’t want to do LED ON in OVF. I read the data sheet in that after low the BLANK GS counter will increment and it reaches 4096 then BLANK is high. And the Brightness control is through 12 bits. How to set these bits and where to set it. Can you please help me where i am getting struck. It is something different and i like it. ICR1 = F_CPU/64/100 – 1;
F_CPU = 8 MHz and ICR1 = 1249 (max. count value). for checking i connected LED (with resistor) in OCR1A pin. Here i am getting the output what i am expecting like slowly getting up to LED ON and getting down by LED OFF. same like that i want in OUT pins(TLC5940NT). But i am not getting it. What i am doing wrong. Can you please help me. My piece of code and circuit is,

• I referred Arduino circuit. my circuit connection:

TLC5940NT ATMEGA32

GSCLK PD4/OC1B
BLANK CHIP SELECT
DCPRG VCC
SCLK SPI-CLK
SIN MOSI
XLAT PD5/OC1A
VPRG GND
IREF 1.5K to GND
OUT0-15 LED(-VE) & LED(+VE) to VCC

13. Can PWM be used to generate single pulse ? I know there must be some trick incorporated to stuck timer into top value without clearing it. The same about CTC mode. Can you explain ?

• Did you try generating it the way described here? What is it that you’re stuck with?

14. How should change this code of controlling led brightness to use on my atmega128??

• Herman,
If you have understood the concept, you should be able to figure it out on your own by reading the datasheet.

15. Sir,
I think there is a mistake in your code, In first problem you said frequency would be 50Hz(20 ms), If you are using 16 MHz crystal then 8-bit timer will overflow in 15.9375 usec (at 62.7451 KHz), you did not used any prescalar. Am I right, Actually I am usnig a servo motor So, I am strictly bounded for 50Hz(20 ms). please suggest me somthing, I have an idea we can set a calcaulated value of TCNT register after the overflow so the number of clock pulses to be count is in our hand.

• You can’t control servo motor with 8-bit timer. You’ll need to use 16-bit timer for better resolution. If you’re using AVR ATmega16/32, then go for the fast PWM mode (mode 14) of Timer 1. You’ll need to store the TOP value in ICR1 register. I haven’t covered this in any of my tutorials yet, hopefully someday I’ll find time for it. Haha. Read datasheet for more info!

16. Sir,

First of all, I just want to say thank you for these tutorials, they’re the clearest and most complete of any I could find around the web.

I’m working on some code to control an RGBW LED, but I’d also like to have some PWM channels left over for other purposes like generating sound so I’m wondering if it’s possible to have multiple compares on a single timer? Obviously the hardware calculation methods aren’t designed for this. so I tried making a software compare like you had in your earlier examples for the TIMER0 tutorial.

I have an if statement running in main which keeps an eye on the timer to increment some chars and reset once it reaches a certain point. I then use these chars to turn the LED on and off. eg, for three quarters brightness, I turn the LED on, allow the counter char to accumulate to 192, then I turn the LED off, allow the counter to accumulate to 64, then the LED goes back on and so forth.

The trouble is, that no matter what setting I make the thresholds (255, 0 = 100%) (0, 255 = 0%) it remains at the same brightness. I was wondering if you could tell me, am I on the right track? Or is software based calculation not capable of this kind of thing?

If you’re interested here’s my code: http://pastebin.com/izi1GB1Q

Either way, thanks again for your tutorials

• Hi Peter!

In line 62 and line 71, you are using the wrong register to take an input. The input register is ‘PINx’, ‘PORTx’ is used to assign output to a port. Moreover, You need to implement bit masking to take an input from a port that you are using partially as an input and partially as an output.

Hope this helps!

• Hi Vishwam

Thanks so much for your response. I’ve since moved on to another MCU but I’m definitely going to go back and try this out. It bugs me when I can’t figure out a task. Your advice is greatly appreciated.

17. is it possible to control the intensity of 220v ac bulb with the help of pwm??????and how t is possible….plzzzzzzzzzzzzzzzzzzzzzzzzzzz send me detail and code in my email id mahisagariya@gmail.com plzzzzzzz sir plzzzz send mw I really need this priceless info

• I’m new to this like you, so take this with a pinch of salt, but a little research suggested the component you’re looking for is called a “Solid State Relay”

Here’s a few examples which may be suitable: http://tinyurl.com/oetjb2b

You didn’t list the wattage of the bulb you intend to control, but you’ll need to take that into account to calculate the total amps that’ll run through your device and select a suitable component accordingly.

I’m wondering though, if it’s an AC circuit, and a standard lightbulb, would a regular dimmer switch not suit your purposes? Unless you need it to be specifically computer controlled it would probably be cheaper.

Also, I have no idea how flourescant/incandescant bulbs react to this kind of power control, but I’d imagine LED bulbs are ok.

As above, don’t take any of this for granted, I could be wrong about everything.

• You can’t directly controll a 220V AC with a microcontroller.
Microcontrollers work on DC and many of them have a max of 5V rating.

• Did you check the link I gave him? Those components accept a DV 5v (or less) input and control an AC current.

• thanks sir for sending me these link but I can’t control ac bulb

• No problem, sorry I couldn’t help.

• You can ccontrol but you will need to use a variable resistor, same as that of a fan regulator, to vary the brightness of an ac 220V bulb.

18. Erh, I think something is wrong with your duty cycle calculation.
In fast pm mode the duty cycle is:

(OCRx+1)/(TOP+1) *100%
This is important because a dc of 0% is not supported for avr fast pwm.
with TOP=255, the minimum duty cycle = 1/256 * 100% !!!

19. Hello Max. What is mean WGM01:0 or COM01:0? I see bits in the datasheet WGM00, WGM01, WGM02 but can’t understand how to use or read part – “:0” after the name, is it mode of wave generation?

This site uses Akismet to reduce spam. Learn how your comment data is processed.