How set ATmega328P-AU timer0 pins (5.6) to 20KHz phase-correct PWM

Hi,
I purchased Pololu Dual MC33926 Motor Driver to use MC33926 with my Arduino Pro Mini (Atmega 328p-au)
and 2 DC motors.
Unfortunately I can only use PWM pins 5 and 6 wich works on Timer0 (other PWM pins are used by RFM SPI and other external devises) and the default PWM frequency is not enough, so in order to suppress audible whining noise I
would like to run motors at 20KHz phase-correct PWM.
I know that Timer0 will affect millis(), micros() and delay() functions, but it’s not a problem.

The MC33926 Motor Pololu library contains the code of how to set pins 9 and 11 (timer1) to work on 20KHz with 0-400 PWM values.

I have found how to set the timer0 to 31.250 kHz (but that is to much because MC33926 can only support up to 20KHz PWM) so there is a lot of jitter in motor movements :
http://playground.arduino.cc/Main/TimerPWMCheatsheet

TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00); 
TCCR0B = _BV(CS00); 

And modify the line in the wiring.c function in the Arduino program files
hardware\arduino\cores\arduino\wiring.c :

#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(1 * 510))

I have read the Atmel datasheet and, I’m sure that it should be very easy for someone who know the programming, but it’s really over my abilities.

Your help will be appreciated.

Hello.

The way that Timer0 on the ATmega328P was designed, if you need two PWM outputs then the PWM frequency will have to be your clock frequency divided by a power of 2. Some achievable frequencies with a 16 MHz clock are 976 Hz, 7.8 kHz, 15.6 kHz, and 31.25 kHz.

I recommend that you just control the motors using the Arduino analogWrite function, which uses a frequency of 976 Hz. Unfortunately, this will result in audible PWM noise.

You could set the Timer0 prescaler to 1:8 and use Fast PWM in order to achieve a PWM frequency of 7.8 kHz. However, that frequency is still low enough that you can probably hear it.

You could set the system clock prescaler to 1:2, set the Timer0 prescaler to 1:1, and use Phase Correct PWM in order to achieve a PWM frequency of 15.6 kHz, which might be high enough to be out of your range of hearing. You can test your hearing of high frequencies using an online tone generator. Changing the system clock prescaler means that all of the code on your AVR would run at half the speed (8 MHz), and all the hardware peripherals would run at half the speed, so you might need to change a lot of things to get your code working again, depending on what libraries you are using and what assumptions your code makes.

I recommend using analogWrite, but let me know if you would like help with either of the other options.

–David

Hi David,
thank you for your reply.

So there is no way to set the Timer0 PWM to run 20KHz like you did it in your library for Timer1 ??

// 16MHz / 1 (prescaler) / 2 (phase-correct) / 400 (top) = 20kHz
TCCR1A = 0b10100000;
TCCR1B = 0b00010001;
ICR1 = 400;

Regards,
Khamzat

Hello, Khamzat.

Assuming that your clock is 16 MHz and that you need two PWM outputs from Timer0, there is no way to get a 20 kHz PWM frequency. Timer0 does not have an ICRn register like Timer1. The frequency of Timer0’s PWM can be set using the OCR0A register, but that is the same register that is used for setting the duty cycle of the first PWM output. This means that you have to choose between having two PWM outputs with limited frequency options or one PWM output with a wide range of frequency options.

Are you sure you need two PWM outputs? If both of your motors are always running at the same speed or one of the motors is restricted to just running at full speed whenever it is on, then you could make your system work with one PWM output and it could be 20 kHz.

–David

Hello David,
Those two DC motors are used in Wireless Follow Focus project (with PID) and controlled by a remote controller.
Some time they will run at same time, sometime separately. Speed will vary all the time.

If it is not possible to get 20KHz from Timer0, could you suggest a standalone I2C PWM (LED ?) driver IC which can be controlled from Arduino and will run at 20KHz?
Thank you again for your assistance.

Khamzat

I do not know of any PWM drivers that like that.

–David