Programming Arduino Timer 2 in Fast PWM mode

 In this Arduino electronics tutorial Fast PWM mode of Timer 2 of Arduino is explained with program example codes. 

The Arduino is based on the ATmega328p microcontroller. PWM(Pulse Width Modulation) signal is generated by configuring the Timer/Counter unit inside the microcontroller. The Arduino/ATmega328p has three timer/counter unit called Timer/Counter 0, Timer/Counter 1 and Timer/Counter 2. 

For Fast PWM with Timer 0 see Programming Arduino Timer 0 in Fast PWM mode and for Timer 1 see Programming Arduino Timer 1 in Fast PWM mode

Timer 2 PWM pins

With timer 2, on Arduino Uno the fast PWM signal is generated either on pin 3(PB3/OC2A) or pin 11(PD3/OC2B) or on both of them as shown below.

Arduino Uno Timer 2 PWM pins

 The Arduino Uno broad uses the ATmega328p microcontroller and on this microcontroller IC, the corresponding pins for the timer 2 fast PWM are pin PB3(OC2A) or pin PD3(OC2B) or on both of them.

Timer 2 PWM pins

Registers

The Timer/Counter 2 is configured by using the following registers.

1. TCCR2A

2. TCCR2B

3. OCR2A/OCR2B depending upon the channel A or B used

4. TIFR2(Optional)

5. TIMSK2(Optional)

Timer 2 Fast PWM modes

The Timer 2 has the following Fast PWM mode:

1) Fast PWM with TOP at 0xFF

2) Fast PWM with TOP at OCRA

2) Mode 7: Fast PWM with TOP at OCR0A

 In this Fast PWM mode, the TOP value to which the counter compares match is OCR0A. When the count matches the TOP value, match occurs and output is triggered at either the OC0A/OC0B pin or both. The output can be either set to toggle or non-inverted or inverted output on the OC0A/OC0B. The type of output(toggle, inverted or non-inverted) depends on the COM bits setting. 

The duty cycle of the PWM is set by loading the OCRxA or OCRxB register.

For non-inverted mode, the Duty Cycle formula is as follows:

\[OCR0 = \frac{256D}{100} - 1\] where D is the duty cycle in range 0% to 100%

For inverted mode, the Duty Cycle formula is as follows:

\[OCR0 = 255 - \frac{256D}{100}\]

where D is the duty cycle in range 0% to 100%
 

The Clock Select(CS) bits are used to set the frequency of the PWM signal.

The frequency of the Fast PWM wave for Timer 2 can be calculated using the following formula:

\[F_{w}= \frac{F_{cpu}}{256N}\] 

where, \(F_{cpu}\) is the Arduino clock frequency which is 16MHz and N is the pre-scalar value that can be either 1,8,32,64,128,256 or 1024.

Example 2: Mode 3 Fast PWM, Inverted PWM using Timer 2 on OC2B

In this example we will generate fast PWM signal on OC2B pin which is PD3 pin on ATmega328P and pin 3 on the Arduino. The duty cycle of the PWM signal is 75%. For this duty cycle we can calculate the value to be loaded into the OCR2B register using the formula for duty cycle for inverted mode provided above. The value to be loaded is 63 for 75% duty cycle. The formula for the frequency is the same as for the case of non-inverted mode. The frequency is 500Hz using pre-scalar of 128.


void setup () {
	DDRD |= (1<<PD3);
	OCR2B = 63;
	TCCR2A = (1<<COM2B1) | (1<<COM2B0) | (1<<WGM21) | (1<<WGM20);
	TCCR2B = (1<<CS22) | (1<<CS20);
}

void loop() {

}

 

 Example 3: Mode 3 Fast PWM with varying PWM duty cycle

In this example, a varying duty cycle PWM signal is generated using Timer 2 Output Compare unit B that is used to control the brightness of a LED. The duty cycle is increased from 0% to 100% and from 100% back to 0%. The output is from the OC0B pin(PD3 pin)which is pin 3 on Arduino. To do this we have to first declare the PD3 pin as output. Then we load variable duty cycle value into the OCR2B register which will increase and decrease with 5ms delay. In this example code we have used delay() built in function of Arduino. This delay() function uses Timer 0 internally so using this example code with Timer 0 will not work as expected. The frequency is the same as before which is 500Hz.

The following is the code.

void setup () {
	DDRB |= (1<<PB3);
}

void loop() {
	for(int k=0; k < 255; k++){
		pwmfunc(k);
		delay(5);
	}
	for(int k = 255; k >0; k--){
		pwmfunc(k);
		delay(5);
	}
}

void pwmfunc(int dc){
	OCR2B = dc;
	TCCR2A = (1<<COM2B1) | (1<<WGM21) | (1<<WGM20);
	TCCR2B = (1<<CS22) | (1<<CS20);
}

 

The following video demonstrates the brightness control using Timer 2 Fast PWM.


 

Post a Comment

Previous Post Next Post