Hey all,
For a project I am experminating with IR transmitters and IR receivers using arduino uno rev3.
I am trying to send a carrier signal of 38khz modulated at 300/150hz as a form of special encoding. I have figured out how to do that at 50% duty cycle using an interrupt as shown below. However,I want to lower the duty cycle so I can add more current to the IR transmitter currently working at Ifp of 140ma.
My problem is understanding timers.
I will explain the code below:
Here I am creating a 38khz using timer2:
void setIrModOutput() {
const int DUTY_CYCLE = 50; // 50%
const bool isFrequency150hz = false;
noInterrupts();
/* Set up timer2 at pin 11(OC2A) and pin 3(OC2B)(Disabled, normal port)
f(OCR2A) = fclk/(2*N*(OCR2A+1)), fclk = 16Mhz, N-prescaler = 1. */
pinMode(LED, OUTPUT);
TCCR2A = 0; TCCR2B = 0; // ensure 0
TCCR2A = _BV(WGM21); // set mode 2 CTC, OC2A amd OC2B normal port operation.
TCCR2B = _BV(CS20); // no prescaler.
// Timer2 38Khz - 16 Mhz clock divided by the prescaler(1) and the desired frequency 38000hz divided again by 2 and minus 1, CTC Mode.
OCR2A = calcTimerFrequency(38000, 1, 0); // OCR2A = 209 => 3
And Here I am creating 300/150hz using timer1(Note I did that so OCR1A values will be higher and I could get a much much lower duty cycle. However now I found out Vishay recommended 30% duty cycle).
/* Set up timer1 at pin 9(OC1A)(Disabled, normal port) and pin 10(OC1B)(Disabled, normal port)
I dont Use OCR1A, Hence it is disabled. f(OCR1A) = fclk/(2*N*(OCR1A+1)), fclk = 16Mhz, N-prescaler = 256.
I only use the interupt of OCR1B, Hence it is disabled also. f(OCR1B) = fclk/(N*(OCR1B+1)), fclk = 16Mhz, N-prescaler = 256.
OCR1A = 207, OCR1B = 20 => 300.480hz with duty cycle of 10.09% (T = 3328(usec), Pulse width t1 = 336(usec)).
OCR1A = 415, OCR1B = 20 => 150.24hz width duty cycle of 4.819% (T = 6656(usec), Pulse width t1 = 320(usec)).
*/
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
TCCR1A = 0; TCCR1B = 0; // ensure 0
TCCR1A = _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10); // set mode 15 fast pwm, OC1A and OC1B normal port operation.
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12); //prescaler of 256.
if (isFrequency150hz) {
// Timer1 150/300hz - 16 Mhz clock divided by the prescaler(256) and the desired frequency 150/300hz minus 1, Fast PWM Mode.
OCR1A = calcTimerFrequency(150, 256, 1);
OCR1B = calcTimerDutyCycle(50, OCR1A);
} else {
OCR1A = calcTimerFrequency(300, 256, 1);
OCR1B = calcTimerDutyCycle(30, OCR1A);
}
TIMSK1 = _BV(OCIE1B); // enable Timer1 Interrupt for OC1B.
interrupts();
}
The Main problem is using the interrupt of timer1 of vector OC1B
I am not sure how to switch between toggle compare mode and off mode of COM2A0 using the output of timer1 OCR1B(pin 10).
shown below:
/** Interrupt for timer1 COMPB Vector.
The Interrupt occurs when the timer reach its OCR1A value
Inside we check when the pin is on to enable/disable output of OCR2A(pin 11)
**/
ISR(TIMER1_COMPB_vect) {
TCCR2A ^= _BV (COM2A0) ; // Toggle OC2A on Compare Match
if ((TCCR2A & _BV (COM2A0)) == 0)
digitalWrite (LED, LOW); // ensure off
}
}