Increase PWM output resolution?


is there a simple way of increasing the output resolution of the PWM output on the Arduino when using analogWrite()? 10-bit would be much nicer than 8.

Best regards Lars

It depends which timer you use. Timer 1 is a 16-bit timer and has 16-bit resolution, Timers 0 and 2 have 8-bit resolution. I believe Timer 1 PWM outputs are digital pins 11 and 12.

Thanks for your answer.

I've tried all PWM outputs and when using analogWrite I can only set 256 different values on all of them. Do I have to do something else to be able to use the full power of Timer1? Can I e.g. modify analogWrite in a simple way?


It's on page 109 of the ATMega168 data sheet. It shows you what registers to bang (direct access) to get it. But I suspect there is no easy way to modify analogWrite().

Here's the first part of analogWrite() from hardware/cores/arduino/wiring_analog.c:

void analogWrite(uint8_t pin, int val)
        pinMode(pin, OUTPUT);

        if (digitalPinToTimer(pin) == TIMER1A) {
                sbi(TCCR1A, COM1A1);
                OCR1A = val;

So it's a write of the 16-bit val value to the 16-bit OCR1A register. I don't see why there would be any 8-bit resolution limitation here. Perhaps someone else can step in and explain.

WHy not use a TLC5940 which will give you 10 bit resolution?

Hello, I'm not familiar with that IC. How would I use it, in that case?

If I have to use an external circuit I was thinking of using a operational amplifier as a summing amplifier. With this I can add two PWM lowpass filtered outputs together as

total output = output1 + output2/255

which gives me 16-bit resolution.

but it feels very unnecessary to this with such a powerful microcontroller.

Here is something I was messing around with ages ago.
The way the code is written is probably not the best way to do this but it did work for me.
You will need to read the atmega data sheet to understand what the different registers do.

#define potPin 0
#define ledPin 9

int potVal;

void setup()
// Set pwm clock divider
  TCCR1B &= ~(1 << CS12);
  TCCR1B  |=   (1 << CS11);
  TCCR1B &= ~(1 << CS10);  

// Set pwm resolution  to mode 7 (10 bit)

TCCR1B &= ~(1 << WGM13);    // Timer B clear bit 4
TCCR1B |=  (1 << WGM12);    // set bit 3

TCCR1A |= (1 << WGM11);    //  Timer A set bit 1
TCCR1A |= (1 << WGM10);    //  set bit 0

pinMode(ledPin, OUTPUT); 


void loop()
  potVal = analogRead(potPin);
  analogWrite(ledPin, potVal);

A thousand thanks to you jabber. It works great!

FYI. The TimerOne library on the Arduino Playground can also solve this (and many other things).

I modify this library to use all the timers You can have a look here