Go Down

Topic: 10-bit PWM with Arduino mega (Read 8292 times) previous topic - next topic


I've been reading and searching, but couldn't find a solution.

How can I get 10-bit PWM on my Arduino mega?  I need 4 pins with 10-bit resolution.  

I've understood that I'll have to play with the timers, but that's way over my head.    

Anybody willing to show me how this can be done?   Much appreciated!


The current PWM frequency of ~500Hz works, it could be slower as well. This is an LED application that requires very subtle color differences. 8 bits turned out to be insufficient resolution.


Just an idea: One could try to change the PWM duty cycle very fast to accomplish intermediate values.
You interrupt every 6ms; the eye will average what it sees during 24ms, so you have four time slots of 6 ms to fine tune.

Assume you have around 50% duty cycle, this could be 128, 128.25, 128.5 or 128.75 to cover a 1.1024 resolution
What to chose for slot 1,2,3,4:
case 128:  all 128
case 128.25:  3x128+1x129
case 128.5: 2x 128+2x129
case 128.75: 1x 128+3x129


pretty cool idea. However, I have quite a bit of other code running communications and calculations. Not sure if this would work nicely.

I'm sure it can be done by playing around with the timers. The Arduino Mega has a few. Unfortunately, there isn't much documentation about the Arduino Mega timers.    Guess I'll have to spend some time learning this.



Unfortunately, there isn't much documentation about the Arduino Mega timers

Yes there is, it's all in the processors data sheet. You can achieve PWM of between 2 and 16 bits precision on 12 channels.
All you need to do is to poke a few values into registers, the data sheet tells you what they are. As far as I know they haven't been incorporated into the Arduino wrapper yet.


Ok, I guess I should have phrased differently.. There isn't much _easy_ documentation about this :-).  Don't forget, for people like me (no experience with microcontrollers), Arduino is a blessing. I just spent some time reading the 16-bit timer section (Chapter 17) of the datasheet.   Pretty heavy stuff.    

I'll have to spend some serious time here, have no idea how the analogwrite is implemented with arduino and if messing with the timers will require re-coding it.


have no idea how the analogwrite is implemented with arduino

One of the great things about the Arduino is you can actually look at the source of how analogWrite is implemented.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.


Ok, this is where I'm at:  

From the datasheet: Timers 1,3,4 and 5 are 16-bit timers.  

from Arduino wiring.c:

     // set timer 3, 4, 5 prescale factor to 64
     sbi(TCCR3B, CS31);      sbi(TCCR3B, CS30);
     sbi(TCCR4B, CS41);      sbi(TCCR4B, CS40);
     sbi(TCCR5B, CS51);      sbi(TCCR5B, CS50);
     // put timer 3, 4, 5 in 8-bit phase correct pwm mode
     sbi(TCCR3A, WGM30);
     sbi(TCCR4A, WGM40);
     sbi(TCCR5A, WGM50);

I can find these values in the datasheet as well (table 17-2), so I think I understand what is being done.    I only need to add

     sbi(TCCR3A, WGM31);
     sbi(TCCR4A, WGM41);

to set the Timers 3 and 4 in 10-Bit PWM mode.  These timers work with the following pins:
from pins_arduino.c:
     TIMER3B      , // PE 4 ** 2 ** PWM2      
     TIMER3C      , // PE 5 ** 3 ** PWM3      
     TIMER3A      , // PE 3 ** 5 ** PWM5      
     TIMER4A      , // PH 3 ** 6 ** PWM6      
     TIMER4B      , // PH 4 ** 7 ** PWM7      
     TIMER4C      , // PH 5 ** 8 ** PWM8      
     TIMER5C      , // PL 5 ** 44 ** D44      
     TIMER5B      , // PL 4 ** 45 ** D45      
     TIMER5A      , // PL 3 ** 46 ** D46      
Interestingly, pins 44,45 and 46 can apparently also be used for PWM on the Arduino Mega.

Is this correct?  If so, it's much easier than I anticipated. Should be easy to add some functions to set the PWM resolution to the Arduino code.  

Setting the PWM frequency should be similarly simple.. by setting CS32, CS31, CS30, CS42, CS41, CS40, etc.  I'll play with this as well.

When I've figured it all out, I'll post some simple functions that should help other idiots like me without having to revert to the datasheet.


Might want to check these links:



Thanks,   I found those as well but I didn't understand the timers fully until I read the datasheet.   Also, I wasn't sure how to implement this for the mega.

Go Up