PWM - an overview

WORK IN PROGRESS

 

PWM sometimes seems to be a misunderstood and complicated topic.

 

This tutorial will cover the basics of what PWM is, what it can be used for, and how to use the AVR controllers to generate PWM.

01 - What is PWM?

PWM stands for Pulse Width Modulation. This means that we can generate a pulse whose width (ie duration) can be altered.

 

The digital world

 

Since microcontrollers live in a digital world then their output pins can be either low (0v) or high (5v). However: the rest of the world tends not to speak such an open-or-shut case ie the rest of the world tends to be analogue. Rather than just being on or off: motors tend to need speed control, lighting may need to be dimmed, servos need to move to a particular position, buzzers need a sound frequency etc.

 

AVR microcontrollers have Analogue To Digitals Convertors (ADC) to convert a voltage from the analogue world to a number but do not have Digital to Analogue Convertors (DAC) to convert digital numbers back into variable voltages.

 

PWM is the closest solution.

 

By turning an output pin repeatedly high and low very quickly then the result is an average of the amount of time the output is high. If it is always low the result is 0v, always high then the result is 5v, if half-and-half then the result is 2.5v.

 

Why does this work? Well most real world devices have some kind of latency (ie they don't do what you ask immediately). This could be caused by a mixture of momentum, inductance, capacitance, friction (amongst others).

 

For example: if you connect a motor to a battery then it will, eventually, rotate at full speed. Disconnect the battery and the motor will take a little while to slow down until it stops. Equally if the motor is only connected to the battery for a very short time before being disconnected then it wont have enough time to get up to full speed. So if we repeatedly connected and disconnected the battery then the motor would start turning, then slow down, start turning, slow down etc. Obviously if we only did this a few times a second then it would be kind of jerky - but if we did it fast enough then we could control the speed of the motor dependent on the percentage of time the battery was connected versus not connected.

 

Similarly - if we wanted to dim lights or LEDs then they take a little while to get up to 'full glow' and, once disconnected from the power, the glow fades away. So we could create a dimmer by varying the amount of time on or off.

 

Servos are another example. They tend to expect a pulse every 20ms - depending on the width of the pusle they move to a given location.

 

How do we create a PWM signal

Before we discuss the intricacies of how we program a microcontroller then let's consider some basics to get a general idea of what we want to achieve.

 

Microcontrollers are very good with whole (integer) numbers. So assuming we have two numbers: one called BOTTOM and a higher number called TOP. By making the microcontroller start at BOTTOM, and then count upwards until it reaches TOP, and then repeat the process - if we were to then plot the resulting numbers on a graph then we end up with what is called a Sawtooth waveform that looks like this.

 

 

Of course you can never output this signal from your controller as it can only cope with on or off and not all these numbers - it just shows how the number starts at BOTTOM, counts up to TOP, and then starts all over again.

So the next step is to add a 'comparator' which is used to decide whether our output pin should be high or low. This comparator is yet another number which is somewhere in the range between BOTTOM and TOP. If the current Sawtooth number is less than the comparator value then the output will be low, otherwise the output will be high.

If the value of the comparator was equal to BOTTOM then the Sawtooth value could never be lower than bottom so our output pin would always be high. Equally if the comparator value was equal to TOP then the output pin would always be low. However: if the comparator value was the mid-value between BOTTOM and TOP then the output pin would spend 50% of its time being low and the other 50% being high. By varying the comparator value we can change the 'high' time anywhere between 0% and 100% of the time.

Looking back at the previous diagram we can see that the sawtooth waveform is 6 units high and repeats every 3 units across. So if we were to set our comparator to be 2 units above the BOTTOM value then what would happen?
The sawtooth waveform would spend 1/3 of the time below this value and the remaining 2/3 of the time above value. So our digital output pin would be a square wave that is low for 1/3 of the time and high for 2/3 of the time.

 


Frequency

In the above example the sawtooth waveform repeated every 3 units. Assuming that each unit was 1ms then our waveform repeats every 3ms.

Given that Frequency = 1 / Time

then the signal frequency is 1/0.003, or 333.33 Hz. Note that with PWM this frequency remains constant - we just use the comparator value to adjust the duty cycle.

 

Duty Cycle

The percentage of time that our output pin is high is called the duty time. In the example above it is high for 2/3 of the time ie a 66.66% duty cycle.

 

 

 

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.

 

PWM Out

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.

 

03 - AVR specifics

 

As we have seen in the previous chapter there are several things to bear in mind for PWM:-

 

1. The clock speed of your microcontroller. Obviously a given microcontroller only has one speed that at it runs at - although this can be can be altered by changing fuse bits or by adding external crystals. Changing the clock speed will effect ALL of your PWM channels

2. A microcontroller can have one or more Timer that can be used to produce PWM. Each Timer may provide zero-or-more PWM channels and will have a pre-scaler value that effects all of the channels that it provides and controls the speed at which the clock is used to count between BOTTOM and TOP. Each Timer can have a mode of operation (Fast PWM, phase correct or phase and frequency correct) which may have a fixed value for TOP or allow you to specify a precise value.

3. Each channel can have a comparator mode (inverted, or non-inverted) as well as its own comparator value that allows you to define the duty-cycle of the PWM signal for the channel.

 

If you are struggling with these concepts then please go back and re-read the previous chapters (or let me know if something is missing or non-sensible!).

 

Since PWM 'in-practice' uses a number of fiddly little bits in various registers - and these change from one controller to another - then its hard to give you a 'one-solution-fits-all'. So we will now start to look at where these settings exist for each controller. The principles are always the same - but the registers and the bits may change. So the purpose of this chapter is to come up with some tabular data for different controllers and channels so that you can substitute the appropriate values into your code. It may sound complicated - but once you settle on a given controller then (I hope) it will all make sense.In the next chapter I provide some downloads to give the specific names for each register/bit for various microcontrollers.

 

In order for you to make sense of some of the datasheets then I will try to describe some of the 'generic' nomenclature they use.

 

Each Timer has various registers that are used to store its configuration. These are normally called TCCRxA, TCCRxB, TCCRxC etc where 'x' is the Timer number (1,2,3, etc). Since each timer provides different capabilities then it requires more or less configuration bits so each timer may have a varying number of configuration registers. If they one require one register then the last character is dropped and it is just called TCCRx. Since the Timers are capable of a lot more than just PWM then some of the configuration values in these registers is way beyond the scope of this tutorial.

 

The pre-scaler mode for a timer is generally set by the combination of 3 bits called (from most to significant to least significant) CSx2, CSx1 and CSx0 and normally exist in register TCCRxB  where 'x' is the timer number. These bits, for PWM purposes, may have the following example values:-

0,0,0 = The timer is stopped and so no PWM will be generated. This kills the whole timer and therefore also kills all PWM channels it provides. The main advantage of 'stopping' a timer is that the chip may consume less power. Its always good to kill off facilities you don't need.

0,0,1 - PWM is active with a pre-scaler value of 1

0,1,0 - PWM is active with a pre-scaler value of 8

0,1,1 - PWM is active with a pre-scaler value of 64

1,0,0 - PWM is active with a pre-scaler value of 256

1,0,1 - PWM is active with a pre-scaler value of 1024

 

The comparator mode requires 2 bits that are normally stored in register TCCRxA where 'x' is the timer number. But don't forget that each timer can support mulitple channels so there will be a complete set of these 2 bits for each channel for each timer. The bits are called COMxy1 and COMxy0 where 'x' is the timer number and 'y' is the channel number: 'A', 'B' etc. The general value for these two pins is as follows:-

0,0 - This PWM channel is switched off.

1,0 - This PWM channel is switched on in non-inverting mode

1,1 - This PWM channel is switch on in inverting mode

NB The last two values will switch the PWM channel 'on' - but unless the timer, as a whole, is switched 'on' by setting a pre-scale value as mentioned above then nothing will happen.

 

The mode of operation is set using the four (or less) bits WGMx3, WGMx2, WGMx1, WGMx0 where 'WGM' stands for 'Waveform Generation Mode', and 'x' is the Timer number. Just to make life a bit more complicated the controllers often split these bits so that some are stored in register TCCRxA and others in register TCCRxB. These four bits actually give a total of 16 different modes (called Mode 0 to Mode 15). Each Timer (especially 8 bits ones) will only support a subset of these modes. Some of these modes are for non-PWM usage and so we wont discuss them further.

The most flexible modes, only available on 16 bit Timers, are those where TOP is set to a specific value by ICRx and use OCRxy is used to modify the duty cycle on the fly. These modes are:-

Mode WGMx3 WGMx2 WGMx1 WGMx0 Description
8 1 0 0 0 Phase and Frequency Correct mode
10 1 0 1 0 Phase Correct Mode
14 1 1 1 0 Fast PWM Mode

 

The value of TOP is specified by the register ICRx where 'x' is the timer number and is a 16 bit value (ie 0 to 65,535). Note that there is only one value per timer - so all the PWM channels on the same channel will share this value. This is not normally an issue since, as an example, if we were using two channels on the same timer to drive two servos then this one value for TOP is used to set the overall pulse frequency - which is every 20ms for a servo. So there is no problem with the same value applying to both servos.

Other mode numbers are available for these 3 basic PWM modes - the only difference is that the value of TOP is fixed at a set value ie 255, 511, 1023 and so you have less flexibility to set an exact repeating frequency.

 

The comparator value, which you use to specify the duty cycle of a given channel, is set by writing the required number to register OCRxy. Where 'x' is the timer number, and 'y' is the PWM channel A, B etc. So for PWM channel A on Timer 1 then we would write to OCR1A. If the Timer only has one possible channel then the final letter would be removed ie OCRx

 

 

So let's practice this with an imaginary example - before giving some real examples in later chapters. Assume that we wanted to set up a 16 bit PWM on Channel B of Timer 1 with a prescaler of 1, non-inverting mode, Phase and Frequency Correct, with a TOP of 10,000. Then we would replace 'x' in the above details with the Timer number - ie '1' for this example, and the 'y' with the Channel number - ie 'B' for this example. So in pseudo code this is what we would do:

// Set up the pre-scaler to 1

Register: TCCR1B - set bits CS12,CS11,CS10 to 0,0,1 respectively

// Set up the comparator mode to 'non-inverting'

Register: TCCR1A - set bits COM1B1 and COM1B0 to 1,0 respectively

// Set for phase and frequency correct mode

In Registers TCCR1A and/or TCCR1B - set bits WGM13, WGM12, WGM11, WGM10 to 1,0,0,0 respectively

// Set the TOP value

Set Register ICR1 to 10,000

// We can now change the duty cycle by varying the value of the comparator in register OCR1B with a value between 0 and TOP (ie 0 to 10,000)

 

Easy?

04 - Reference Information

I have produced some tables of PWM information for different AVR microcontrollers. I find them a really useful summary of the datasheets when using PWM. Once you've played with PWM a bit, and understood the basics, then these sheets are 90% of what you need from then on!  N.B. I haven't embedded them as images as they are quite big and don't show up very well at a small resolution inline with this text.

Click on the name of the processor to download the individual PDF documents.

 

Alternatively you can download an Excel file for all of them from here

 

I've done my best to verify the information in these sheets but since I don't own all of the hardware then I can't test them in practice. So if anyone finds any errors then please let me know.

 

Calculating the value of TOP

 

For 'Fast PWM' modes the formula is as follows:-

Output_PWM_Frequency =  Clock_Speed / (Prescaler * (1 + TOP))

 

or

TOP = (Clock_Speed / (Prescaler * Output_PWM_Frequency)) - 1

 

 

For 'Phase Correct' and 'Phase and Frequency Correct' modes the formula is as follows:-

Output_PWM_Frequency = Clock_Speed / (2 * Prescaler * TOP)

or

TOP = Clock_Speed / (2 * Prescaler * Output_PWM_Frequency)

 

 

 

 

 

 

 

 

05 - Example :- Driving a servo via PWM

In order to drive a servo we need to understand the mechanics of a servo:-

  1. It should be sent a pulse every 20ms
  2. The width of the pulse should 1.5ms to zero the servo
  3. A width of 1ms will make it turn fully to one side
  4. A width of 2ms will make it turn fully to the other side

So the first PWM point is that the PWM repeat frequency should be every 20ms.

 

Secondly we note that the active pulse length is between 1ms and 2ms. This represents a duty cycle between 1ms per 20ms (5%) and 2ms per 20ms (10%) hence a 5% fluctuation between minimum and maximum. So out of our total comparator values then only 5% of them will actually make any difference to how the servo behaves.

 

For an 8 bit timer with 2^8 (ie 256) different values then this 5% fluctuation represents 5% of the total of 256 (= 12.8). So you could only set the servo to move to any one of 12 different positions. This is a much smaller value than a servo is capable of. But you may decide it is still enough for a given application.

 

For a 16 bit timer with 2^16 (65,536) different values then this 5% fluctuation represents 5% of the total of 65,536 (=3276.8). So you could set the servo to move to one any of 3,276 different positions. This is more steps than most servos can actually cope with but does, at least, cover all the physically achievable positions even though there will be a lot of duplicates ie position 1,234 may well be the same as position 1,235.

 

Since we are not driving a DC Motor then we will go with Fast PWM mode.

 

So lets make a decision, we will go with the 16 bit PWM because:-

  1. Each servo is a physical thing and its response may not be exactly 1ms to 2ms it could be smaller (say 1.2ms to 1.8ms in which case we would have less than 12 different settings). So a wider choice of values with the 16 PWM gives us more leeway
  2. Assuming we have two servo motors then the ATMega8 provides 2 x 16 bit PWM outputs on Timer1 which support fast PWM mode versus only one 8 bit PWM on Timer2
  3. The 16 bit timers allow us to use a mode of operation which allows us to define a more appropriate value of TOP to make sure that the frequency is every 20ms. The 8 bit timers don't allow us to do this.

So we are going to use 16 bit PWM via Timer1.

 

In order to setup the hardware we first have to tell Timer1 to repeat every 20ms or 50Hz. To calculate the value for TOP we will use the formula from the previous section:

TOP = (Clock_Speed / (Prescaler * Output_PWM_Frequency)) - 1

 

Since we are using a 16 bit timer then the value of TOP must be in the range 0 to 65,535. If the result is bigger than this then we need to bump up the pre-scaler in order to reduce the TOP to fit this range. So starting with a prescaler value of 1:

 

For a 1MHz controller then

TOP = (1,000,000 / (1 * 50)) - 1 = 19,999   This is 'in-range' so our answer is: prescaler=1 and TOP=19,999

 

For a 8MHz controller then

TOP = (8,000,000 / (1 * 50)) - 1 = 159,999  This is not 'in-range' so lets try again unsing the next available prescaler value of 8

TOP = (8,000,000 / (8 * 50)) - 1 = 19,999    This is 'in-range' so our answer is: prescaler=8 and TOP=19,999

 

 

 

 

Here is our code so far for an ATMega8 with 1Mhz clock speed:

TCCR1A = 0;          // disable all PWM on Timer1 whilst we set it up


ICR1 = 19999 ;   // frequency is every 20ms


// Configure timer 1 for Fast PWM mode using ICR1, with no prescaling

TCCR1A = (1<<WGM11)
    TCCR1B = (1 << WGM13) | (1<<WGM12) | (1 << CS10);


 

or for an 8Mhz processor:

TCCR1A = 0;          // disable all PWM on Timer1 whilst we set it up


ICR1 = 19999;   // frequency is every 20ms


// Configure timer 1 for Fast PWM mode via ICR1, with 8x prescaling

TCCR1A = (1<<WGM11)
     TCCR1B = (1 << WGM13) | (1<<WGM12) | (1 << CS11);


 

We can generalise by using compiler directives to insert the correct values by using:-

#if F_CPU == 8000000
    ICR1 = 19999

// 8x prescaling

TCCR1A = (1 << WGM11)

TCCR1B = (1 << WGM13) | (1<<WGM12) | (1 << CS11);

#elif F_CPU == 1000000
    ICR1 =19999;

// 1x prescaling

TCCR1A = (1 << WGM11)

TCCR1B = (1 << WGM13) | (1<<WGM12) | (1 << CS10);

#else
#error    No F_CPU has been set or it is an unrecognised value
#endif


 

The Timer1 is now set up to be able to provide up to 2 PWM outputs on pins OC1A and OC1B respectively. At the moment our statement 'TCCR1A=0;' means that we have disabled both of them.

 

To activate the first channel on OC1A, which is also port B1, we must do the following:-

 DDRB |= _BV(1);      // make port B1 an output pin


TCCR1A |= 2 <<  6;  // enable PWM on port B1 to use non-inverting mode - mode2


we can now adjust the duty cycle of the output pin by setting OCR1A to a value between 0 and ICR1.

 

 

To activate the second channel on OC1B, which is also port B2, we must do the following:-

 DDRB |= _BV(2);      // make port B2 an output pin


TCCR1A |= 2 <<  4;  // enable PWM on port B2 to use non-inverting mode - mode 2


we can now adjust the duty cycle of the output pin by setting OCR1B to a value between 0 and ICR1.

 

 

So we now have a repeating 20ms pulse on our output pins whose duration is set by either OCR1A or OCR1B. What values do we need to put in these registers in order to drive the servo?

Well ICR1 holds the value of TOP which represents 20ms. We know that a centered servo requires a pulse of 1.5ms so we need to write a comparator value to OCR1A or OCR1B of:  ICR1 * 1.5 / 20.

 

The coolest thing about PWM is that it is all taken care of in the hardware. All we have to is change the values of the comparator in OCR1A and/or OCR1B to change the position of the servo (with a modified servo this means its speed).

 

So assuming a differential drive robot that has two modified servos then we can demonstrate this as follows for a 1Mhz controller:-

int main(){
// set up 2 PWM channels on PB1 and PB2 using Timer1

TCCR1A = 0; // disable all PWM on Timer1 whilst we set it up
ICR1 = 19999; // frequency is every 20ms


// Configure timer 1 for Fast PWM mode via ICR1, with no prescaling
TCCR1A = (1 << WGM11)
TCCR1B = (1 << WGM13) | (1<<WGM12) | (1 << CS10);

// Set PB1 and PB2 as outputs
DDRB |= _BV(1) | _BV(2);
TCCR1A |= 2 << 6; // enable PWM on port B1 in non-inverted compare mode 2
TCCR1A |= 2 << 4; // enable PWM on port B2 in non-inverted compare mode 2

OCR1A = ICR1 * 2 /20; // 2ms pulse to left motor on PB1
OCR1B = ICR1 * 2 /20; // 2ms pulse to right motor on PB2


while(1){



// do nothing - the hardware is pumping out 2ms pulses every 20ms to the servos on PB1 and PB2



// for a differential drive robot the motors are on each side of the robot so the robot should be spinning around its midpoint
}


return 0;

}

06 - Example:- Driving a DC motor using PWM and a motor controller

The first thing to note is that you cannot connect a DC motor directly to the output pins of your microcontoller - you'll blow up the microcontroller. You need to have a bunch of electronics in between the two. This circuit is called a 'motor controller', 'motor driver' or an 'H-Bridge'. The forum on this site has various discussions on this topic. I have created a tutorial giving various motor controller designs here but the following example will work equally with other circuitry.

 

To drive a DC motor we will use a PWM signal and vary the duty cycle to act as a throttle: 100% duty cycle = full speed, 0% duty cycle = coast, 50% duty cycle = half speed etc.

 

Unlike a servo a DC motor doesn't have any pre-requisite for the frequency of the PWM signal so it is an area that you can experiment with. However: if the PWM frequecy is very low then the motor will rotate in a sequence of 'jerks', a slightly higher frequency and the motor will make an audible 'hum'. So you need to increase the PWM frequency until this stops.

 

The other consideration is that if your driver circuitry uses MOSFETs then the PWM frequency should never exceed the switching speed of the MOSFET. If you are building your own H-Bridge then it is best to use 'PWM optimised MOSFETs' as they provide improved energy efficiencies- google for it - in which case your PWM frequency may need to be set up to use a particular frequency. So check the datasheets for the MOSFETs being used.

 

Also check out how your controller board copes with forward and reverse. Some controllers use the PWM for speed and another pin to set direction (forward or reverse). Other controllers achieve it all in the one PWM signal e.g. duty cycles < 50% are reverse and > 50% are forward.

 

 

Assuming we are driving more than one drive motor then we will choose either a 'Phase Correct' or a 'Phase and Frequency Correct' mode rather than 'Fast PWM' - as discussed earlier. The relevant formulas for these modes are:

Output_PWM_Frequency = Clock_Speed / (2 * Prescaler * TOP)

or

TOP = Clock_Speed / (2 * Prescaler * Output_PWM_Frequency)

 

Looking at the different modes of operation in the reference section you will see that all the Timers provide 8-bit Phase Correct mode with a fixed value for TOP of 255. This gives us 256 different speeds to choose from - which is more than ample. So can we use these? Using the first equation, and assuming an 8MHz process clock speed, then the highest PWM frequency we can achieve is to use a prescaler of 1:-

Output_PWM_Frequency = 8,000,000 / (2 * 1 * 255) = 8,000,000 / 510 = 15,686Hz

Without knowing your driver then I can't comment as to whether this is ok or not. If the PWM frequency needs increasing then you will need to use the Phase Correct mode that allows you to specify the value of TOP via register ICRx. Reducing TOP to a value below 255 will increase the overall frequency at the expense of having less individual speed settings. ie halving TOP will double the frequency but give you half the number of speed settings.

 

But lets assume that the above figures are satisfactory and that we are using Timer2 on an 8MHz ATMega8. Here's the code:-

TCCR2 = 0; // Turn all PWM whilst setting up

// Select 8 bit phase correct with TOP=255

TCCR2 |= (1<<WGM20);

// Select prescaler = 1

TCCR2 |= (1<<CS20);

// Turn on the PWM channel using non-inverting mode

TCCR2 |= (1<<COM21);

 

We can now vary the speed by changing the value of OCR2 between 0 and 255. The PWM output will appear on pin OC2.

 

07 - Example:- Making sounds with PWM

In this example we will use a piezo sounder like this one

These devices can be attached directly to a microcontroller pin by connecting the red wire to the output pin and the black wire to ground.

 

If your output pin is set high then there is a voltage across the sounder - but this won't make a noise. A sounder needs to be turned on and off in rapid succession to make a tone. Each sounder is designed to give an optimal output for a given switching frequency. Check the datasheet for your sounder - but this figure is normally around 4kHz to 5kHz.

 

So we will assume a frequecy of 4kHz.

 

Unlike the previous examples: we will keep the duty cycle at 50% but instead we will vary the PWM frequency by changing the value of TOP. This implies that we need a mode of operation that allows us to specify TOP via the ICRx register.

 

Assume we are using the 1MHz ATMega8 from the $50 robot then the only Timer that allows us to change the value of TOP is Timer1 which has two channels. So we will use Timer1 channel A. We will use Fast PWM.

 

Using our formula:

TOP = (Clock_Speed / (Prescaler * Output_PWM_Frequency)) - 1

then

TOP = (1,000,000 / (1 * 4,000)) - 1 = 249   For a PWM frequency of 4kHz

 

 

So in summary:

    TOP=249 for 4kHz

    prescaler = 1

    Mode = Fast PWM

    Use Timer1 Channel A

    Connect the sounder to pin OC1A

 

So here's the code:-

 

TCCR1A = 0; // Stop all PWM on Timer 1 when setting up

TCCR1A |= (1<<WGM13) | (1<<WGM12) | (1<<WGM11); // 16 bit Fast PWM using ICR1 for TOP

TCCR1B = 0;

TCCR1B |= (1<<CS10);  // pre-scaler = 1

TCCR1A |= (1<<COM1A1); // enable channel A in non-inverting mode

 

ICR1 = 249;  // 4kHz PWM

OCR1A = ICR1 / 2; // 50% duty cycle

 

We can then vary the frequency by changing ICR1 and by setting OCR1A to be half of that new value (in order to keep a 50% duty cycle). For example:

ICR1 = 300;

OCR1A = ICR1 / 2;

 

So here's a little challenge for you and your $50 robot. You've already created light sensors  - so why not use one of them to decide on the frequency of the sounder so that it makes a difference noise depending on whether its in a dark place or a light place. The only hardware you need is a piezo sounder (expect to pay about 99p in the UK, so about $1.50).

 

 

 

08 - Achieving PWM in software

 

Depending on your requirements, and the hardware that you have to hand, then it may be that you don't have sufficient hardware PWM channels available. So what now? Well you could try replacing your microcontroller with a 'plug-in compatible' chip. The ATMega8 only has 3 PWM channels but can be replaced with an ATMega168 which has 6 PWM channels. That may, or may not, solve the issue.

 

But why would I want to do this versus using delays as done in the $50 robot?

The delay method is fine if you are only using a few servos. But if you are trying to drive 10 servos then each of those delays adds up. So if each servo is sent a position pulse and then you are pausing for 20ms then with 10 servos you are pausing for a total of 200ms every time around your main loop. Whilst the pauses are happening then the rest of your code cannot be doing anything. So each servo actually ends up getting the full delay of 200ms and will therefore be very jerky. This also means that you are also only reading your sensors every 200ms. In other words: the more servos you add then the slower, and more jerky, the whole robot becomes.

 

So to solve this issue we need to get rid of all of those delay loops so that the main program can run at full speed and so that each servo is 'refreshed' every 20ms no matter how many additional servos you connect (within reason!).

 

The solution is to use software interrupts to simulate PWM which, in theory, could be used to produce PWM on any general output pin on your microcontroller and thus provide a much larger number of PWM output channels. The big caveat is that this will never be quite as precise as doing it using hardware because it is more susceptible to being interrupted by other interrupt service routines you may have. However, if the devices you are driving are not time critical then this gives an acceptible solution - even if it allows you to use software for the non-time-critical devices thereby freeing up your precious hardware channels for the devices which are.

 

The basic technique is that each software PWM channel requires that you:

  1. Turn on the output pin for the PWM channel and
  2. queue up a 'toggle event' that will be run at a later date.
  3. When the time has elapsed you change the output pin to low and
  4. queue up a 'toggle event' that will be run at a later date.
  5. When the time has elapsed go to step 1

The sum of the two delays will dictate your PWM frequency, and the duration of the delay in step 2 will dictate the duty cycle. If we can perform all of this under interrupts then your main program can run without pauses and each servo should be refreshed every 20ms.

 

Of course the simple solution is to use my library WebbotLib.  See http://webbot.org.uk