Fast PWM on Attiny 13 using Arduino/C

Hello, it's my first post here btw. The problem I've came across is I want to have 1 output of Fast PWM on Attiny13 - particulary for controlling PC PWM fan, which requires frequency at around 25kHz. I searched for quite long time and still have problems, which are:

I have a piece of program that works on Arduino:

//const int controlPin= 3;
const int temp =A0;
void setup()
{
  TCCR2A = 0x23;
  TCCR2B = 0x09;  // select clock
  OCR2A = 79;  // aiming for 25kHz 
  DDRD |= 1 << 3; // enable the PWM output (you now have a PWM signal on digital pin 3)
//same as pinMode(controlPin, OUTPUT);  }

void loop(){
  OCR2B = (analogRead(temp))/13;
  delay(1000);
}

I try to make it compatible with Attiny13, and this is the closest version:
The values of the registers matches the info in datasheet of Attiny 13 I think

void setup()
{
  TCCR0A = 2<<COM0A0 |  3<<WGM00; // clear 0c0a at compare match //enable fast pwm
  TCCR0B = 0<<WGM02 | 1<<CS00; //enable fast pwm mode // not to use prescaler
  
  OCR0A = 79;  // aiming for desired frequency (only test values until it'll finally work)
  DDRB = 0xFF; // all pins as outputs
  OCR0B = 60;  // set the PWM duty cycle
}

void loop()
{
  OCR0B = 60;
  delay(500);
  OCR0B = 30;
  delay(500);
}

Now: the strange think is that no matter what values are OCR0B/A it creates a 5.5kHz output at around 46% duty cycle (freq./voltage multimeter). As I am not an experienced MCU programmer (I know C and a little how to set values in registers but nothing more), I don't expect big accuracy and can even adjust values by testing - but it don't behave as I would love to.

Probably there's something wrong when setting Fast PWM Mode in first lines or I flipped somehow A/B registers. Please help who can set correct values for it to work as the first program on Arduino.

Thank you in advance, I appreciate your help on that.
Marek

Moderator edit: size tags removed

After reconfiguring timer 0, delay is very unlikely to work correctly. Use _delay_ms instead.

...the strange think is that no matter what values are OCR0B/A it creates a 5.5kHz output...

Are you certain? From the configuration it should be 1200000/256 = 4687.5 Hz.

Ok about delay function. The frequency could be a little less, it's measured with cheap multimeter I've bought for around 10$. Thank you for advice, I will let you know if that changed something

EDIT: OK so I did a little more tests and: frequency is closer to 4687 it's 4487 according to PC sound card oscilloscope so it's fine, but:

_delay_ms() behaves badly - it takes nearly 17s to make a 10s programmed change. MCU is clocked 9.6MHz (internal).
I created a program consisting of only 2 digitalWrites and it seems that MCU can't do more than these 4.7kHz.
Is it possible I've changed main clock? Looking now in documentation and I cannot see a mistake in bits assignments.

Coding Badly, can you explain why the clock is 1200000/256 as I suppose I don't use prescaler (CS bits)?
Also if anybody knows, why changing OCR0A doesn't affect frequency? (in Fast PWM it should be working)

This...

marekbawol:
EDIT: OK so I did a little more tests and: frequency is closer to 4687 it's 4487 according to PC sound card oscilloscope so it's fine

...and this...

MCU is clocked 9.6MHz (internal).

...and this...

I don't use prescaler (CS bits)?

...are mutually exclusive. The processor is not running at 9.6 MHz. It is running at 1.2 MHz. Which is why I used "1200000" instead of "9600000" when I calculated the PWM frequency.

After changing the board selection did you use Burn Bootloader to also change the fuses?

OK, so I understood a little bit:

#include <avr/io.h>
#include <util/delay.h>

int main(void) {
 
    //factory settings is to divide internal clock 9.6MHz by 8.
    //don't, and just run at 8 MHz (set the clock divider to 1 so no effect)
    CLKPR = (1<<CLKPCE);
    CLKPR = 0; // Don't divide
 
    //all pins go OUTPUT
    DDRB = 0xFF;
 
TCCR0A  = ((5<<WGM00) |(2<<COM0A0)) ; //mode Phase correct PWM
TCCR0B  = ( (1<<CS00)); //clock input don't divide
OCR0A=253; //now it seems to be duty cycle - initial value

   while (1==1){                            //that while is changing duty cycle, signal freq is 18.75kHz
        for (int i=0; i < 255; i ++){
            OCR0A = i;
            _delay_ms(120);
        }
        for (int i=0; i < 255; i ++){
            OCR0A = 255-i;
            _delay_ms(120);
        }
    }
}

So, let me comment it: Now the frequency is 9600000. I know why, because of factory fuse bits.
I changed mode to others but cannot acquire both frequency and duty cycle control.
Now in Phase Correct PWM I can control duty cycle, but again it'going always up to 256.
That gives 9600000(freq)/2(phase correct mode)/256(TOP value)= 18.75kHz
If it is possible to change freq by setting the TOP value a little less than 256 it will give 25kHz and both freq/duty control. But do you know how? In which mode it works and through what (OCR0B)?
Thanks in advance.

You just need to use mode 7 instead of mode 3 (one bit difference from the code you posted earlier)...

void setup()
{
TCCR0A = 2<<COM0A0 | 3<<WGM00; // clear 0c0a at compare match //enable fast pwm
TCCR0B = 1 <<WGM02 | 1<<CS00; //enable fast pwm mode // not to use prescaler

OCR0A = 79; // aiming for desired frequency (only test values until it'll finally work)
DDRB = 0xFF; // all pins as outputs
OCR0B = 60; // set the PWM duty cycle
}

To get an exact frequency of 25 kHz you will have to use a prescaler of 8 and a TOP of 47 (which makes the PWM rather coarse grained with only 48 steps).

9600000 / (8 * (47+1)) = 25000

Thank you, it's certainly what I've been looking for. Actually, for fan control 2% accuracy is fine.
Marek