Let's Make Robots!

Need to setup TIMER3 on Mega to higher frenquency PWM

I need to set TIMER3, controlling pins 2 and 3 on an Arduino Mega to either fast PWM mode (acceptable) or faster (higher frequency)(preferable).

I use this PWM to control an audio signal through a Silonex light sensitive resistor/LED unint and some audio contamination can be heard because of the speed at which the Silonex reacts. I used TIMER0 in tests with a prescaler of 1 and it works OK. But TIMER1 is "fast" PWM and TIMER3 is "phase correct".

So, either I make TIMER3 "fast" or even better, I set TIMER3 even faster (I would like to try a maximum frequency of 125000 or 250000 Hz if that's possible. A "fast" PWM does 62500 max).

I have read the whole "Arduino 101: Timers and Interrupts"a few times, but I'm just not good enough to "get it".

Thanks, Robert.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

A quick and easy solution would be to download the timer3 lib and run the following example:


 *  Timer3 library example
 *  Author: RobotFreak, November 2011

#include "TimerThree.h"

void setup()
  Timer3.initialize(8);       // initialize timer1, and set a 8 microsecond period (125kHz)
  Timer3.pwm(2, 512);         // setup pwm on pin 2, 50% duty cycle
  Timer3.pwm(3, 512);         // setup pwm on pin 3, 50% duty cycle

void loop()
  // your program here...

Thank you RobotFreak,

I understand the first line (I went through the code in the library). I don 't understand the relation between duty cycle and period. And the relation between duty cycle and the PWM value that analogWrite(pin, value) sends to the pin. (Maybe I just don't understand duty cycle...)

Also, would this code produce the same results"?

void setup()
  Timer3.pwm(2, 512,8);         // setup pwm on pin 2, 50% duty cycle
  Timer3.pwm(3, 512,8);         // setup pwm on pin 3, 50% duty cycle

You will need to call Timer3.initialize(), otherwise it will not work. Using analogWrite() will not work here, because the Arduino core initialize Timer 1,3,4,5 to use 8bit pwm mode.The value range for 8bit pwm is 0..255. Timer3 lib is using 10bit pwm mode, with a value range of 0..1023.

Found another interesting article about timers and PWM: http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM


I won't have to test it (analogWrite) then. The timer3.pwm() will be it.

Question: The pwm() has 3 params in the library. Omiting the last one (period) makes it similar to setpwm()?

Thanks for the library and all the pointers to the reading material.I wouldn't have undestood the code in the library without all the reading (there are still some nebulous stuff in there...)

The pwm() function is using a C++ trick to accept different parameter lists. When you look in the function declaration in the header file:

    void pwm(char pin, int duty, long microseconds=-1);

You see, the last parameter has a default value of -1. If you call the function with only 2 parameters, the timer period will not be changed. Because this is already been done in the initialization function.

The difference between pwm() and the setPwmDuty() function is, setPwmDuty doesn't initialize the PWM pin. If you only call setPwmDuty() in your program, the PWM output pin will not work.


In every program you need to call in your setup() function the initialize() function once and the pwm() function for each needed PWM output . In the loop function you can change everything you want with the setPwmDuty() or setPeriod() function to change PWM duty and PWM period time.

I must confess that I also do not understand everything about timers and their different modes. It's the most complicated stuff in Arduino programming.

Period = the length of one pulse which gives the frequency

Duty cycle = how many percent of one pulse is actually "filled" - 100% the whole period is high, 50% half of the period is high

Have a look here http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=68302&start=all&postdays=0&postorder=asc and here too http://aquaticus.info/pwm

Got that. Then I presume that timer3.pwm() replace analogWrite(). But why set the duty cycle to 50% in setup?

If you ask why in  the setup() function ... well you can set it in the loop too :) As with all init functions only that *should* be done in setup.

Yes it replaces analogWrite.

Have you actually had a look at the library source or you just blindly copyed it in there?

I also just got that it was an example, that you don't have to initialise the pins at 50%, or any value, in setup().

I did, I did look at the source! But the reason I'm asking these questions is that I have a very hard time understanding the whole PWM modification thing, NOT what to use them for.

I'm used to Arduino coding, which is what I need as an artist to do what I have to do with music and art in general. But modifying PWMs involves learning a lot about how the AVR functions and looking at the code and registers and stuff is just ... well, complicated. I've been working on this for days BEFORE I asked questions here.

Reading the library code shows me the relations between the parts, and I still have questions.

Question: The initialise() statement goes in setup(). I know that. But why would I put the two following statements in the setup() section? The question was more about "Will the analogWrite() function still work?"