Reputation: 29
Using my Arduino Mega 2560 I am trying to generate a PWM signal where I can change both PWM frequency and Duty Cycle. For that I decided to use Timer2 OC2A output. The code is the following one:
void setup()
{
// ======================================================
// Timer 2 example: Phase and Frequency correct PWM
// ======================================================
pinMode(10, OUTPUT);
TCCR2A = 0;//reset the register
TCNT2 = 0;
TCCR2A = 0b10000001; // COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
// 1 0 0 0 0 0 0 1
// Behavior: PWM on OC2A (Arduino pin 10) ; Waveform generation mode 5 (Phase and Frequency Correct)
TCCR2B = 0b00001001; // FOC2A FOC2B - - WGM22 CS22 CS21 CS20
// 0 0 0 0 1 0 0 1
// Behavior: Waveform generation mode 5 (Phase and Frequency Correct) ; Prescaler -> clk/1
OCRA = 319; // TOP value -> defines de PWM frequency (25 kHz)
OCR2A = 159; // duty cycle value (80% of ICR1)
}
void loop()
{
}
When I try to compile I get the following error:
PWM_Mega.ino:43:3: note: suggested alternative: 'OCR2A'
OCRA = 319; // TOP value -> defines de PWM frequency (25 kHz)
^~~~
OCR2A
exit status 1
'OCRA' was not declared in this scope
I understand the error is because OCRA is not defined. In the uC datasheet (see picture below), mode 5 TOP, that defines the PWM frequency, is defined using register OCRA but when I put that name into my code, it is not recognized. Does anyone know the name of that register so that I can use it in the code?
Thanks
Upvotes: 1
Views: 1570
Reputation: 29
Many thanks, KIIV! That was exactly the point. But then I have to say that the uC datasheet is not well documented.
In order to help others having similar issues using Timer2 for PWM generation, I will post down the working code that I have tested on my Arduino Mega for three PWM Modes (1, 3 and 5). You can find also the cheat sheet I have prepared for myself. Anyone feel free to review it and comment if necessary:
ATMega 2560: Cheat sheet Timer 2 for PWM generation
// PWM generation using the Arduino Mega 2560 Rev. 3
#include "Arduino.h"
void setup()
{
// // ==========================================================
// // Timer 2 example: Phase correct PWM (8 bit) ; Mode 1
// // ==========================================================
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
TCCR2A = 0;//reset the register
TCCR2B = 0;//reset the register
TCNT2 = 0;
TCCR2A = 0b10100001; // COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
// 1 0 1 0 0 0 0 0
// Behavior: PWM on OC2A and OC2B (Pins 9 and 10) ; Waveform generation mode 1 (Phase correct PWM ; TOP = 255)
TCCR2B = 0b00000010; // FOC2A FOC2B - - WGM22 CS22 CS21 CS20
// 0 0 0 0 0 0 1 0
// Behavior: Waveform generation mode 1 (Phase correct PWM ; TOP = 255) ; Prescaler -> clk/8
// Note: fpwm = fclk/(N·2·255) --> N = pre-scaler factor
// = 16M /(8·2·255) = 3.92 kHz
OCR2A = 10; // duty cycle value (4% PWM)
OCR2B = 100; // duty cycle value (40% PWM)
// // =================================================
// // Timer 2 example: Fast PWM (8 bit) ; Mode 3
// // =================================================
// pinMode(9, OUTPUT);
// pinMode(10, OUTPUT);
// TCCR2A = 0;//reset the register
// TCCR2B = 0;//reset the register
// TCNT2 = 0;
//
// TCCR2A = 0b10100011; // COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
// // 1 0 1 0 0 0 1 1
// // Behavior: PWM on OC2A (Arduino pin 10) ; Waveform generation mode 3 (Fast PWM ; TOP = 255)
//
// TCCR2B = 0b00000100; // FOC2A FOC2B - - WGM22 CS22 CS21 CS20
// // 0 0 0 0 0 1 0 0
// // Behavior: Waveform generation mode 3 (Normal PWM ; TOP = 255) ; Prescaler -> clk/64
//
// // Note: fpwm = fclk/(N·256) --> N = pre-scaler factor
// // = 16M /(64·256) = 976 Hz
//
// OCR2A = 10; // duty cycle value (4% PWM)
// OCR2B = 100; // duty cycle value (40% PWM)
// ===========================================================================
// Timer 2 example: Phase and Frequency correct PWM (8 bit) ; Mode 5
// ===========================================================================
// pinMode(9, OUTPUT);
// TCCR2A = 0;//reset the register
// TCCR2B = 0;//reset the register
// TCNT2 = 0;
//
// TCCR2A = 0b00100001; // COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
// // 0 0 1 0 0 0 0 1
// // Behavior: PWM on OC2B (Arduino pin 9) ; Waveform generation mode 5 (Phase and Frequency Correct)
//
// TCCR2B = 0b00001010; // FOC2A FOC2B - - WGM22 CS22 CS21 CS20
// // 0 0 0 0 1 0 1 0
// // Behavior: Waveform generation mode 5 (Phase and Frequency Correct) ; Prescaler -> clk/8
//
// // Note: fpwm = fclk/(N·(2·TOP) --> N = pre-scaler factor
// // = 16M /(8·2·100) = 10 kHz
//
// OCR2A = 100; // TOP value -> defines de PWM frequency (10 kHz)
// OCR2B = 50; // duty cycle value (50% Duty Cycle)
}
void loop()
{
}
Upvotes: 1
Reputation: 3739
As you want to change the Timer2 frequency you'll have to sacrifice channel A (unlike Timer1 there is no input capture register, that can be used as TOP value)
The OCRA in the image means OCR2A (OCR2A means: Output Compare Register for timer2 channel A)
Therefore you can use only channel B as PWM output
note: Timer2 is 8b only and values like 319 (0x13F) will overflow into 63 (0x3F)
Upvotes: 0