Programming Arduino Timer 0 in Fast PWM mode

 In this tutorial Fast PWM mode of Timer 0 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 has three timer/counter unit called Timer/Counter 0, Timer/Counter 1 and Timer/Counter 2. 

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

Programming Arduino in Fast PWM mode

 The Timer/Counter 0 is configured using the following registers.

1. TCCR0A

2. TCCR0B

3. OCR0A/OCR0B depending upon the channel A or B used

4. TIFR0(Optional)

5. TIMSK0(Optional)

 

The TCCR0A and TCCR0B contains three Waveform Generation Mode(WGM) bits called WGM00, WGM01 and WGM02, two Compare Output Mode(COM) bits called COM00 and COM01 and three Clock Select(CS) bits called CS02, CS01 and CS00. 

The WGM bits are used to set waveform generation mode which can be normal, CTC, Fast PWM and Phase Correct PWM.  The COM bits are used to control the type of output at the output compare pins OC0A and OC0B. The CS bits are used to control the frequency of the output PWM signal.

Each Timer/Counter has two output compare pins called OC0A and OC0B. The Timer/Counter 0 output compare pins OC0A and OC0B are called PWM pins 6 and 5 respectively on Arduino board. These Timer 0 pins on Arduino Uno are shown below.

Arduino Uno Timer 0 PWM pins

 

 The Timer 1 OC1A and OC1B pins are called PWM pins 9 and 10 respectively on Arduino board. Similarly, the Timer 2 OC2A and OC2B pins are called PWM pins 11 and 3 respectively on Arduino board.

Fast PWM modes with Timer 0

Each Timer of Arduino has different modes of Fast PWM.

The Timer 0 has the following Fast PWM mode:

1) Mode 3: Fast PWM with TOP at 0xFF

2) Mode 7: Fast PWM with TOP at OCRA(or OCRB)

 

1) Mode 3: Fast PWM with TOP at 0xFF

In this Fast PWM mode, the TOP value to which the counter compares match is 0xFF. When the count matches the TOP value, match occurs and output is triggered at the OC0A/OC0B pin. The output can be either set to no output at all(OC0A/OC0B disconnected) or non-inverted or inverted output. The type of output(inverted or non-inverted) depends on the COM bit 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,64,256 or 1024.

The following are Arduino Fast PWM examples and Arduino PWM example code.

1.1 Non-Inverted Fast PWM with Timer 0 on OC0A(Arduino pin 6)

In this example we will generate non-inverted Fast PWM signal on Arduino pin 6(OC0A pin) using Timer 0. We can use the formula provided above to calculate the duty cycle and frequency of the PWM signal(or you can also use the online ATmega microcontroller Timer/Counter calculator).

If we want duty cycle of 75%, the value of OCR0A is 191 using the duty cycle formula for non-inverted PWM. If we use prescalar of 1, then we get PWM frequency of 62.5KHz.

The following program code generates non-inverted Fast PWM wave with duty cycle of 75% and frequency 62.5KHz.

//source: https://ee-diary.com

void setup () {
  // Pin 6 (OC0A) is output
  pinMode(6, OUTPUT);  
   // Load 191 to generate 75% PWM
  OCR0A = 191;
   // 62.5kHz non-inverted PWM on OC0A with no prescalar
  TCCR0A = (1 << COM0A1) | (1<<WGM01) | (1<<WGM00); 
  TCCR0B = (1 << CS00); 
}
void loop() {
}

The following shows schematic diagram for PWM output to a LED connected to the pin 11 on Arduino Uno.

The following shows graph of 75% duty cycle fast PWM signal.

 

The following graph is Fourier Transform of the PWM signal which shows frequency of the PWM is 62.5KHz.


 An example application of this is driving a DC motor using L298N and Arduino. See the arduino electronics tutorial Speed and direction control of DC motor using Arduino Fast PWM.

1.2 Inverted Fast PWM with Timer 0 on OC0A(Arduino pin 6)

