Frequency in PWM-Timer2 Mode 5

Dear all,

I am playing a bit with a 5V PWM-controlled Noctua fan.
Therefore, a base frequency of 25 kHz is required. For the project I’ve chosen a mini pro with ATmega 168 / 5V level, running at 16 MHz.
I made two approaches: The first one using timer1 and afterwards a second attempt using timer2.
(Reason: I would like to use ICP1 in the next step on timer1 to “count” the rpm of the fan - so I had to move the control PWM on a different PWM timer.)

The code below works fine with timer2:

#define PWM_FAN_PIN 3 
#define RPM_FAN_PIN 2

//Serial Communication speed
#define BAUDRATE 115200

const unsigned int top = 160; //defines the Frequency - see question below

void setupTimer2();
void setFanSpeed( unsigned int val);
 

void setFanSpeed( unsigned int val){    
      if(val <= top)
        OCR2B = val;
      else{
        Serial.println(F("Invalid fan speed"));
        OCR2B = 0; 
      }     
}


void setupTimer2(){
   //Clear Timer1 control and Count registers
  TCCR2A = 0; // undo configurations on Timer2 pin 11
  TCCR2B = 0; // undo configurations on Timer2 pin 3
  TCNT2 = 0;  // Reset Register of Timer2 

  //Setting wave form generation mode (WGM) to PWM, phase correct mode 5 
  // NO prescaler -> CS12=0; CS11=0; CS10=1;


  
  TCCR2A =  (1<<COM2B1) | (1<<WGM20);
  TCCR2B = (1<<WGM22) | (1<<CS20);
  OCR2A = top;
}


void setup() {

  while(!Serial);
  
  Serial.begin(BAUDRATE);
  Serial.println(F("Start Operation - setup"));


  setupTimer2(); 
  pinMode(PWM_FAN_PIN, OUTPUT);


  
}

void loop() {

  
  for(unsigned int i=0; i<=top; i++){
    setFanSpeed(i);
    Serial.println(i);
    delay(500);
  }

  delay(4000);
  setFanSpeed(0);
  delay(6000);
}

Now the question concerns the top value of 160. Previously I tried 320, following the suggested formula from Wolles Elektronikkiste:

Frequency = 16MHz / {2x [ prescaler x (1+top)] };

The factor 2 accounts for the phase correct PWM mode.
Inserting 25 kHz and a prescaler = 1, I would expect top = 319.
Now the fan was not working properly on the top = 319 ( it turned on from loop values of 4 to 60 and then later on from 260)

Again, using the different timer1, I’ve used

const unsigned int top = 320;
// other code
//Clear Timer1 control and Count registers
  TCCR1A = 0; // undo configurations on Timer1 pin 9
  TCCR1B = 0; // undo configurations on Timer1 pin 10
  TCNT1 = 0;  // Reset Timer1 

  //Setting wave form generation mode (WGM) to PWM, phase correct mode 10 [TOP  ICR 1]: WGM13=1, WGM12=0, WGM11=1 and WGM10=0
  // NO prescaler -> CS12=0; CS11=0; CS10=1;
  // COM1A1 = 1 and COM1A0 = 0 : Clear OC1A on Compare Match when up-counting; set OC1A on Compare Match when down counting
  // COM1B1 = 1 and COM1B0 = 0 : Clear OC1A on Compare Match when up-counting; set OC1A on Compare Match when down counting

  
  TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
  TCCR1B = (1<<WGM13) | (1<<CS10);

  ICR1 = top;

This worked fine, according to the formula above.
Where is my mistake in calculating the frequency for timer2 ?

Thanks a lot in advance!

You can’t fit 320 into an 8-bit register. You have to use a prescale.

16 MHz / 25 kHz = 640 clocks per cycle
Divide by 2 for Phase Correct: 320
Won’t fit in a byte so divide by prescale of 8: 40
Subtract 1: 39

So set the prescale to 8 and the TOP to 39.

1 Like

Thanks a lot johnwasser!

Indeed - this is an issue.
But conversly, that would mean, that in the code above the PWM is running at

16 MHz / (2 x {160+1}) = 50 kHz

But the fan should not be able to respond at this frequency. (Rated at 20 KHZ - 28 kHz)
But it works perfectly at full speed on the settings above and stops at 0 -10,...

Still strange

EDIT: Is it something like a higher harmonic in PWM? :slight_smile: