I'd like to set the output frequency of the PWM from pin 9 (connected to timer1) to 20kHz to reduce the audible noise the motor makes at lower duty cycles.
I've been reading the atmel 32u4 datasheet but I'm getting confused on some of the implementation details for changing the PWM. My current attempts at implementing this are:
pinMode (9, OUTPUT); // OC1A on the Micro
TCCR1A = 0; // stop Timer 1
TCCR1B = 0;
// setup Timer 1
TCCR1A = bit (COM1B1) | bit (WGM11) | bit (WGM10);
TCCR1B = bit (WGM13) | bit (CS11); // PWM phase correct, prescaler of 8
OCR1A = 50; //frequency 20kHz
This as I understand it should set timer1 with a prescaler of 8 in phase correct mode. Then by setting the OCR1A register with a value of 50, calculated from:
I should be able to set the desired frequency. Am I going about this the correct way and how do I go about setting the duty cycle of the PWM using this?
If the MAX value is 50, with a prescale of 8, in phase-correct mode, that's 8*100 clock cycles per PWM
cycle, yes, 20kHz.
The duty cycle can be varied by setting OCR1B between 0 and 50. You can only output on channel B
if using OCR1A to set the MAX value. The mode that uses ICR1 to set the MAX value might be more
appropriate (not sure if there is one for phase-correct though).
Thanks for your comment! I've had a look again at the PWM registers and am trying to configure the registers to a mode that uses ICR1:
TCCR1A = bit (COM1A1) | bit (WGM11);
TCCR1B = bit (WGM13) | bit (WGM12) | bit (CS10);
ICR1 = 1000;
OCR1A = 0; // Set this to change duty cycle
Is this what you meant? I assume the duty cycle will now vary between 0 and 1000? Is there a better way of doing this that would give me a larger duty cycle?
I'd like to set the output frequency of the PWM from pin 9 (connected to timer1) to 20kHz
You are using mode 14 which is fast PWM to ICR1. Your prescaler is 1. The timer counts are 0 referenced, so the period of the timer will be (1001 counts x.0625us per count). If ICR1 = 999 there will be a frequency of 16 KHz.
I assume the duty cycle will now vary between 0 and 1000? Is there a better way of doing this that would give me a larger duty cycle?
As MarkT says, the duty cycle is a percentage between 0 and 100%. It will be controlled by the value of OCR1A which can range from 0 to ICR1.