In this example, inverted Fast PWM signal is generated on OC0A pin(Arduino pin 6) with duty cycle of 60% and frequency of 976.560Hz. For duty cycle of 60% in inverted mode, the OCR0A register is loaded with 101. With Fcpu of 16MHz, and pre-scalar of 64, the PWM frequency is 976.560Hz.

void setup () {
  // Pin 6 (OC0A) is output
  pinMode(6, OUTPUT);  
   // Load 101 to generate 60% fast PWM
  OCR0A = 191;
   // 976.560Hz inverted fast PWM on OC0A with 64 prescalar
  TCCR0A = (1 << COM0A1) | (1 << COM0A0) | (1<<WGM01) | (1<<WGM00); 
  TCCR0B = (1<<CS01) | (1 << CS00); 
}

void loop() {
}

 The following shows graph of 60% duty cycle fast PWM signal.

 


The following graph is Fourier Transform of the PWM signal which shows frequency of the PWM is 976.560Hz. 


1.3 Non-Inverted Fast PWM with Timer 0 on OC0B(Arduino pin 5)

 In this example, non-inverted Fast PWM signal is generated on OC0B pin(Arduino pin 5) with duty cycle of 80% and frequency of 7.810KHz. For duty cycle of 80% in non-inverted mode, the OCR0A register is loaded with 204. With Fcpu of 16MHz, and pre-scalar of 8, the PWM frequency is 7.810KHz.

void setup () {
  // Pin 5(OC0B) is output
  pinMode(5, OUTPUT);  
   // Load 204 to generate 80% fast PWM
  OCR0B= 204;
   // 7.810KHz non-inverted fast PWM on OC0B with 8 prescalar
  TCCR0A = (1 << COM0B1) | (1<<WGM01) | (1<<WGM00); 
  TCCR0B = (1<<CS01); 
}

void loop() {
}

  The following shows graph of 80% duty cycle fast PWM signal.

 The following graph is Fourier Transform of the PWM signal which shows frequency of the PWM is 7.810KHz.


1.4 Inverted Fast PWM with Timer 0 on OC0B(Arduino pin 5)

 In this example, inverted Fast PWM signal is generated on OC0B pin(Arduino pin 5) with duty cycle of 80% and frequency of 62.5KHz. For duty cycle of 80% in non-inverted mode, the OCR0B register is loaded with 165. With Fcpu of 16MHz, and pre-scalar of 1, the PWM frequency is 62.5KHz.

void setup () {
  // Pin 5(OC0B) is output
  pinMode(5, OUTPUT);  
   // Load 165 to generate 35% fast PWM
  OCR0B= 165;
   // 62.5KHz inverted fast PWM on OC0B with 1 prescalar
  TCCR0A = (1 << COM0B1) | (1 << COM0B0) | (1<<WGM01) | (1<<WGM00); 
  TCCR0B = (1<<CS00); 
}

void loop() {
}

 The following shows graph of 35% duty cycle fast PWM signal.

The following graph is Fourier Transform of the PWM signal which shows frequency of the PWM is 976.560Hz. 


 

2) Mode 7: Fast PWM with TOP at OCR0A

 With mode 7 Fast PWM the TOP is OCR0A. In this mode with channel A, we can either toggle OC0A pin to create square waveform output, generate non-inverted Fast PWM or generate inverted Fast PWM with different duty cycle and frequency. With channel B, we can either generate non-inverted Fast PWM or generate inverted Fast PWM with different duty cycle and frequency.

The following are Arduino Fast PWM examples and Arduino PWM example code.

2.1 Toggled Fast PWM with Timer 0 on OC0A(Arduino pin 6)

 When using channel A, we can set the output at OC0A pin to toggled mode. The counter counts up until the Top value in OCR0A register is reached and match occurs. When match occurs the output at OC0A pin is toggled. Since the output is toggled the duty cycle is fixed at 50%. The frequency in this toggle mode is given by,

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

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

This wave frequency formula is same as the one for CTC mode. So this mode 7 Fast PWM toggle mode is same as CTC mode. See Arduino CTC mode Programming with Examples.

