ATmega328p micrcontroller Timer/Counter can be used to generate
two kinds of PWM signals which are Fast PWM and Phase Correct PWM. In the tutorial ATmega328P Fast PWM mode Programming Examples we explained Fast PWM mode with examples codes. In this tutorial we will explain with example codes how Phase Correct PWM mode can be used. Phase correct PWM mode is used is used for motor control applications. In this tutorial
we will explain and illustrate Fast PWM mode for Timer/ Counter 0 with
example codes.
For other ATmega328P modes of operation examples see the following:
- Normal Mode(see ATmega328p Timer Programming Examples)
- CTC mode(see Programming ATmega328p in CTC mode)- Fast PWM mode(see ATmega328P Fast PWM mode Programming Examples)
Phase Correct PWM mode
The Phase Correct PWM mode is used to generate PWM signal at the output compare pins(either OC0A or OC0B depending upon which output compare unit A or B is used). It is called Phase Correct PWM because the generated PWM signal has symmetrical waveform nature which is due to its dual-slope nature of operation.
Modes of Phase Correct PWM mode
There are two Phase Correct PWM modes for Timer/Counter 0 unit. They are mode 1 and mode 5 which are selected using the waveform generation mode bits(WGM02, WGM01, WGM00) located in the TCCR0A and TCCR0B registers. The following table shows the WGM bits combination for mode 1 and mode 5.
The WGM02 bit is located in the TCCR0B register as shown below.
The WGM01 and WGM00 bits are located in the TCCR0A register as shown below.
The
difference between the mode 1 Phase Correct PWM and mode 5 Phase Correct PWM is the TOP
value. For mode 1 the TOP value is is 0xFF whereas the the TOP value for
mode 5 is OCR0A. If mode 5 is used then we have to load count value into
the OCR0A register. If mode 1 is used then we don't have to load the
counter since the TOP value in this case is 0xFF. Once the mode is selected the counter is
started and the timer/counter starts counting from zero to TOP value and
when TOP value is reached the counting is repeated from the bottom.
Types of Fast PWM mode
There are two types of Phase Correct PWM modes:
(a) non-inverting Phase Correct PWM
(b) inverting Phase Correct PWM.
The Compare Output Mode bits (COM0A1 and COM0A0) located in the TCCR0A register are used to set up non-inverting or inverting mode for the output at OC0A pin. The following table shows how to select the COM0A1 and COM0A0 bits.
Similarly, the Compare Output Mode bits (COM0B1 and COM0B0) located in the TCCR0A register are used to set up non-inverting or inverting mode for the output at OC0B pin. The following table shows how to select the COM0B1 and COM0B0 bits.
Following picture shows the timing diagram for Phase Correct PWM which includes non-inverted and inverted PWM outputs.
(a) Non-Inverting Phase Correct PWM mode
In order to use the Phase Correct PWM mode, we have to set the Wave Generation Mode bits(WGM01 and WGM00) located in the TCCR0A register and also the WGM02 bit located in the TCCR0B register. These bits are configured so that either mode 1 or mode 5 of phase correct mode is used.
After selecting either mode 1 or mode 5, the Compare Output Mode(COM0A1, COM0A0 for output at OC0A and COM0B1, COM0B0 for output at OC0B) bits are configured for using non-inverting mode.
Non-Inverted Phase Correct PWM Frequency & Duty Cycle
Non-Inverted Phase Correct PWM Frequency
The phase correct PWM wave frequency for Timer0 is calculated using the following equation.
\[F_{w}=\frac{Fosc}{510N} \hspace{5cm} -------->(1)\]
where, \(F{osc}\) is the CPU or crystal oscillator frequency and N is pre-scalar which can have value of 1, 8, 64, 256 and 1024.
For example, using equation (1), if we use pre-scalar N of 1 we can generate Phase Correct PWM signal of frequency 15.69KHz.
The CS02, CS01 and CS00 bits are used set the Pre-scalar value N in the above equation for frequency. The following table shows the function of these CS bits.Non-Inverted Phase Correct PWM Duty Cycle
The duty cycle of the non-inverted Phase Correct PWM signal is calculated using the following formula.
\[OCR0= \frac{255D}{100}\hspace{5cm} ------------->(2)\]
where, D is the duty cycle 0% to 100%.
For example if we want the PWM signal to have 40% duty cycle then using equation (2), the value for the OCR0A is 102. We can also use the Online ATmega Timer/Counter calculator to determine the count value to be loaded into the OCR0A register. An example is shown below.
Non-Inverting Phase Correct PWM mode 1 with output at OC0A
The following steps can be followed to program ATmega328P in Phase Correct PWM.
(a) Make the OC0A pin(Port D Pin 6) an output pin
DDRD |= (1<<PD6);
(b) Load count value into the OCR0A register for (40%)duty cycle control
OCR0A = 102;
(c) Configure TCCR0A and TCCR0B register for (i) non-inverting, (ii) Phase Correct PWM mode, (iii) Pre-scalar(N=1) for frequency control
TCCR0A |= (1<<COM0A1) | (1<< WGM00);
TCCR0B |= (1<<CS00);
The
following C program will setup the atmega328p Timer/Counter0 in non-inverting Phase Correct PWM mode with frequency of 15.69KHz and duty cycle.
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
int main()
{
DDRD |= (1<<PD6); //Phase Correct PWM output at OC0A pin
OCR0A = 102; // Duty cycle of 40%
TCCR0A |= (1<<COM0A1) | (1<<WGM00); //Non-Inverting Phase Correct PWM mode 1
TCCR0B |= (1<<CS00); //No-Prescalar
while (1);
return 0;
}
The following schematic diagram shows Phase Correct PWM output at the OC0A pin(port D pin 6).
Non-Inverting Fast PWM mode 3 using OCR B unit
The following C program code will output non-inverting Phase Correct PWM signal at the OC0B pin of ATmega328P with frequency of 15.69KHz and duty cycle of 40%.
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
int main()
{
DDRD |= (1<<PD5); //Phase Correct PWM output at OC0B pin
OCR0B = 102; // Duty cycle of 40%
TCCR0A |= (1<<COM0B1) | (1<<WGM00); //Non-Inverting Fast PWM mode 1
TCCR0B |= (1<<CS00); //No-Prescalar
while (1);
return 0;
}
The following schematic diagram shows Phase Correct PWM output at the OC0B pin(port D pin 5).
Non-Inverting Fast PWM mode 7 using OCR B unit as Output
In the Phase Correct PWM mode 5, the OCR0A register is used to hold the TOP value. Thus the output cannot be taken from the OC0A pin hence the output is only from the OC0B pin. In case of mode 5 the OCR0B register is used to set the duty cycle of the PWM. Important thing to remember is that the TOP value in OCR0A register must be less or equal to the Duty Cycle value in the OCR0B register.
The following C program illustrates how one can use the ATmega328P microcontroller to set it in the non-inverting Phase Correct PWM mode 5 with duty cycle of 40%(The duty cycle was calculated using the pwm duty cycle formula provided above), frequency of 15.69KHz, with TOP value of 200.
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
int main()
{
DDRD |= (1<<PD5); //Phase Correct PWM output at OC0B pin
OCR0A = 200; // Top Value of 200(must be equal or greater than Duty Cycle)
OCR0B = 102; // Duty cycle of 40%
TCCR0A |= (1<<COM0B1) | (1<<WGM00); //Non-Inverting Fast PWM mode 5
TCCR0B |= (1<<WGM02) | (1<<CS00); //No-Prescalar
while (1);
return 0;
}
The following circuit diagram shows Phase Correct PWM output at the OC0B pin.
(b) Inverting Phase Correct PWM mode
The Phase Correct PWM mode is selected either as mode 1 or mode 3 using the WGM bits(WGM02, WGM01 and WGM00) in the TCCR0A and TCCR0B registers. After selecting the Phase Correct PWM mode, the inverting mode is selected using the COM bits(COM0A1, COM0A0 when output is at OC0A pin or/and COM0B1, COM0B0 when output is at OC0B pin).
The frequency and duty cycle of the generated inverted Phase Correct PWM signal is calculated and used as follows.
Inverted Phase Correct PWM Frequency
The inverted phase correct PWM wave frequency for Timer0 is calculated using the following equation which is same as the frequency for non-inverted phase correct PWM frequency.
\[F_{w}=\frac{Fosc}{510N} \]
where, \(F{osc}\) is the CPU or crystal oscillator frequency and N is pre-scalar which can have value of 1, 8, 64, 256 and 1024.
For example, using equation (1), if we use pre-scalar N of 1 we can generate Phase Correct PWM signal of frequency 15.69KHz.
Inverted Phase Correct PWM Duty Cycle
The duty cycle of the inverted Phase Correct PWM signal is calculated using the following formula.
\[OCR0= 255 - \frac{255D}{100} \hspace{5cm}------------->(3)\]
where, D is the duty cycle 0% to 100%.
For
example if we want the PWM signal to have 40% duty cycle then using
equation (3), the value for the OCR0A is 153. We can also use the Online ATmega Timer/Counter calculator to determine the
count value to be loaded into the OCR0A register. An example is shown below.
Inverted Fast PWM mode 1 with output at OC0A
Below
is program code to generate inverted Phase Correct PWM signal at OC0A pin with
duty cycle of 40% with count value of 153 which is loaded into the OCR0A register and frequency
of 15.69KHz. The duty cycle was calculated using the pwm duty cycle
formula provided above.
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
int main()
{
DDRD |= (1<<PD6); //Phase Correct PWM output at OC0A pin
OCR0A = 153; // Duty cycle of 40%
TCCR0A |= (1<<COM0A1) | (1<<COM0A0) | (1<<WGM00); //Inverting Phase Correct PWM mode 1
TCCR0B |= (1<<CS00); //No-Prescalar
while (1);
return 0;
}
The following circuit diagram shows Phase Correct PWM output at the OC0A pin.
Inverted Fast PWM mode 1 with output at OC0B
Below
is program C code to generate inverted Phase Correct PWM signal at OC0B pin
with duty cycle of 40% corresponding to count value of 153 that is loaded into the OCR0B register(pwm duty
cycle formula is provided above) and frequency of 15.69KHz.
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
int main()
{
DDRD |= (1<<PD5); //Phase Correct PWM output at OC0B pin
OCR0A = 191; // Duty cycle of 40%
TCCR0A |= (1<<COM0B1) | (1<<COM0B0) | (1<<WGM00); //Inverting Phase Correct PWM mode 1
TCCR0B |= (1<<CS00); //No-Prescalar
while (1);
return 0;
}
The following circuit diagram shows inverted Fast PWM output at the OC0B pin.
Inverted Phase Correct PWM mode 5
For generating inverted Fast PWM in mode 5, we have to use the OCR0A for TOP value for counting. In this case we have loaded OCR0A top value of 200. This top value must be greater than the duty cycle value 153 for 40% duty cycle which is loaded into the OCR0B register. The duty cycle was calculated using the pwm duty cycle formula provided above. In case of mode 5, the output PWM signal is taken from OC0B pin. To use mode 5 we must set all the wave generation mode bits WGM02 located in TCCR0B and WGM00 which are located in TCCR0A register.
Following is the C program code for generating inverted Fast PWM signal in mode 7.
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
int main()
{
DDRD |= (1<<PD5); //Phase Correct PWM output at OC0A pin
OCR0A = 200; // Top Value of 200(must be equal or greater than Duty Cycle)
OCR0B = 153; // Duty cycle of 40%
TCCR0A |= (1<<COM0B1) | (1<<COM0B0) | (1<<WGM00); //Inverting Phase Correct PWM mode 5
TCCR0B |= (1<<WGM02) | (1<<CS00); //No-Prescalar
while (1);
return 0;
}
So in this atmega328p programming tutorial on generating PWM signals using timers in the
atmega328p chip, we have illustrated the Phase Correct PWM mode with example
code.
See the following examples of using PWM with Arduino, ATmega32A and ATmega328P.
Generate Sine Wave using Arduino PWM and Simulink
PWM Application Examples with Arduino Nano
PWM - Programming Arduino using Matlab
DC motor Speed control with Potentiometer and PWM using Arduino