02 - AVR PWM concepts

Why use hardware PWM?


An advantage of using the microcontroller to generate the PWM signal for us is that once it has been set up correctly the PWM signal will continue to be generated for us automatically in the background. We don't need to write any complicated interrupt routine or other timing code. The beauty is that by simply changing the comparator value we can alter the duty cycle of the PWM until such time as we decide to modify it again.


AVR PWM Hardware


The AVR microcontrollers use the various timers for producing PWM. The timers are complicated (and advanced) beasts and can be used for all sorts of different things. Sometimes, looking at the datasheets, it is hard to seperate the PWM functionality from all of the other things that they can do. Whilst I don't want to explain the Timers functionality it is worth trying to explain them from a PWM view point. This chapter tries to explain the concepts in generic terms. In the next section we will look at how all the different settings are actually used for different PWM channels on different AVR chips.


How many PWM channels are available?


The quick, and un-helpful answer, is that it depends on the microcontroller you are using. You will need to check the datasheet and look in the 'Features' at the top. Alternatively:- a later chapter will allow you to download PWM factsheets for various controllers.


As examples: the ATMega8 has 3 channels, the ATMega168 has 6 channels, the ATMega32 has 4 channels. So it is not implied that 'the bigger' the chip = the 'more PWM channels'. However: we will discuss a method later whereby we can use software to generate PWM on as many output pins as are available/required.


I know how many channels my controller has - what other differences are there?


We will try to break this down by looking specifically at the ATMega8 as used in the $50 Robot although the same principals apply to all of the AVR chips.


All of the PWM facilities are provided by the internal Timers of the AVR. Each timer may, or may not, support PWM. Assuming that PWM is supported: then the other differences are:-

The datasheet overview of the ATMega8 says there are 3 x PWM channels. Further inspection of the datasheet shows that Timer1 provides 2 x 16 bit channels, Timer2 provides 1 x 8 bit channel, Timer0 provides no PWM facilities. This info can be found by using the PDF Bookmarks to navigate to the overivew of each timer. I will explain what all these 'differences' mean as we go but 'in summary' the 16 bit channels tend to offer more functionality and more options than the 8 bit channels.


Here is a simplified view of the Timers when they are used for PWM:-




The clock

This is either the speed of any external crystal you have used or the internal clock speed of your microcontroller. When you compile your program you normally (in AVRlib) have to set the F_CPU variable to this value. Obviously there is only one clock speed per microcontroller.


The pre-scaler

In the previous section we discussed how the PWM repeatedly counts up from the BOTTOM number to the TOP number. What we failed to mention is how quickly this is done. This is set, for each timer, by the combination of the processor clock speed and the pre-scaler.


The purpose of the pre-scaler is to divide the clock frequency by a given value so as to slow down the counting process in the timer. This slow-down factor is always a power of 2 and is typically either 1, 8, 32, 64, 128, 256 or 1024. Note that each Timer may only provide a subset of these pre-scaler values.


Here is the formula to work out how often the counter is incremented:  every  pre-scaler / clock   seconds


So if the clock is 1MHz and the pre-scaler is 1 then the counter will add one to its value every : 1 / 1,000,000 => every 1uS

If the clock is 8MHz and the pre-scaler is 8 then the counter will add one to its value every : 8 / 8,000,000 => every 1uS

If the clock is 8MHz and the pre-scaler is 1 then the counter will add one to its value every : 1 / 8,000,000 => every 0.125uS


The other benefit of the pre-scaler is to help us to minimise the code changes that we need to make if we programmed the fuse-bits to change the clock speed of the controller from 1MHz to 8MHz. As you can see from the formula above: ie we make the clock speed 8 times bigger then so long as we make the pre-scaler 8 times bigger as well then the counter will continue to count at exactly the same speed. For example: if our code is currently working with a clock speed of 1MHz and a pre-scaler value of 1; then if we change the controller to work at a clock speed of 8MHz then we can change the pre-scaler to 8 so that the counter still counts at the same rate. This is very useful as the remainder of our code then remains the same.


Note that if one timer provides multiple PWM channels (eg ATMega8 has 2 channels via Timer1) then they share the same pre-scaler setting.


