If you need precision timing, you will probably have to bypass many of the Arduino library functions and directly control the AVR peripherals (e.g. hardware timers) yourself using the mega168 registers (then again, I have little experience with what's out there so maybe you can find some existing libraries that will suit your needs). My advice is: don't be afraid to get your hands dirty and delve into the mega168 datasheet.
The following code will generate a 100 kHz pwm on pin OC2B (Arduino digital pin 3) on a mega168 running at 16 MHz:
setup()
{
// configure hardware timer2 to generate a fast PWM on OC2B (Arduino digital pin 3)
// set pin high on overflow, clear on compare match with OCR2B
TCCR2A = 0x23;
TCCR2B = 0x09; // select timer2 clock as unscaled 16 MHz I/O clock
OCR2A = 159; // top/overflow value is 159 => produces a 100 kHz PWM
pinMode(3, OUTPUT); // enable the PWM output (you now have a PWM signal on digital pin 3)
}
loop()
{
OCR2B = 80; // set the PWM to 50% duty cycle
do some stuff;
OCR2B = 40; // set the PWM to 25% duty cycle
do some stuff;
pinMode(3, INPUT); // turn off the PWM
do some stuff;
pinMode(3, OUTPUT); // turn the PWM back on
}
Note that you can also turn the PWM off by setting the duty cycle to 0: OCR2B = 0. However, AVRs aren't so great about handling a PWM with 0% duty cycle and will end up producing tiny glitches at your PWM frequency, so a cleaner way to disable them is by turning the output pin to an input. The down side to using the input technique is that when you set it back to an output you might get an erroneous first high pulse that is much longer than it should be.
Also note that any Arduino library functions that rely on timer2 will probably conflict with this code.
Does this make any sense?
- Ben