PWM Duty Cycle Resolution Arduino Uno from 8-bit to 10-bit


I am writing a programme that communicates over I2C with a raspberry pi. The raspberry pi sends values for the Arduino to set the PWM duty cycles on pins 3, 9, 10 and 11. I have alread changed the PWM frequency on these pins to ~ 30 Hz to match it with the system which I am controlling. This is done using:

TCCR1B = TCCR1B & 0b11111000 | 0x05;
TCCR2B = TCCR2B & 0b11111000 | 0x07;

Currently I can set PWM duty cycles between 0 - 255 (8-bit). I have been reading that it is possible (hardware is sufficient) to set atleast some of these pins to have a better duty cycle resolution (10-bit; 0 - 1024). Is this possible with the Uno? If so could you give me some pointers to how I should go about it. I am concerned that since I have changed the PWM frequency that this will intefere with my ability to adjust the duty cycle resolution since they’re intricately related?


Here is my code:


#include <Wire.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/wdt.h>

#define SLAVE_ADDRESS 0x03 // I2C Address of the Arduino
int howMany = 0, debug = 0;
int state = 0,x,y,z;
char buffer100[7];
int position=0,A,B;
char str,values[100],warr[20];
String receivedMessage,X,Y,Z;

int startStringPosition,startStringPosition1,startStringPosition2;
int endStringPosition,endStringPosition1,endStringPosition2;

void setup() {
    pinMode(13, OUTPUT);
    Serial.begin(115200);         // start serial for output
    Wire.begin(SLAVE_ADDRESS);    // initialize i2c as slave
TCCR1B = TCCR1B & 0b11111000 | 0x05;  // Reduce PWM Frequency to 30 Hz.
TCCR2B = TCCR2B & 0b11111000 | 0x07;  // Reduce PWM Frequency to 30 Hz.

    // define callbacks for i2c communication
    Serial.println("Listening on Serial Port");
    wdt_enable(WDTO_8S); // Setting watchdog timer for 8s. If no reset of timer within 8s, Arduino will reset.

void loop() {

// callback for received data
void receiveEvent(int howMany)
position = 0;
digitalWrite(13,HIGH); // When data recieved, set LED on PIN13 high.
  while(Wire.available())  //Reading data over I2C.

    str =;
values[position] = str; 


values[position] ='\n';

// -------------- Extracting values for PWM Duty Cycles from String.
// -------------- String format: A%dB%dC%dZ.

receivedMessage = String(values);
 startStringPosition= receivedMessage.indexOf('A')+1; 
 endStringPosition= receivedMessage.lastIndexOf('B');
if(debug > 0){ // Show X if in Debug mode. This slows program down.
 char Xchar[X.length() +1];
 startStringPosition1= receivedMessage.indexOf('B')+1; 
 endStringPosition1= receivedMessage.lastIndexOf('C');
 if(debug > 0){ 
  char Ychar[Y.length() +1];
 startStringPosition2= receivedMessage.indexOf('C')+1; 
 endStringPosition2= receivedMessage.lastIndexOf('Z');
  if(debug > 0){ 
  char Zchar[Z.length() +1];
// --- Using values to set PWM Values (0 - 255) 

//   analogWrite(3,y); // Not used Currently




digitalWrite(13,LOW); // Resetting the LED on PIN13

wdt_reset(); // Reseting watchdog timer. 

  1. No, as far as PWM outputs are concerned, 255 is the max. Analog inputs, however are 0-1023 range.
    2)There is absolutely no need to be concerned. You can use a normal analogWrite(pin,value), only thing is, it might happen too fast or too slow, so you may need to compensate for that.

Hope that helped!

I would have thought that would be the case but there seems to be some people claiming that it is possible by 'brute force':

I am not sure exactly how to go about it or what others think of this. This site also eludes to the fact that it's possible:


Andy, I think your aim is only partly achievable. According to this:

PWM pins 5 & 6 use timer0. timer0 is an 8-bit timer, so 10-bit resolution not possible
PWM pins 9 & 10 use timer1. timer1 is a 16-bit timer, so 10-bit resolution should be possible
PWM pins 3 & 11 use timer2. timer2 is an 8-bit timer, so 10-bit resolution not possible

You could consider upgrading to a Arduino Mega, which has a 16-bit timer3 I believe.