How the pre-scaler values are set, along with the value of TOP, vary from one AVR chip to the other and from one Timer to another. I will give some more concrete examples in later chapters.


A point on external frequencies

The pre-scaler is very helpful when the clock rate changes by a power of 2. ie changing the clock speed from 1Mhz to 8Mhz can easily be compensated by changing the pre-scaler from 'x' to '8x' without changing other code. So be slightly aware of using clock speeds, via external crystals, that are not a multiple of 2. For example: if your development board used the internal 1MHz or 8MHz clock and then your production board used an external 20MHz crystal then life gets complicated as 20 is not a power of 2 so there is no compensating value that we can change the pre-scaler to - and so some of the rest of your code will need to change as well.


The comparator

The comparator value that is used to change the duty cycle of the PWM is just a register variable.



This is the pin on the microcontroller that is changed between high and low and will be fixed for a specific controller/package. For example: on the ATMega8 the 2 channels on Timer1 are output on OC1A and OC1B (which are pins 15 and 16 on a 28 pin DIP package - also known as PB1, PB2), and the 1 channel from Timer2 is output on OC2 (which is pin 17 on a 28 pin DIP package - also known as PB3).


Choice of Timers

When you have multiple PWM channels available then the choice of which PWM timers to use is also governed by:-

  1. The number of bits of accuracy 
  2. The modes of operation
  3. The compare output modes


So let's now describe what these mean...



The modes of operation

Most PWM timers can support the following modes:

  1. Fast PWM
  2. Phase Correct PWM
  3. Phase and Frequency Correct PWM

At the end of the day - if you are only using a PWM timer to drive one 'thing' then these different modes are pretty much of the same. But if you are driving multiple 'things' (especially any kind of motor: DC motor or servo) from the same PWM timer then there is a subtle difference between them. Since all PWM channels, via the same timer, share the same waveform generator then the only thing that dfferentiates each channel is the 'comparator' value.


'Fast PWM' uses the sawtooth waveform that we saw earlier. But if we have two PWM channels:one with a comparator of a 33.33% duty cycle and the other with a 66.66% duty cycle then the PWM output pins will be as follows:


As you can see each 'pulse' finishes at the same time but the duty cycle dictates when the pulse starts. If you are doing something like fading LEDs then this doesn't matter. But if you are driving DC motors then it makes a BIG difference. Why? Well my only analogy is this... Assume both motors went 'full ahead' for a second - you've gone in a straight line. Now make the left motor go full ahead for one second and then stop, then let the right motor go full ahead for one second and then stop. The two resultant positions are NOT the same. The difference is caused by the relative timings and is further amplified by the wheelbase (ie wheel-to-wheel) distance of your setup.


So what about 'phase correct' and 'phase and freqency correct' modes? The datasheets say that there is no difference between them if we are not changing the value of TOP on the fly. Since TOP is dictating our repeating frequency then we aren't changing it so these two modes are interchangeable and analoguous. So we will cover both of them with one discussion and will refer to them both collectively as 'any phase correct' mode. The major difference is that 'fast PWM mode' counted repeatedly from BOTTOM to TOP to generate a sawtooth waveform whereas these 'any phase correct modes' will count up from BOTTOM to TOP, and then from TOP to BOTTOM so rather than a sawtooth they generate a triangular waveform:


So the first thing to note with these modes is that frequency is now halved. With fast PWM the frequency was relative to TOP but now it is 2*TOP because we are both counting up to TOP and then down to BOTTOM. So lets now compare the outputs with the same fast PWM graph if we have two PWM channels with duty cycles of 33.33% and 66.66%



As you can see the red and blue pulses are no longer aligned at the end of the pulse as they were for fast PWM but they are now centered around the TOP value. This will minimise the positional errors that we mentioned for fast PWM. So it is recommended that if you are using PWM to drive DC motors that you use one of these 'any phase correct' modes rather than fast PWM mode.


Bits of accuracy

