Timer problem - OCR2B value changes nothing

I tried to use timer interrupt. Start setting frequency 1kHZ on Timer 2B. It is working fine.
But then I tried to change timer interrupt frequency and results are strange.
Changing TCCR2B value work as expected, but changing OCR2B do nothing.
First I observed only values in Serial.print(), next I added digital.Write() and connected oscilloscope to D6.
Detailed frequency values shown in comment below code.
Please check my code, and tell me what I do wrong.

uint32_t m_uTick = 0;
#define OUT_PIN 6

ISR(TIMER2_COMPB_vect) 
{
  m_uTick++;
  if(m_uTick & 0x01)
    digitalWrite(OUT_PIN, HIGH);
  else
    digitalWrite(OUT_PIN, LOW);
}

void initializeTimer()
{
  cli();
  TCCR2A = 0;
  TCCR2B = 0x01;  // or 0x03  - see comments below
  TIMSK2 = _BV(OCIE2B);
  OCR2B = 24;     //or 124   - see comments below
  sei();          
}



void setup() 
{
  Serial.begin(250000);
  pinMode(OUT_PIN, OUTPUT);
  initializeTimer();
}


void loop() 
{
  Serial.print(m_uTick/200.0);
  Serial.print("kHz\n");
  cli();
  m_uTick = 0;
  sei();
  delay(200);
}

//observations (pro mini 3.3V @8MHz):
// TCCR2B == 0x03, OCR2B = 124;   Serial.print shows 0,98kHz (OK expected ~1kHz), oscilloscope shows 486HZ (OK, expected ~500Hz)
// TCCR2B == 0x01, OCR2B = 124;   Serial.print shows 31,28kHz (OK expected ~32kHz), oscilloscope shows 15.5kHZ (OK expected ~16KHz)
// TCCR2B == 0x03, OCR2B = 24;   Serial.print shows 0,98kHz (not OK expected ~5kHz), oscilloscope shows 486HZ (not OK, expected ~2,5kHz)
// TCCR2B == 0x01, OCR2B = 24;   Serial.print shows 31,28kHz (not OK expected ~80kHz), oscilloscope shows 15.5kHZ (not OK expected ~40kHz)

What change do you expect?

1 Like

Please check my comments below code, I expected that if I change OCR2B value from 124 to 24 I will have 5x higher frequency. For example TCCR2B = 0x03 (divider /32) and OCR2B = 124 - I expected frequency 8MHz/(2 * 32 * (124+1)) = 1kHz and it was OK. But with TCCR2B = 0x03 OCR2B = 24 I expected 8MHz/(2 * 32 * (24+1)) = 5kHz, but I still get 1kHz.
The same with TCCR2B = 0x01 (/1). OCR2B = 124, frequency 8MHz/(2 * 1 * (124+1)) = 32kHz - OK, TCCR2B = 0x01, OCR2B = 24, still 32kHz, not 80kHz as I expected.
Why?

Just these comments show me that you confused OCR2B with something else. Please name the timer mode you are using and which registers determine the output frequency.

1 Like

What's the arduino you using?

Suppose that you run it on atmega328.
You didn't set the Timer mode, so the timer still in Normal one. In the Normal mode the counter run from 0 to 0xFF. The frequency doesn't depend on OCR2B value.

No, but if you have chosen the correct timer PWM mode, you can expect a different pulse width.

What is the exact type of MCU?

@b707 pro mini 3.3V 8Mhz
@jremington @DrDiettrich - yes, I think I missed something, now reading how to start timer properly.

This ATmega328 timer tutorial is among the very best.

2 Likes

Thank you, I used this example and it is working.

ISR(TIMER2_COMPA_vect)
{
//something
}

void initializeTimer()
{
  cli();
  TCCR2A = bit (WGM21) ;   // CTC mode
  OCR2A  = 49;            // or 24, or 124, see comment below
  TIMSK2 = bit (OCIE2A);   // enable Timer2 Interrupt   
  //TCNT2 = 0;              // counter to zero, not necessary
  //GTCCR = bit (PSRASY);        // reset prescaler now. not necessary
  TCCR2B =  0x02;// or 0x03, or 0x04 - see comment below
  sei();        
//results OK      
//TCCR2B  0x02    0x02    0x03    0x02    0x03    0x03    0x04
//OCR2A   24      49      24      124     49      124     124
//freq    40kHz   20kHz   10kHz   8kHz    5kHz    2kHz    1kHz
   
}

Yes, Nick Gammon's coverage of the subject is worth reading and is possibly overlooked.
I particularly liked his comprehensive table of values for setting a wide range of frequencies for PWM.
You can always be certain that Nick's code will work.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.