Programming Arduino Timer 1 in Fast PWM mode

 In this tutorial Fast PWM mode of Timer 1 of Arduino is explained with arduino 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 2 see Programming Arduino Timer 2 in Fast PWM mode.  

Timer 1 PWM pins

With timer 1, on Arduino Uno the fast PWM signal is generated either on pin 9(PB1/OC1A) or pin 10(PB2/OC1B) or on both of them as shown below.

 

Arduino uno Timer1 PWM pins

Timer  2 Registers

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

1. TCCR1A

2. TCCR1B

3. OCR1A/OCR1B depending upon the channel A or B used

4. TIFR1(Optional)

5. TIMSK1(Optional)

 

Fast PWM modes with Timer 1

The Timer 1 has the following Fast PWM modes:

1) Mode 5: 8-bit Fast PWM with TOP at 0x00FF 

2) Mode 6: 9-bit Fast PWM with TOP at 0x01FF

3) Mode 7: 10-bit Fast PWM with TOP 0x03FF

4) Mode 14: Fast PWM with TOP at ICR1

5) Mode 15: Fast PWM with TOP at OCR1A

 

1) Mode 5: 8-bit Fast PWM with TOP at 0x00FF

In this mode, the TOP is 0x00FF when the timer/counter 1 OCR0A/OCR0B is loaded with count value, it counts up to the 0x00FF and when match occurs, the output on OC0A/OC0B pin can be either be cleared or set on compare match. When the output is cleared we get non-inverted Fast PWM waveform and when the output is set we get inverted Fast PWM waveform.

The frequency of the generated Fast PWM signal is given by,

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

With \(F_{w}\) of 16MHz, and no pre-scalar N = 1 we get frequency of 62.5KHz

For non-inverted Fast PWM, the duty cycle is calculated using the following equation.

\[OCR1A(or OCR1B) = \frac{256D}{100} - 1\] 

where D is the duty cycle in %. 

For example for 25% duty cycle the calculated value of OCR1A is 63.

The frequency and OCR1A/OCR1B value for given duty cycle can be calculated using the ATmega microcontroller online Timer calculator.

The following Arduino program illustrates Fast PWM. Here a non-inverted Fast PWM of frequency 62.5KHz and duty cycle of 25% is generated on pin 9(OC1A) pin.

void setup () {
// Pin 9(OC1A) is output
pinMode(9, OUTPUT);
// Load 63 to generate 62.5KHz fast PWM
OCR1A= 63;
// non-inverted fast PWM on OC1A with prescalar of 1
TCCR1A = (1<<COM1A1) | (1<<WGM10);
TCCR1B = (1<<WGM12) | (1<<CS10);
}

void loop() {
}

The following shows waveform generated on PWM pin 9 with duty cycle of 25%.

PWM pin 9 with duty cycle of 25%

And the following figure shows Fourier transform of the same PWM waveform above at frequency 62.5KHz.

 

Fourier transform of PWM signal at 62.5KHz

For inverted Fast PWM the duty cycle is calculated using the following formula.

\[OCR1A(or OCR1B) = 255 - \frac{256D}{100}\]

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

The following Arduino program illustrates Fast PWM generation using Arduino. Here we generate inverted Fast PWM signal on pin 10 of Arduino(OC1B) of frequency 7.81KHz using prescalar of 8 and duty cycle of 60% by loading 101 into the OCR1B register.

void setup () {
// Pin 10(OC1B) is output
pinMode(10, OUTPUT);
// Load 101 to generate 7.81KHz fast PWM
OCR1B= 101;
// inverted fast PWM on OC1B with prescalar of 8
TCCR1A = (1<<COM1B1) | (1<<COM1B0) | (1<<WGM10);
TCCR1B = (1<<WGM12) | (1<<CS11);
}
void loop() {
}

 The following shows non-inverted fast PWM signal with frequency of 7.81KHz and duty cycle of 60%.

 

The following shows Fourier transform of the above PWM signal.


2) Mode 6: 9-bit Fast PWM with TOP at 0x01FF

In the following Arduino program Fast PWM is generated. Here, the Timer 1 is configured to operate in inverted Fast PWM mode(mode 6), using channel A so that the output is on OC1A pin or Arduino pin 9, and with frequency of 3.910KHz obtained using the pre-scalar of 8 and duty cycle of 75%.