This refers to the possible range of values for TOP (since BOTTOM is always 0). As an example: if TOP was set to 7 then your comparator could only be set to a value between 0 and 7 giving you 8 individual duty cycles that you could select from. This would be refererred to as 3 bits of accuracy: since 2 ^ 3 = 8 different settings.


So with an 8 bit Timer then the maximum number of different duty cycles would be 2^8 or 256. For a 16 bit timer it would be 2^16 or 65,536.


Most 8 bit Timers only support a fixed value for TOP of 255 (ie 256 different duty cycles) - ie 8 bit accuracy. 


The 16 bit Timers are a lot more flexible in the values that you can use. First they can provide additional fixed values for TOP: giving 9 or 10 bits of accuracy. But they also provide additional modes of operation for up to 16 bit accuracy where you can use a register called ICRx (where x is the Timer number) to specify an exact number for TOP anywhere up to 65,535. This allows you to create a PWM waveform whose frequency is highly accurate.


Compare Output Modes

Each PWM channel also has a user-specified 'Compare Output Mode' with four options for each of these modes of operation. The compare modes generally fit into the following catagories: PWM is turned off, inverted PWM, non-inverted PWM, and toggled PWM. The 'PWM is turned off' is fairly self explanatory. The other compare modes dictate what happends to the output pin when the counter reaches your 'comparator' value:-

Of these modes the 'non-inverted mode' is the most logical one to use because the comparator value is proportional to the duty cycle. So if we were to say that duty-cycle=speed then lowering the comparator will reduce the speed and increasing the comparator will increase the speed. It's a throttle!


So how do we decide which timer to use?


First of all look at what you are driving via the PWM. If you are feeding a motor controller to drive a DC motor then you cannot possibly expect that a range of 65,536 different speed values makes any sense. All motors behave differently. Even 256 different speed settings would normally be too much to ask - would you notice the difference between 33/256'ths of full speed compared to 34/256'ths of full speed?  Also the PWM frequency is not very time critical so using one of the built in values for TOP should be fine. So DC motors are a good candidate for 8 bit PWM. For the ATMega8 there is only one 8 bit PWM channel so if you are driving two motors then you will be forced to 'upgrade' to the 2 x 16 bit PWMs - but always start with the lowest requirement and then 'upgrade' them to suit what your hardware can provide.


But servos are very different. They generally need a signal every 20ms and the high pulse should be between 1ms and 2ms. If our repeating frequency is every 20ms then an 8 bit timer (having 256 increments) would mean each increment would represent 20ms/256 or 0.078ms. However: most of the 20ms is dormant and all we have to play with is the pulse duration between 1ms and 2ms and we can only break this down into 1/0.078 or 12.8 steps. So an 8 bit timer would only give us 12 independent positions for a normal servo. Most servos (subject to make and model) have around 90 possible steps - so only being able to access 12 of them isn't making the most of the servo - although it may(?) be enough for your particular purpose. Using a 16 bit timer would give a timer granularity of 20ms/65536 or 0.0003ms and so for the 1ms to 2ms pulse width would give 3,276 individual steps. So this is overkill but at least we can make the most of the abilities of the servo. Also: the 16 bit Timers allow us to precisely set the value of TOP in order to generate an exact 20ms signal.


Rules of thumb

  1. Look at what you are driving via PWM and decide on the Frequency (ie for a servo it would be every 20ms)
  2. Consider the number of individual steps you realistically need when varying the duty cycle to decide if you need an 8 bit Timer PWM or 16 bit Timer PWM
  3. Decide if you need to use Fast PWM or Phase Correct PWM mode. For Phase Correct then the value of TOP will need to be halved.
  4. Look at your microcontrollers clock speed to come up with a value for TOP and a value for the prescaler. The value of TOP should be as high as you can make it (by adjusting the prescaler value) as this gives you the most steps in the duty cycle. For a 16 bit Timer then TOP must be less than 65,536 and for an 8 bit Timer it must be less then 256.
  5. Assign your PWMs to individual timers remembering that PWMs on the same timer share the same pre-scaler
  6. If necessary upgrade your PWM channels to a 'higher-than-needed' resolution. ie if you run out of 8 bit timers then start using 16 bit timers

In later chapters we will give some source code examples, calculators and downloads.