PWM Freq. I can't change it - please help :-(

I'm working with Arduino MEGA 2560. I need to encrease the 500Hz pwm freq. I've read around the forum and Arduino website yet without working result.

I want also understand the arduino clock/timers behaviour but the information around the web are not so clear. Nowhere I found a fully working sketch!

Can anyone help me?

Best regards, Mauro

Its not changeable! All you can do is change the width of the pulses.

You can write your own of course - you can control the port bits directly, supposedly get up to 2.x MHz frequency that way.

Try a simple test, see what you get (may need a little tweaking to compile correctly)

byte pin3 =3; // pin to toggle
void setup()
pinmode (pin3 output);
void loop()
digitalWrite (pin3, HIGH);
delayMicroseconds(10); // for example
digitalWrite (pin3, LOW);
delayMicroseconds(20); // to make low time longer than high time for example
// change the times to change the overall frequency and the Pulse widths

Many thanks for the answer.

Yes, I know that is not changeable by default, but I referred to the AVR internal register as you wrote.

I can't use the software pwm becouse the CPU must do many many things and I need some working PWM output that works by itself (by hardware).

I tried some code found in the Arduino site and forum but I wasn't able to do it works... :-(

the compiler didn't show errors if I change the timer registers but output is always at 500Hz


How fast do you want the PWM frequency to be Mauro?

I need about 8 - 10 Khz.

But what I really want is also udestand how can use it, also for the future other applications. For example for motors is good to use 20 - 30 Khz.

Anyway, any help is welcome ;)


I am running a fencing scoring machine. I have a loop running where I check if 100uS have gone by and then I read some inputs and make decisions. So you can get pretty fast doing the same.

  currentMicros = micros();  // sample the time
  if (currentMicros - previousMicros >= hundred_uS_interval) // more than our interval?
    // save the last time we okayed time updates 
    previousMicros = currentMicros; // save the current time for next comparison
    toggle = 1-toggle;  // results in 0 1 0 1 ...

    // do stuff on 0.1mS intervals, 1mS intervals, ets.
//  I use toggle to write an output high/low, then read it back to see if a contact has been closed for 2mS


Why is the Arduino default 500Hz anyway? It seems kind of low to me.

Dunno, I've only been around since August. 15.9 of the datasheet discusses the several modes of PWM the ATMega328 supports.

Maybe this will help:


I've checked also the last link. I undestood that there is a base freq then a prescaler that divide by fixed factor. I also tried to change the register with this code but the output freq is always 500Hz.

to CrossRoads: I use all analog input with intensive polling with a serial data comunication to send any analog reading. the pwm must works on multiple pins about 3 at the same time of other tasks.

I'd like to have a simple working code that drive one pin to study how it works... :relaxed:


This thread gives the method I have used to juice up the PWM frequency for my needs.

You could try not using phase correct pwm out of the timers, fast pwm will get you an almost double speed increase with the same prescaler. Take a look at the timer sections in the data sheet, has all the info that you’re looking for.

x gardner: yes that source is compiled without errors or warnings but the output is always 500Hz. :(

x egdinger: yes I'm check it now but my doubt is: are the register name on atmel datasheet wrote same as arduino constant defined in the compiler? I will check if I can use the register name written in the datasheet.


The register names are the same. Can you post some of the code you are using, when trying to set the registers?

If you look in wiring.c you can see where the set the default prescaler values and the waveform type (phase correct/fast, etc).

        // timers 1 and 2 are used for phase-correct hardware pwm
    // this is better for motors as it ensures an even waveform
    // note, however, that fast pwm mode can achieve a frequency of up
    // 8 MHz (with a 16 MHz clock) at 50% duty cycle
        TCCR1B = 0;

    // set timer 1 prescale factor to 64
    sbi(TCCR1B, CS11);
    sbi(TCCR1B, CS10);
    // put timer 1 in 8-bit phase correct pwm mode
    sbi(TCCR1A, WGM10);

Sorry for my late.

I don't really understand how spi(...) does... :~ maybe only set the register flag

:-( I've made more test but arduino always push out 500Hz... :-(

There's no one that have a tested working code? just for check... :cold_sweat:


"sbi()" sets a bit in a register.

Which timer(s) do you want to modify? You realize that different timers affect different pairs of PWM pins, right? Altering the behavior of Timer0 has side effects, eg, millis(), that you may not want. The other timers are fair game as long as they aren't used by a library you've included in your sketch.

i have the same problem. any help would be appreciated

here's some actually useful information. I didnt read all the posts, but yes you can change the pwm frequencies. There are 8bit and 16bit pwm options. I really haven't looked into it too much since i just had to change it for one job. is a great article. Really you want phase correct pwm if possible, unless you need pwm above about 30khz.

for the 8 bit timers, start reading page 94 of the 328P datasheet you can set N on the equations by looking at page 110. Really the whole 8bit pwm section is only 9 pages.

If you need more resolution look at the 16bit.

The closest you can get to 500hz without using the cpu's time is 490hz.

  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(CS22);
  OCR2A = 180;
  OCR2B = 50;

and just set OCR registers to whatever you want your duty to be

another useful setup for pwm that's about 32khz:

  //ultrasound pwm setup
  pinMode(3, OUTPUT); //3 and 11 are fans
  pinMode(11, OUTPUT);
   TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);

  TCCR2B = _BV(CS20);
  OCR2A = 255;
  OCR2B = 255;

really read those about 15 pages and look through the equations and divisors to find the frequency you want. If that doesn't work then use the 16bit pwm options

To the guy who suggested using a software cpu controlled pwm:... seriously?