I am playing on a Arduino UNO, you would have to compare the datasheets to determine differences.
For my research on this answer I am looking at:
Also:
- we know PWM pins are D3, D5, D6, D9, D10, D11
- I am using D11 for this since I can attach my oscilloscope to the MOSI pin of the ISCP
- D11 maps to PB3 (MOSI/OC2A/PCINT3) (see datasheet or this cool gfx)
Normal usage
First, let's see what happens when we set an arbitrary PWM on pin 11
int DUTY = 25;
analogWrite(11, DUTY * 256 / 100);
results in:
- Freq: ~487Hz
- Duty: ~25%
- Time: ~2.05ms
This first point I will make is that with the given 490Hz the PWM duration is actually 2ms which seems to be close to what you want (you said between 1-2ms), maybe my misunderstanding there.
Playing with pre-scalers
From several of the links posted above, you will see that you have different pre-scalers available depending on which timer you are using: eg.
Pins 5 and 6: controlled by Timer 0 in fast PWM mode (cycle length = 256)
Setting Divisor Frequency
0x01 1 62500
0x02 8 7812.5
0x03 64 976.5625
0x04 256 244.140625
0x05 1024 61.03515625
TCCR0B = TCCR0B & 0b11111000 | <setting>;
Pins 9 and 10: controlled by timer 1 in phase-correct PWM mode (cycle length = 510)
Setting Divisor Frequency
0x01 1 31372.55
0x02 8 3921.16
0x03 64 490.20
0x04 256 122.55
0x05 1024 30.64
TCCR1B = TCCR1B & 0b11111000 | <setting>;
Pins 11 and 3: controlled by timer 2 in phase-correct PWM mode (cycle length = 510)
Setting Divisor Frequency
0x01 1 31372.55
0x02 8 3921.16
0x03 32 980.39
0x04 64 490.20
0x05 128 245.10
0x06 256 122.55
0x07 1024 30.64
TCCR2B = TCCR2B & 0b11111000 | <setting>;
(All frequencies are in Hz and assume a 16000000 Hz system clock.)
These are relatively simple to setup and use (the setting is at the bottom of each of the above code blocks), but you have to be mindful of playing with the pre-scaler of timer0 (which controls millis()
and delay()
). So if you have a choice, steer clear of timer0, or pwm pins 5 and 6.
Example of using just the inbuilt pre-scalers without any additional libraries:
#define PIN 11
void setup(){
pinMode(PIN,OUTPUT); // not absolutely required
int DUTY = 20;
TCCR2B = TCCR2B & 0b11111000 | 6;
}
void loop() {
static long counter = 0;
if(millis()%10==0){
counter++;
analogWrite(PIN, counter%255);
}
}
I know you can manipulate the frequency better than that, and I have been playing with this for hours and then I finally stumbled upon the final link (which believe it or not, I found via YouTube!).
Using an External Library
To use the PWM library you will need to download it from Google Code, save/import/get it into your library folder, and restart the IDE. Once you do that, you can explicitly set the frequency (within limits, 333Hz is within those limits), and you should be set.
Code example:
#include <PWM.h>
int32_t frequency = 333;
#define PIN 10
void setup(){
pinMode(PIN,OUTPUT);
int DUTY = 20;
InitTimersSafe(); // won't touch timer0
SetPinFrequencySafe(PIN,frequency); // again, not timer0
pwmWrite(PIN, DUTY * 256 / 100);
}
There is even a pwmWriteHR
which allows for higher resolution, but that does not work with timer2 (which is only an 8-bit timer).
The matching, non-safe (ie initialises and uses timer0 as well) functions are:
InitTimer(); // and
SetPinFrequency(PIN,frequency);
The only limitation I have found so far is that it doesn't work with PWM pin D11. I have tested D3, D9 and D10 (they all worked fine), but I did not get around to testing D5 or D6.
Good luck, I hope this helps.