For generating 100khz square wave signal using the frequency formula above with pre-scalar of 1 or using the CTC mode Timer online calculator, the value to be loaded into the OCR0A is 79. In the following code, square wave(duty cycle of 50%) with frequency of 79 is generated on OC0A pin.

void setup () {
  // Pin 6(OC0A) is output
  pinMode(6, OUTPUT);  
   // Load 79 to generate 100KHz toggled fast PWM
  OCR0A= 79;
   // toggled fast PWM on OC0A with prescalar of 1
  TCCR0A = (1 << COM0A0) | (1<<WGM01) | (1<<WGM00); 
  TCCR0B = (1<<WGM02) | (1<<CS00); 
}

void loop() {
}

The following shows the toggled output using mode 7 on OC0A pin.

toggled output using mode 7 on OC0A pin

The following shows Fourier Transform of the above square wave at 100KHz.

toggled output using mode 7 on OC0A pin

2.2 Non-Inverted Fast PWM with Timer 0 on OC0B(Arduino pin 5)

In this example a non-inverted Fast PWM signal is generated using Arduino on pin 5(OC0B pin). The formula for the frequency and duty cycle for non-inverted PWM is given by the following equations.

 Frequency:

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

that is,

\[OCR0A = \frac{F_{cpu}}{N F_{w}}-1\] 

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

Duty Cycle:

\[Duty Cycle(D) = \frac{OCR0B}{OCR0A}*100\] 

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

 Using the frequency formula, with pre-scalar of 1, and 16MHz clock frequency we get frequency of 200KHz if OCR0A value is 79. Then for duty cycle of 50%, the value of OCR0B is 40.

The following program generates non-inverted Fast PWM signal on OC0A pin with frequency of 200KHz and duty cycle of 50%.

void setup () {
  // Pin 5(OC0B) is output
  pinMode(5, OUTPUT);  
   // Load 79 into OCR0A to generate 200KHz fast PWM
  OCR0A = 79;
  // Load 40 into OCR0B to get duty cycle of 50%
  OCR0B = 40;
   // non-inverted fast PWM on OC0B with prescalar of 1
  TCCR0A = (1 << COM0B1) | (1<<WGM01) | (1<<WGM00); 
  TCCR0B = (1<<WGM02) | (1<<CS00); 
}

void loop() {
}

 The following shows waveform and Fourier transform of the 50% duty cycle 200KHz non-inverted waveform.


 


2.3 Inverted Fast PWM with Timer 0 on OC0B(Arduino pin 5)

In this example inverted Fast PWM signal is generated using Arduino on pin 5(OC0B pin). The formula for the frequency and duty cycle for inverted PWM is given by the following equations.

 Frequency:

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

that is,

\[OCR0A = \frac{F_{cpu}}{N F_{w}}-1\] 

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

Duty Cycle:

\[Duty Cycle(D) = 100 - \frac{OCR0B}{OCR0A}*100\] 

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

 Using the frequency formula, with pre-scalar of 1, and 16MHz clock frequency we get frequency of 500KHz if OCR0A value is 31. Then for duty cycle of 20%, the value of OCR0B is 25.

The following program generates non-inverted Fast PWM signal on OC0A pin with frequency of 500KHz and duty cycle of 50%.

void setup () {
  // Pin 5(OC0B) is output
  pinMode(5, OUTPUT);  
   // Load 31 to generate 500KHz fast PWM
  OCR0A= 31;
	// Load 25 into OCR0B for 20% duty cycle
	OCR0B = 25;
   // inverted fast PWM on OC0B with prescalar of 1
  TCCR0A = (1<<COM0B1) | (1 << COM0B0) | (1<<WGM01) | (1<<WGM00); 
  TCCR0B = (1<<WGM02) | (1<<CS00); 
}

void loop() {
}

 The following shows the 20% duty cycle 500KHz inverted waveform.

 

20% duty cycle 500KHz inverted waveform

The following shows the Fourier transform.


 

Post a Comment

Previous Post Next Post