Variable Frequency generator using timer 1

Hello ,

Ive been consulting the Atmega328 datasheet + some internet tutorials and i want to use timer 1 to generate variable frequency with constant duty cycle. Ive written a code but it doesn`t work as aspected. For testing i am using a led on digital pin 9 (OC1A pin) , when the timer passes the OCR1A limit the OC1A pin(9) should be set high by the hardware , when the timer passes OCR1B the TIMER1_COMPB ISR must be serviced , this means timer will reset and the CPU will process the ISR making pin 9 LOW.

It works(the led blinks) but the timing is off..... As long as OCR1A<OCR1B and OCR1A,OCR1A=(10000...50000) the led will be ON for aprox 4 sec and OFF for 4 sec. Ive spend some time trying to find my mistake but i can`t see it.

Thanks for your time !

void setup()
{
pinMode(9,OUTPUT); //Set the OC1A pin to output
TIMSK1 &= ~((1<<TOIE1)|(1<<OCIE1A)|(1<<ICIE1)); //Disable all interrupts except OCIE1B

TCCR1A &= ~((1<<WGM11) | (1<<WGM10));  //Configure timer1 in normal mode (no PWM)
TCCR1B &= ~(1<<WGM12);  // Configure timer1 in normal mode (no PWM)

TCCR1A |= (1 << COM1A1)|(1 << COM1A0); //Set OC1A on Compare Match (Set output to high level). 
TCCR1A &= ~((1 << COM1B1)|(1 << COM1B0)); //Set normal port operation,OC1B disconnected.
   OCR1A   = 5024; //Set Output Compare Register 1 A
   OCR1B   = 5224; //Set Output Compare Register 1 B

TCCR1B |= (1<<CS12)  | (1<<CS10) ; // Set bits for timer prescaler /1024
TCCR1B &= ~(1<<CS11);   // Clear bits for timer prescaler /1024

TIMSK1 |= (1<<OCIE1B);   //Set the interrupt for OCIE1B for timer 1
}

/* Install the Interrupt Service Routine (ISR) for Timer1.  */
ISR(TIMER1_COMPB_vect) {
digitalWrite(9, LOW); //Set the pin LOW   // The timer should autoreset
}

void loop()
{
//Nothing
}

Hi, Slightly OT but the traditional way to get 50% duty cycle of a variable frequency is to toggle a flip-flop chip with a twice-the-needed-frequency signal.

Sometimes Hardware Wins :roll_eyes:

I'd start from "hacking", oopppss, reverse engineering :slight_smile: tone library:
http://arduino.cc/en/Reference/Tone

Thanks for the replays.

Yes, i can obtain 50% duty cycle by hardware setting but i need something like 20-22%.

Did anyone tried my code on an Arduino , maybe mine is a little off...? If i set the A compare to 15000 and the B compare to 16500 it should blink for a short period and then stay off 10 times longer than it blinked.

I found a few mistakes , will repost when the code will be working.

Are you sure the timer auto-resets?

In normal mode, the timer keeps on counting. Once you reach your Set point, the output goes high, once you go past your compare interrupt setpoint, the interruption handler kicks in and changes the polarity of the bit, but the timer will keep on counting, fold back and repeat. That may be why your timing is off. :\