void setup () {
// Pin 9(OC1A) is output
pinMode(9, OUTPUT);
// Load 127 to generate 3.910KHz fast PWM
OCR1A = 127;
// inverted fast PWM on OC1A with prescalar of 8
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<CS11);
}

void loop() {

}

 

The following figures shows waveform and Fourier transform of fast PWM with frequency of 3.91KHz and duty cycle of 75%.


 


3) Mode 7: 10-bit Fast PWM with TOP 0x03FF

 In this example of Fast PWM with Arduino we generate Fast PWM signal on pin 10 on Arduino using Timer 1 channel B. The output is non-inverted Fast PWM signal with frequency of 15.63KHz and duty cycle of 65%.

void setup () {
// Pin 10(OC1B) is output
pinMode(10, OUTPUT);
// Load 665 to generate 65% duty cycle fast PWM
OCR1B = 665;
// non-inverted fast PWM on OC1b with prescalar of 1 for 15.630KHz fast PWM
TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10);
TCCR1B = (1<<WGM12) | (1<<CS10);
}

void loop() {
}

The following shows the fast pwm waveform and Fourier transform of the generated Fast PWM signal with frequency of 15.63KHz and duty cycle of 65%.



4) Mode 14: Fast PWM with TOP at ICR1

 In this mode, TOP value is loaded into ICR1 register. The frequency and duty cycle of the output wave depends upon the compare output mode COM bits setting which can be either toggle, non-inverted or inverted mode. 

Frequency

In toggle mode, the frequency is given by the following equation,

\[F_{w}= \frac{F_{cpu}}{2N(1+ICR1)}\] 

For example for Arduino with 16MHz cpu frequency, and no-prescalar N=1 and ICR1 value of 200 we get frequency of 39.8KHz.

If either non-inverted or inverted mode is used then the frequency is given by,

\[F_{w}= \frac{F_{cpu}}{N(1+ICR1)}\]

 Duty Cycle

If the compare output mode is set to toggle either on channel A or B then the duty cycle is fixed to 50%. This means in this setting the output is a square wave with frequency given by the above equation.

If the COM bits are set to either inverting and non-inverting then the duty cycle cycle is given by the following equations.

For non-inverted mode,

\[Duty Cycle = \frac{OCR1}{ICR1} *100\] 

where Duty Cycle is in % and OCR1 can be either the OCR1A or OCR1B depending upon which channel is being used.

And for inverted mode

\[Duty Cycle = (1 - \frac{OCR1}{ICR1}) *100\]

 

 Example 1: Toggled Fast PWM on Arduino pin 9

In the following Arduino Fast PWM example, a square wave of frequency 39.8KHz is generated on Arduino pin 9(OC0A pin). To generate this frequency we load 200 into the ICR1 register. 

void setup () {  
// Pin 9(OC1A) is output
pinMode(9, OUTPUT);
// Load 200 into ICR1 to generate 39.8KHz sq.wave PWM
ICR1 = 200;
// toggled fast PWM on OC1A with prescalar of 1 for 39.8KHz fast PWM
TCCR1A = (1<<COM1A0) | (1<<WGM11); 
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
}

void loop() {
}

 The following pictures shows the generated Fast PWM signal with its Fourier transform.


fourier transform of toggled Fast PWM

Example 2: Non-Inverted Fast PWM on Arduino pin 10

 In this example a non-inverted Fast PWM  waveform is generated on Arduino pin 10(OC0B pin). The frequency and duty cycle formula are provided above. Here 320 is loaded into ICR1 register to obtain 50KHz signal and 256 is loaded into the OCR1B register to obain 80% duty cycle.

void setup () {  
// Pin 10(OC1B) is output
pinMode(10, OUTPUT);
// Load 320 into ICR1 to generate 50KHz sq.wave PWM
ICR1 = 320;
//Load 127 into OCR1B for 80% duty cycle
OCR1B = 256;
// non-inverted fast PWM on OC1B with prescalar of 1 for 50KHz fast PWM
TCCR1A = (1<<COM1B1) | (1<<WGM11);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
}

void loop() {
}

The following graph shows the output Fast PWM wave and its Fourier Transform.



Example 3: Inverted Fast PWM on Arduino pin 9

 In this example inverted Fast PWM signal is generated on Arduino pin 9(OC0A) with frequency of 31.9KHz and duty cycle of 80%. To get 31.9KHz signal we load 500 into ICR1 register and to get 80% duty cycle we load 100 into the OCR1A register.

