Arduino can be used to generate different types of PWM(Pulse Width Modulation) signals which are Fast PWM and Phase Correct PWM signals. The PWM signal are used in different applications like DC motor speed control, as RC PWM signal for RC transmitter and receiver, generating sounds, as signals in telecommunications, power regulation, rectification, and DAC applications etc. Here Fast PWM signal generation with Arduino Uno timer/counter 0 is illustrated.
Arduino Uno board is based on ATmega328 microcontroller. The ATmega328 microcontroller has built in three timer/counters called Timer/Counter 0,Timer/Counter 1 and Timer/Counter 2. Each of the timer/counter is capable to generate different types of PWM signals.
Here we will be using Timer/Counter 0.
The hardware block diagram of the Timer/Counter 0 is shown below.
How Arduino generates Fast PWM signal?
Arduino generates Fast PWM signal by starting the timer and counting upto the value of count loaded into the OCR0A or OCR0B. The OCR0A and OCR0B registers are used to set the duty cycle of the Fast PWM signal. The frequency of the Fast PWM signal is set using the main clock frequency of the microcontroller and setting the value of pre-scalar in the TCCR0B register. The Fast PWM output is available on the pin OC0A((Port D Pin 6) or OC0B(port D pin 5) pin depending upon which output compare register A(OCR0A) or output compare register B(OCR0B) has been used. Furthermore, we can control the TOP value for the Fast PWM generation. Thus the Timer/Counter 0 has two modes for Fast PWM which are the mode 3 and mode 7. In mode 3, the TOP value is 0xFF and in mode 7 the TOP value is the count value loaded into the OCR0A register. Furthermore withing these modes(mode 3 or mode7) we can configure the PWM output as either non-inverting and inverting output.
The followings are important points to remember for configuring Fast PWM mode.
1. Frequency Control
The frequency of the PWM output is given by the following equation,
\(F_{w}=\frac{F_{osc}}{256N}\)
In the above equation \(F_{w}\) is the Fast PWM output wave frequency, \(F_{osc}\) is the microcontroller oscillator or CPU frequency and N is the pre-scalar value. N, the pre-scalar, can be set to have value of 1, 8, 64, 256 or 1024.The value of N is controlled using the CS00, CS01 and CS02 bits in the TCCR0B register which is shown below.
The table for CS bits(Clock Select bits) is below.
This frequency equation above holds for both the non-inverting Fast PWM and inverting Fast PWM.
2. Duty Cycle control
The duty cycle is controlled by loading count value into the OCR0A and/or OCR0B register. The duty cycle is different for non-inverting mode and inverting mode.
For non-inverting Fast PWM signal, the duty cycle formula is,
\(OCR0 = \frac{256D}{100} - 1\)
For inverting Fast PWM mode, the duty cycle formula is,
\(OCR0 = 255 - \frac{256D}{100}\)
3. Mode 3 and Mode7
There are two modes of Fast PWM which are mode 3 and mode 7. The difference is the TOP value. In mode 3, the TOP value is 0xFF whereas in mode 7 the top value is the value loaded into the OCR0A register. The mode 3 or mode 7 is selected using the waveform generation mode bits WGM02, WGM01, WGM00 located in the TCCR0A and TCCR0B registers.
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 table below shows the waveform generation mode bits WGM02, WGM01, WGM00 for configuring mode 3 and mode 7.
The Fast PWM signal frequency, duty cycle, non-inverting or inverting
nature etc are controlled using the following control registers TCCR0A
and TCCR0B.
4. Non-Inverting and Inverting Mode
We can choose whether to output inverting or non-inverting Fast PWM signal at the OC0A and OC0B pin. The Compare Output Mode bits COM0A1 and COM0A0 are used to configure inverting and non-inverting mode for output at OC0A pin and the COM0B1, COM0B0 bits are used to configure inverting and non-inverting mode for output at OC0B pin. The following table shows how to select the COM0A1, COM0A0 and COM0B1, COM0B0 bits for configuring non-inverting and inverting Fast PWM waveform.
These bits are located in the TCCR0A register.
Procedure for Programming Arduino in Fast PWM mode
1. Choose frequency for the Fast PWM output
2. Calculate the required pre-scalar value N for the chosen PWM frequency
3. Choose where to output the Fast PWM signal
4. Select which mode, mode 3 or mode 7 to be used
5. Select inverting or non-inverting mode
Programming Arduino in non-inverted Fast PWM mode
In this Arduino programming example, we will write program to generate non-inverting 976Hz Fast PWM signal on pin OC0A pin which is Arduino pin 6 or Port D Pin 6 on ATmega328p microcontroller with duty cyle of 75%.
To set PWM frequency to 976Hz with Arduino clock frequency of 16MHz and to set 75% duty cycle we can use the formula provided above or use the online calculator to calculate the pre-scalar value required and the count value to be loaded into the OCR0A register.
The calculated value for Pre-scalar N is 64 and the OCR0A count value is 191.
The following is the Arduino code for programming in non-inverted Fast PWM mode.
//source: https://ee-diary.blogspot.com
void setup () {
// Pin 6 (OC0A) is output
pinMode(6, OUTPUT);
// Load 191 to generate 75% PWM
OCR0A = 191;
// 976Hz non-inverted PWM on OC0A with prescalar 64
TCCR0A = (1 << COM0A1) | (1<<WGM01) | (1<<WGM00);
TCCR0B =(1 << CS01)|(1 << CS00);
}
void loop() {
}
In the above program, first we make the Arduino pin 6(OC0A pin) an output. The we load the count value of 191 into the OCR0A register to set the duty cycle to 75%. Then we configure the timer/counter 0 for Fast PWM mode, with pre-scalar set to 64 for 976Hz PWM frequency and in non-inverting mode by configuring the bits in TCCR0A and TCCR0B registers.
Testing with Malab/Simulink
We can test the generated Fast PWM from Arduino using Matlab/Simulink which is explained in details in How to test Arduino Fast PWM Signal with Matlab/Simulink. The time scope shows the Fast PWM waveform in real time which is shown below.
The following shows the spectrum analyzer showing the frequency spectrum of the PWM signal with peak at frequency 975Hz.
The following is video demonstration of testing the Fast PWM with Simulink.
Programming Arduino in inverted Fast PWM mode
In this Arduino programming example, we will write program to generate an inverting 244.14Hz Fast PWM signal on pin OC0B pin which is Arduino pin 5 (or Port D Pin 5 on ATmega328p microcontroller) with duty cyle of 65%.
To set PWM frequency to 7.81 KHz with Arduino clock frequency of 16MHz and to set 65% duty cycle we can use the formula provided above or use the online calculator to calculate the pre-scalar value required and the count value to be loaded into the OCR0B register.
The calculated value for Pre-scalar N is 256 and the OCR0B count value is 89.
The following is Arduino program code to output inverting Fast PWM wave on OC0B pin or pin 5 on Arduino.
void setup () {
// Pin 5(OC0B) is output
pinMode(5, OUTPUT);
// Load 89 to generate 65% fast PWM
OCR0B= 89;
//244.14Hz inverted fast PWM on OC0B with 1 prescalar
TCCR0A = (1 << COM0B1) | (1 << COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B = (1<<CS02);
}
void loop() {
}
In the above code, we first set the Arduino pin 6(OC0A pin) as an output. We then load the count value of 89 into the OCR0A register to set the duty cycle to 65%. Then we configure the timer/counter 0 for Fast PWM mode, with pre-scalar set to 256 for 244.14Hz PWM frequency and in non-inverting mode by configuring the bits in TCCR0A and TCCR0B registers.
Testing with Matlab/Simulink
The generated PWM signal can be tested with Matlab/Simulink which is explained in details in How to test Arduino Fast PWM Signal with Matlab/Simulink. The following pictures shows the Fast PWM wave and the frequency spectrum on the spectrum analyzer.
The frequency spectrum shows peak at frequency 234Hz.
The following is video demonstration of testing the Fast PWM with Simulink.
In this tutorial we showed how to write program for Arduino to generate Fast PWM signal in non-inverting mode and inverting mode with Time/Counter 0. We can also generate Fast PWM signal with Timer/Counter 1 and Timer/Counter 2 which is illustrated in the following tutorials.
- Programming Arduino Timer 2 in Fast PWM mode