PWM on the ATmega168

mbateman correctly noted : This tutorial deals with PWM that does not care too much about the base freqency and can use the whole range of 0-100% duty cycles. It is not suitable for servo control since it is not the correct base freqency and with the 8 bit timers, does not have sufficient granularity for the 5-10% range that servos require. For things like LED dimming and H-bridge motor control it is useful.

Before beginning this tutorial make sure you understand what PWM is . Google it. Do some research, then come back. Read this : http://www.societyofrobots.com/member_tutorials/node/228 .

Open up AVRstudio to your existing project - if you followed the $50 Robot tutorial this would be Photovore_V1. Then right click Source Files and select "Create New Source File".

Type in "pwm.c" without the quotation marks. Press OK. If you look in the left sidebar under the folder "Source Files" , there will be a new file called pwm.c . Click that file. Now paste the following code into pwm.c .

// IMPORTANT : The following code was done for the Roboduino board.//The Roboduino is ATmega168 based so the hardware is the same. Only//difference is that I used pin numbers instead of port numbers. To see//what pin //number correlates to what port number use this chart -//http://www.arduino.cc/en/Hacking/PinMapping168 .

// http://www.CuriousInventor.com/kits/roboduino

//For example pwmInit56 is for pins 5 and 6 which translates into PD5 and PD6

//There are two channels of PWM per timer, in the comments I wrote down which pin is which

The next step is to open up SoR_Utils.h ( one of the header files that should be included if you followed the $50 Robot Tutorial.) Scroll to the top of SoR_Utils.h and you should see a bunch of #includes . They would look similar to this ( but not necessarily exactly)

Any pin that you want to be PWM needs to be set to be an output. If you use the the configure_ports code I used above, then all your PWM channels will be set to be outputs ( and cannot be used for inputs).

To actually use the PWM in your code you need to do the following:

Initialize timer for pins

Turn on PWM for that pin

Set PWM

Note that you need to initialize the PWM and turn on a PWM only once in your code and not each time you want to set a PWM.

For example to use PWM on pins 9 and 10 you would use the following code in your main code:

pwmInit910(); // Intialize PWM for timer which controls pins 9 and 10 ( since pins 9 and 10 are on the same timer) pwmOn9(); // turn on PWM for pin 9 pwmInit56(); //Initialize timer for pins 5 and 6(since pins 5 and 6 are on the same timer) pwmOn5(); // turn on PWM for pin 5 pwmSet5(255); //pin6 which is 8 bit PWM

pwmSet9(65535); //pin9 which is 16 bit PWM

After you already initiliazed the PWM and turned on PWM for that pin you would only need to use the pwmSet function each time you wanted to change the PWM duty cycle. So lets say you initiliazed the PWM for 6 and turned on PWM for pin 6 once already, then later on you want to change the duty cycle to 50%, you would only need to do : pwmSet6(128); .

Also note that Pins 3,11,5,6 are 8 bit PWM and pins 9,10 are 16 bit PWM. 8 bit means you have 256 steps of PWM (from 0 - 255). So 255 would be 100% duty cycle (full voltage) and 128 would be 50% duty cycle (half voltage). The 16 bit PWM is basically the same except it has 65536 steps ( from 0-65535).

If you have any questions use the Robot Forum - societyofrobots.com/robotforum .