void setup () {
// Pin 9(OC1A) is output
pinMode(9, OUTPUT);
// Load 500 into ICR1 to generate 31.9KHz sq.wave PWM
ICR1 = 500;
//Load 100 into OCR1A for 80% duty cycle
OCR1A = 100;
// inverted fast PWM on OC1A with prescalar of 1 for 31.9KHz fast PWM
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
}

void loop() {
}


The following graph shows the Fast PWM waveform and its Fourier transform.


 

5) Mode 15: Fast PWM with TOP at OCR1A

In this mode, OCR1A is used to hold the top value for the timer 1.

The frequency and duty cycle depends upon which mode- toggle mode or inverted/non-inverted mode is used.

Toggle Mode

The frequency is used in toggle mode is given by the following formula.

\[F_{w}= \frac{F_{cpu}}{2N(1+OCR1A)}\] 

For example, with Fcpu of 16MHz for Arduino, N=1 and OCR1A=250 we get frequency of 31.87KHz.

The duty cycle in toggle mode is fixed which is 50%.

Example 1: Toggle mode

The following code is used to configure the Timer 1 in toggle and Fast PWM mode. It generates square wave of frequency 31.87 and duty cycle of 50% on Arduino pin 9(OC0A pin). To generate 31.87KHz signal the OCR1A is loaded with value of 250 and no pre-scalar is used.

void setup () {
// Pin 9(OC1A) is output
pinMode(9, OUTPUT);
//Load 250 into OCR1A for 31.9Khz
OCR1A = 250;
// toggled fast PWM on OC1A with prescalar of 1 for 31.9KHz fast PWM
TCCR1A = (1<<COM1A0) | (1<<WGM11) | (1<<WGM10);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);

void loop() {
}

The following graph shows toggled output Fast PWM signal with its Fourier transform.

 



 

Non-Inverted and Inverted Mode

The frequency in case of non-inverted or inverted mode is given by,

\[F_{w}= \frac{F_{cpu}}{N(1+OCR1A)}\]

The duty cycle is determined as follows.

For non-inverted mode,

\[Duty Cycle = \frac{OCRB1}{OCRA1} *100\] 

where Duty Cycle is in % and OCR1 can be either the OCR1A or OCR1B depending upon which channel is being used.

And for inverted mode

\[Duty Cycle = (1 - \frac{OCRB1}{OCRA1}) *100\]

 

Example 2: Non-Inverted Mode

In this Arduino Fast PWM example, we generate non-inverted Fast PWM on Arduino pin 10(OC0B pin), with frequency of 15.98KHz and duty cycle of 20%. The frequency is obtained when the pre-scalar is set to 1, and 1000 is loaded into the OCR1A register. The 20% duty cycle is obtained by loading the OCR1B register with 200.

void setup () {
// Pin 10(OC1B) is output
pinMode(10, OUTPUT);
//Load 1000 into OCR1A for 15.98KHz
OCR1A = 1000;
//Load 200 into OCR1B for 20% duty cycle
OCR1B = 200;
// non-inverted fast PWM on OC1B with prescalar of 1 for 15.98KHz fast PWM
TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10); 
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
}

void loop() {
}

The following shows the non-inverted, fast PWM waveform and its Fourier transform.



Example 3: Inverted Mode

In this Arduino Fast PWM example, we generate inverted Fast PWM on Arduino pin 10(OC0B pin), with frequency of 15.98KHz and duty cycle of 80%. The frequency is obtained when the pre-scalar is set to 1, and 1000 is loaded into the OCR1A register. The 80% duty cycle is obtained by loading the OCR1B register with 200.

void setup () {
// Pin 10(OC1B) is output
pinMode(10, OUTPUT);
//Load 1000 into OCR1A for 15.98KHz
OCR1A = 1000;
//Load 200 into OCR1B for 80% duty cycle
OCR1B = 200;
// inverted fast PWM on OC1B with prescalar of 1 for 15.98KHz fast PWM
TCCR1A = (1<<COM1B1) | (1<<COM1B0) | (1<<WGM11) | (1<<WGM10);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
}
void loop() {
}

The following shows the non-inverted, fast PWM waveform and its Fourier transform.


 

 



Post a Comment

Previous Post Next Post