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)


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.