Adjusting PWM frequency?

I am trying to control a high speed pwm esc from the arduino. The problem I am having right now is that the servo library only updates the servos at 50hz. This is fine but for building a quad copter its nowhere near good enough. I need something in the 250 to 400hz range for a really nice stable quad. Analog write is the only option here but it operates at 490hz and needs to be lowered quite a bit.

I found this link

and buried within it I found this link (more important)

If you scroll down to the bottom of that link you will see the possible frequencies for the pwm pins.

For pins 6 and 5 (OC0A and OC0B):

If TCCR0B = xxxxx001, frequency is 64kHz If TCCR0B = xxxxx010, frequency is 8 kHz If TCCR0B = xxxxx011, frequency is 1kHz (this is the default from the Diecimila bootloader) If TCCR0B = xxxxx100, frequency is 250Hz If TCCR0B = xxxxx101, frequency is 62.5 Hz

For pins 9, 10, 11 and 3 (OC1A, OC1B, OC2A, OC2B):

If TCCRnB = xxxxx001, frequency is 32kHz If TCCRnB = xxxxx010, frequency is 4 kHz If TCCRnB = xxxxx011, frequency is 500Hz (this is the default from the Diecimila bootloader) If TCCRnB = xxxxx100, frequency is 125Hz If TCCRnB = xxxxx101, frequency is 31.25 Hz

I am running with an atmega 2560 not a 328 and thats where my question comes in. On the bigger atmega 2560 can I potentially get 4 pins that operate at 250hz rather than just 2 as the list states? That would be perfect for my quad if I could do it.

The servo library is used exclusively to control common RC servos which can be attached to your common commercial RC receiver. If you have an ESC module which emulates a servo, the servo library is the way to go. The refresh rate of the library is done in software via one time and not via the ATmega PWM hardware. You can change the refresh rate if you feel like it, but for this you need to look at the code and adapt it yourself.

On the other hand, if you do the speed control on your own via a H-bridge or some drivers, then forget about the Servo library and look for PWM speed control.

Now to your question whether the ATmega2560 processor mysteriously had the IO hardware changed compared to the 1280, let drop me a hint: Both are described in the same data-sheet by Atmel. If what you see there isn't to your liking, you can only change your liking or use another product.


I was able to finally adjust the hardware pwm frequency by dissecting the aeroquad firmware and developers pdf file. This code allows me to produce a 300hz pwm signal on pin 11.

void setup() {

pinMode(11,OUTPUT); //OUT2 (PB6/OC1B)

//Remember the registers not declared here remains zero by default…
TCCR1A =((1<<WGM11)|(1<<COM1B1)|(1<<COM1C1)); //Please read page 131 of DataSheet, we are changing the registers settings of WGM11,COM1B1,COM1A1 to 1 thats all…
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS11); //Prescaler set to 8, that give us a resolution of 0.5us, read page 134 of data sheet
//OCR1A = 3000; //PB5, none
OCR1B = 3000; //PB6, OUT2
OCR1C = 3000; //PB7 OUT3
ICR1 = 6600; //300hz freq…


void loop() {

analogWrite(11, 2000);


analogWrite(11, 4000);



I am now trying to change the servo.h library.

Does anyone know or have an idea where the timing in the servo library occurs. I am looking at it right now and its a bit confusing.

I believe that you can simply change REFRESH_INTERVAL in Servo.h

The servo library uses a single timer with interrupts, doing essentially:

  if more_servos_running
     next interrupt at now + next_servo_time
     next_servo = first_servo
     next interrupt at now + REFRESH_TIME

PWM is not involved.

There seems to be a miscomprehension here.

An R/C ESC will use an update rate of 50Hz of PPM (consistent with standard R/C equipment), but could itself generate PWM signals of much higher frequency to drive the motor, the duty-cycle of which would only vary at the much lower R/C rate.

Thanks for that I opened up the servo.h and found the refresh interval.

It is in a small block of code

define Servo_VERSION 2 // software version of this library

define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo

define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo

define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached

define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds

define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer

define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)

define INVALID_SERVO 255 // flag indicating an invalid servo index

change the REFRESH_INTERVAL value from 20000 to a value in microseconds. It works quite well change it to 10000 and it goes up to 100hz ect.... 5000 - 200hz and so on.

So I was able to get both methods to work changing servo.h and modifying the hardware pwm. This is good and has showed me what the real problem is.

I verified all of the update rates and pulse widths on my oscilloscope but for some reason my FAST pwm esc could not go above 50hz! Thats an issue when the unmodded one can go up to 150hz.

Thanks for the help. Now I have to go to another forum to figure out why the darn esc won't take high update rates!!!!!!!!!!!!!!!!

Now I have to go to another forum to figure out why the darn esc won't take high update rates

Maybe because it is an R/C ESC, and 50Hz is what it was designed for? (I've been using R/C gear for about 30 years, and in all that time update rates have remained constatnt at 50Hz)


The esc I am using is made for 50hz but can be used up to 150hz out of the box from my tests. The esc is controlled by an atmega8 and has its programming pads broken out. The mod I did involves loading modified firmware on to the atmega to allow a higher update rate (400hz).

This high update rate is important when you are trying to create a very stable quadcopter. At 50hz it would not react fast enough and would be very wobbly. Higher rates like 150hz to 400hz would allow it to be more stable.

I'm sorry, but I still think you're mistaking PPM and PWM. On the face of it, R/C PPM looks like low ratio PWM (and it is), but with 8 bit resolution, low ratios result in poor control. Bypass the ESC and drive its H-bridge directly.

I found the problem!

At this link the problem is made pretty clear.

The firmware I used is kind of outdated and only likes update rates of 50 to 60hz. By changing it a bit and recompiling the code I should be able to change it to allow up to 450hz......

By changing it a bit and recompiling the code I should be able to change it to allow up to 450hz

Or, by bypasssing it completely, up to 490Hz. See reply #8 (or, with lower resolution) even higher rates)

At last!!!!!!!!!!

I was able to modify the assembly file and change the two numbers that were behind the low update rate. Then I compiled it with the changes and uploaded the modified hex file.

The motor works flawlessly between 100 to 400hz now. All this trouble due to two numbers......I am definitely making videos about this now.

You guys may have seen my videos already I go by Halo2maniaccc on youtube...wish I could change the name but unfortunately I can't.

Now I am going to revisit the i2c mod which didn't turn the motor (just stuttered) I suspect it had firmware issues as well.