PWM at 20kHz, or 21kHz, or 25kHz etc etc. Timer 1 on a Uno

Researching, there are many threads in this forum, and some great resources in the playground, to change PWM frequency from the bog-standard (slow, whining) rate. I wanted a Nano to run a Pololu DRV8833 motor driver at 20kHz (so not high pitched squealing). I needed high resolution - to run a timber clock perfectly in time with an RTC.

Here is a starting point: http://playground.arduino.cc/Main/TimerPWMCheatsheet
Another resource: Arduino Playground - PwmFrequency

However, reading through these, and through the Datasheet for the ATmega328 - it is challenging to get PWM to run at exactly 20kHz, or at some other pre-selected value (on a consistent basis) - unless you are very experienced, or an engineer.

As an untrained clutz, I studied this for hours before I got it to work, with an enormous range of PWM frequencies to choose from. Because it took me so long to get this far, I thought I should publish so that others can follow (and probably improve) on this work.

I used Timer1 (not Timer0 or Timer2) ... because it has 16 bit resolution (letting you set it at 20kHz).

Timer 1 operates pins 9 and 10. This timer is also used by other libraries, so you'll have to check for incompatibility with your sketch. The links above have suggestions for changes on other timers (but without the resolution).

Heres the code that works for me:

void setup() 
{ 
  Serial.begin(9600);

  TCCR1A = _BV(COM1A1) | _BV(COM1B1);
  TCCR1B = _BV(WGM13) | _BV(CS10);
  ICR1 = 400 ; // 10 bit resolution
  OCR1A = 0; // vary this value between 0 and 400 for 10-bit precision
  OCR1B = 328; // vary this value between 0 and 400 for 10-bit precision      

  pinMode (10, OUTPUT);
  pinMode (9, OUTPUT);
}

void loop() {

 //--- Note:  to set speed, just do (eg) this:  
 //         OCR1B/*pin 10*/ = 328/* speed 0 to 400 */;
 //--- or
 //         OCR1A/*pin 9*/ = 17/* speed 0 to 400 */;

}

Very nice, thank you!

how can i invert one of that two pwm

Set COM1A0 or COM1B0 in TTCR1A to invert the PWM signal on OC1A (Pin 9) or OC1B (Pin 10).