Can't change ATTiny85 PWM frequency

I’m trying to bump up the PWM frequency on a a digital pin on an ATTiny85 for the purpose of filtering to a continuous analog voltage. I’m using the arduino-tiny core and I’ve selected the ATTiny85 1Mhz board in the IDE.

First I took a stock ATTiny85 (default fuses for 1Mhz operation) and ran this code:

void setup()
{
  pinMode(0, OUTPUT);
  analogWrite(0, 128);
}

void loop()
{
}

I don’t have a proper frequency counter so I’m using an Arduino Uno with the FreqCount library, and I checked it against a 555 timer to make sure it was giving me expected results.

I measured the frequency on digital pin 0 (physical pin 5) at 243Hz. Is that normal? My reading led me to expect something more in the 500Hz range, but ok, I want to boost it anyway.

I followed the instructions in this thread, http://forum.arduino.cc/index.php?topic=144935.15, and modified core_build_options.h in the two places indicated to set TIMER_TO_USE_FOR_MILLIS and FAVOR_PHASE_CORRECT_PWM to 0 in the ATTiny85 section of the file. I then ran this code:

#include <UserTimer.h>

void setup()
{
  UserTimer_SetToPowerup();
  UserTimer_SetWaveformGenerationMode( UserTimer_(Fast_PWM_FF) );
  UserTimer_ClockSelect( UserTimer_(Prescale_Value_1) );
  
  pinMode(0, OUTPUT);
  analogWrite(0, 128);
}

void loop()
{
}

When I upload this code, digital pin 0 (physical pin 5) puts out a PWM signal at 486Hz. Something changed, but I’m not getting anywhere near the 32kHz I was expecting. I tried playing with the prescale value but nothing I select makes any difference - still 486Hz. I fused the MCU for 8MHz operation (removed the clock prescaler), and without re-uploading the sketch I then got an output of 3.8KHz, or 8 times faster. But when I selected the ATTiny85 8MHz board in the IDE and re-uploaded, the output dropped back down to 486Hz. :frowning:

What am I missing here? Something dumb, I’m sure.

SaintGimp: I measured the frequency on digital pin 0 (physical pin 5) at 243Hz. Is that normal?

fOCnxPCPWM = fclk_I/O / (N * 510) = 1000000/(8*510) = ~245. Yup. Looks correct.

...and FAVOR_PHASE_CORRECT_PWM to 0...

That only affects pin 1 (PB1, OC0B, OC1A).

SaintGimp: set TIMER_TO_USE_FOR_MILLIS {to 0}

Which moves the millis timer to timer 0 making UserTimer timer 1. Pin 0 is connected to timer 0 (now the millis timer) so your code will not have have the desired affect.

If you leave TIMER_TO_USE_FOR_MILLIS and FAVOR_PHASE_CORRECT_PWM at the default values your code should work as you expect for pin 0.

Ok, this is making a little more sense to me now. For a few minutes I was stumped about where the value 510 came from but then I found elsewhere that fOCnxPCPWM = fclk_I/O / (2 ? N ? TOP) and I guess digital pin 0 is running in phase-correct mode by default, which means it counts up to the maximum value (255) and back down again rather than resetting straight to zero, which causes the timer to count all values twice except 0 and 255 which are counted once per cycle, for a total of 510 values (or 255 * 2).

SaintGimp: ...and I guess digital pin 0 is running in phase-correct mode by default...

Correct. By default timer 1 is used for millis and is configured for Fast PWM. By default timer 0 is UserTimer and is configured for Phase Correct PWM.