Hi,
You should be able to set up PWM at whatever frequency you like quite easily using the ATmega's 8-bit TIMER2. The code I'm posting has been used to generate a 38KHz carrier for IR remote control but I have adapted it for use generating much lower frequencies, e.g. your 1.5KHz. This code has been used on the ATmega328P (Arduino Duemilanove) but shouldn't require any modification - it should just work but I can't guarantee anything. I've had a quick look at the ATmega1280 datasheet and everything seems to be the same with regard to this, so hopefully it will work fine on your board -
http://www.atmel.com/devices/ATMEGA1280.aspx?tab=documentsThe key with using custom PWM frequencies is to work out the correct value for the TOP limit register and the prescaler. Basically, the clock frequency (16MHz) is divided by
(TOP limit * prescaler) to give the frequency of the timer. So if you want a frequency of 1500 Hz you'll need
(limit * prescaler) = (16000000 / 1500)
Since the limit has a maximum value of 255 for TIMER2, you'll need a prescaler value that gives you a value for limit less than 256 and ideally as large as possible within that range to allow maximum precision of control. The possible values for the prescaler are given in the datasheet I linked to and the most appropriate for your case appears to be 64. If you use phase correct PWM, which you may need for your application, then the frequency is divided by 2 again (since fast PWM counts up only and phase correct PWM counts both up and down) - there's a good explanation of all this here:
http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.htmlAny, top stop with the rambling, I think you should be using some code very much like the following:
int pwm_pin = 3;
void setup_pwm()
{
// Set the pin mode to output and make it low when we're not sending PWM
pinMode( pwm_pin, OUTPUT );
digitalWrite( pwm_pin, LOW );
// Disable all timer 2 interrupts
TIMSK2 &= ~((1<<OCIE2A) | (1<<OCIE2B) | (1<<TOIE2));
// Set prescale to 32
TCCR2B &= ~(1<<CS22);
TCCR2B |= ((1<<CS20) | (1<<CS21));
// Set frequency
OCR2A = 166; // = 16000000 / 1500 / 32 / 2
// Set duty-cycle to zero initially
OCR2B = 0;
// Enable phase correct PWM, TOP at OCR2A (OCR2A determines frequency)
TCCR2A &= ~(1<<WGM21);
TCCR2A |= (1<<WGM20);
TCCR2B |= (1<<WGM22);
// Disable OC2A output (pin 11)
TCCR2A &= ~((1<<COM2A0) | (1<<COM2A1));
// Enable OC2B output (pin 3)
TCCR2A &= ~(1<<COM2B0);
TCCR2A |= (1<<COM2B1);
}
After you've done this, writing a value between 0 and 166 to OCR2B should give you between 0% and 100% duty-cycle respectively.