Hi, I'm trying to set up a fast PWM signal using timer 3 on my Mega2560.
I have set up the hardware registers how i believe they should be set up, however I must be missing something as I am getting no PWM output on pin OC3A (D5) whatsoever.
Could someone review my setup function below and let me know if anything stands out please?
void setup() {
//Reset all applicable register values
TCCR3A = 0;
TCCR3B = 0;
TCNT3 = 0;
//Set timer 3 mode to FAST PWM using WGM30, WGM31, WGM32, WGM33 set to 1
//This includes CTC so that the counter is reset when OCR3A is met
TCCR3A |= (1 << WGM30) | (1 << WGM31);
TCCR3B |= (1 << WGM32) | (1 << WGM33);
//Set the compare output mode for Timer 3 Channel A (Set OC3A on compare match)
TCCR3A |= (1 << COM3A1) | (1 << COM3A0);
//Set time prescaler to 1/8
TCCR3B |= (1 << CS31);
//Set output compare value...
//In 1/8 mode: 50pps = (16MHz/8)/50 = 40000
// 10000pps = (16MHz/8)/10000 = 200
OCR3A = 40000;
//Check registers to verify bit settings
Serial.begin(9600);
Serial.println(TCCR3A, BIN);
Serial.println(TCCR3B, BIN);
}
You are using WGM 15 (0b1111) which uses OCR3A for "TOP". You can't also use OCR3A for PWM. Try OCR3B or OCR3C for your PWM output. Or use WGM 14 (0b1110) to use ICR3 for "TOP". That will leave OCR3A available for PWM.
Setting both COM3n0 and COM3n1 is setting up for INVERTED PWM. Is that what you want? For NORMAL PWM (ON until OCR3n is reached, then OFF) set COM3n1 only.
I'm sorry, I dont quite understand...
I am trying to set a variable "TOP" value using OCR3A to essentially vary the PWM output frequency. I am not interested in the duty cycle at this point, only the frequency...
My understanding is if I use OCR3A for the "TOP" value, the pin associated with OCR3A, pin OC3A (D5) will be set low until OCR3A is reached, then set high at "BOTTOM" when the counter resets. Or vice versa if non-inverted.
If that's true, then I shouldnt have to use any other OCR3x registers for my output, only the pin OC3A...
A special case occurs when OCRnA/OCRnB/OCRnC equals TOP and COMnA1/COMnB1/COMnC1 is set. In this case the compare match is ignored, but the set or clear is done at BOTTOM.
I think that means the output pin will not be SET on compare match but will be CLEARED at BOTTOM. The output will thus always be LOW if you use inverted PWM.
If you're not interested in duty cycle then that may not be a problem, until you are interested in duty cycle.
Ah I see... In that case, I'm not sure what the best method of producing a variable frequency PWM would be? Can you provide any ideas here?
In my ideal situation, I'd be able to set a compare value in OCR3A, and have the corresponding pin, OC3A go high or low, depending on inversion, before being set or cleared again when the TCNT3 value resets... which may only end up with a pulse of 1 clock cycle...
Figured it out... there is a non-PWM CTC mode that uses the OCR3A compare register value as the TOP. I hadnt seen that previously, only the ICR CTC mode...
Now OC3A toggles whenever OCR3A is matched...
void setup() {
TCCR3A = 0;
TCCR3B = 0;
TCNT3 = 0;
//Set timer to CTC OCR mode so that OCR3A is the TOP value.
TCCR3B |= (1 << WGM32);
//Set the compare output mode for Timer 3 Channel A (Set OC3A on compare match)
TCCR3A |= (1 << COM3A0);
//Set time prescaler to 8 to allow for speeds of 50pps - 10000pps
TCCR3B |= (1 << CS31);
//Set Output compare value...
//In 1/8 mode: 50pps = (16MHz/8)/50 = 40000
// 10000pps = (16MHz/8)/10000 = 200
OCR3A = 2000;
//set PE4 (OC3A) to output
DDRE |= (1 << PORTE3);
//Check registers to verify bit settings
Serial.begin(9600);
Serial.println(TCCR3A, BIN);
Serial.println(TCCR3B, BIN);
}
Thanks for your help. Pointing me back to the datasheet made me re-read it and pick up on this mode. Appreciate your time!
So you want 50% duty cycle? That is what you get with WGM = 4 (CTC) and COM3A0. You can change the frequency but the output pin toggles on each match so the output duty cycle is 50%.