Phase Correct PWM with ATmega328P

 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.

 

ATmega328p Phase Correct PWM mode

 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).

Phase Correct PWM output at the OC0A pin
 

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).

Phase Correct PWM output at the OC0B pin

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.

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.

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.

Phase Correct 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

Speed control of DC motor with PWM using Arduino

Programming ATmega32A Timer/Counter in Fast PWM mode


Post a Comment

Previous Post Next Post