Maximum Arduino PWM of 62kHz with a 16MHz system clock!

Hi,

Reading this page, I realize that the maximum frequency possible is 62kHz!

TCCR0B = TCCR0B & B11111000 | B00000001;    // set timer 0 divisor to     1 for PWM frequency of 62500.00 Hz

So, my question is, why this extremely low limit when the Arduino clock is 16MHz?

I would like to have 100kHz PWM but surprisingly Arduino isn't capable of!

Regards.

WHY ARE YOU SCREAMING!

But to answer that, the timer is 8-bit so it needs 256 tick to overflow. 16MHz / 256 =~ 62kHz.

And why would you like 100kHz PWM? That's a XY-problem :wink:

That is the technical justification however isn't a reasonable one once you realize the 16MHz clock speed of the Arduino. My math is more like, 16MHz / 1bit = 16MHz... :grin:

I want to simulate a buck converter like the chip LM2576. It looks like the LM2576 has a frequency of 52kHz so 62kHz will do after all! :stuck_out_tongue:

Why not? If you start to divide 16MHz down you're in the KHz range pretty fast. And you still need a tick per step (/ resolution) and the system clock at 16MHz is the fastest the Arduino (uno-ish) has (it has no PLL). You can run the Arduino at 20MHz but then you have to check if all libraries and HAL can handle the switch to 20MHz.

The maximum frequency possible is 8MHz.

You have to choose one of the timer PWM modes that counts to less than 255. However you get less
(duty-cycle) resolution at higher frequencies. The datasheet has all the gory details, timer0 and
timer2 are slightly different, note, and timer1 is 16 bit with more modes.

MarkT:
The maximum frequency possible is 8MHz.

Was you able to do so? Due to the while() loop cycles, we can't get a perfect regular signal as far as I can see...

http://em10-usd-arduino-takahashi.eliotis.com/downloads/files/arduino_max_blink.zip

The best I can achieve is 4Mhz (taking care to while() cycles)…

http://em10-usd-arduino-takahashi.eliotis.com/downloads/files/arduino_perfect_max_blink.zip

Then don't use while loops :wink: Just set it up in PWM mode and CTC on a 1 :slight_smile:

So yes, I have to add to my statements earlier that I assumed to keep the full resolution.

Use the TimerOne library to get 100KHz.

#include <TimerOne.h>
//UNO only

void setup()
{
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);

Timer1.initialize(100);  // Frequency, 100us = 10khz, 10 >>>------> 100KHz
Timer1.pwm(9,512);       // 50% DC on pin 9

//Timer1.pwm(10,255);    // 25% DC on pin 10

// D.C. 
// 10KHz
// You can use 2 to 1023 
// 0 & 1 gives a constant LOW 
// 1024 gives a constant HIGH
// 2 gives ~125ns HIGH pulses
// 1023 gives ~125ns low pulses
// 512 gives 50us
}

void loop()
{
}

septillion:
Then don't use while loops :wink: Just set it up in PWM mode and CTC on a 1 :slight_smile:

Obvious! :smiley:

Can we set CTC to 1? My analyzer do not catch anything. i need to use at least 2 -> 8Mhz (the answer of MarkT).

Might indeed be 2... Just did it from the top of my head. If I really need to do CTC stuff I always have to triple look at the datasheet ::slight_smile:

If you configure timer1 (ATmega328P as in Uno etc.) to use fast PWM ( Wave Generation Mode 14) you can get up to 8 MHz for a 16MHz clock if the timer is set to directly manipulate a pin dedicated to it, in this case OC1A (pin D9):

  //set timer1 toggle at xHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0

  ICR1 = 1 ;      // set TOP
  OCR1A = 0 ;   // set duty cycle

  TCCR1A |= ( 1 << COM1A1 ) | (1 << WGM11) ;

  // wg mode 14
  TCCR1B |= (1 << WGM12) | (1 << WGM13);
  // prescaler  1
  TCCR1B |= (1 << CS10)  ;

The resolution is poor though close to the clock frequency
You get 8 MHz, then 5.33..MHz , then 4 MHz then 3.2 MHz then 2.66.. MHz etc.

septillion:
Then don't use while loops :wink: Just set it up in PWM mode and CTC on a 1 :slight_smile:

So yes, I have to add to my statements earlier that I assumed to keep the full resolution.

It looks promising, can you give a code example of that?

I can do better, I'll give you a tutorial :slight_smile:

septillion:
I can do better, I'll give you a tutorial :slight_smile:

http://maxembedded.com/2011/07/avr-timers-ctc-mode/

Thanks, I will see that.