How to change Timer0 frequency to 20kHz ???

Hi everyone,

I have an issue with DC motors connected to Motor Driver MC33926
as following:

//------------ MOTOR 1 ------------
#define Motor1DirPin   8          // Motor1 Direction Pin
#define Motor1PWM_Pin  6       // Motor1 PWM Pin

//------------ MOTOR 2 ------------
#define Motor2DirPin   7          // Motor2 Direction Pin
#define Motor2PWM_Pin  5      // Motor2 PWM Pin

FYI, I cannot use other PWM pins than 5 and 6.

The default Timer0 frequency is too low so motors makes very loud noise.
I know that this problem could be fixed if TIMER_0 PWM frequency will be set to ultrasonic 20kHz.

I my previous project I used TIMER1 pwm pins with following settings (from Pololu library):

// Set Timer 1 PWM speed at 20kHz
TCCR1A = 0b10100000;
TCCR1B = 0b00010001;
ICR1 = 400;  
/* Timer 1 configuration
prescaler: clockI/O / 1
outputs enabled
phase-correct PWM
top of 400
PWM frequency calculation
16MHz / 1 (prescaler) / 2 (phase-correct) / 400 (top) = 20kHz */


Speed was controlled like that:

digitalWrite(Motor1DirPin, LOW);  
OCR1A = CCW_speed;   // 0-400 speed

digitalWrite(Motor1DirPin, HIGH );
OCR1A = CW_speed;  // 0-400 speed

But I have no idea of how to set same 20kHz frequency on TIMER0, which is also used by Millis(); function. :frowning:

I found how to set it to : 31.250 kHz but MC33926 driver can handle max 20kHz.

For Phase-correct PWM of 31.250 kHz (prescale factor of 1)
Use these two lines in the setup function:

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

Your help will be appreciated.

To create a custom frequency on Timer0 you will not be able to use pin 6 for output, as it's compare value is used to set the top value which controls the frequency.

If you need PWM output of 20Khz on both pins 5 and 6 you can't do it on a AT328.

FYI, I cannot use other PWM pins than 5 and 6.

Can you explain why you have that restraint?

If you use an Arduino Mega you have additional timers available and pins 5 and 6 are on Timer 3 and 4.

The datasheet explains the control registers for all the timer/counter modules.

If you re-configure timer0 then mills()/micros()/delay() will stop working - in fact you should
turn off timer0 interrupts (TIMSK0 = 0)

cattledog:
Can you explain why you have that restraint?

If you use an Arduino Mega you have additional timers available and pins 5 and 6 are on Timer 3 and 4.

I making PID controller with two DC motors and I need to use a pair of PWM pins with the 20KHz, controlled by the same TIMER
I can only use pins 5 and 6, because most of PWM pins 10 and 11 are already in use by SPI RFM69W molule.
So I only have pins 3,9, 5 and 6.
Pins 3, 9 are controlled by two different timers.

MarkT:
If you re-configure timer0 then mills()/micros()/delay() will stop working...

Hi Mark,
are you sure that those functions will really stop working ?

I'm testing now, following configuration found here , and as far as I can see micros(), millis() and delay() works.

For Phase-correct PWM of 31.250 kHz (prescale factor of 1)
Use these two lines in the setup function:

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))

Maybe that one line is enough to fix them, but you’ll be triggering an interrupt every 30us or so just to
manage time, rather than every 1.024ms as is normal.

I making PID controller with two DC motors and I need to use a pair of PWM pins with the 20KHz, controlled by the same TIMER

If this requirement is real, then you will have to use a 16 bit timer where you can set the period value with ICRn so that both output pins are available. If Timer1 is not available on an AT328, you will have to migrate your project to a Mega with the additional 16 bit timers.