Hi everybody,
First of all, sorry for my poor english (I am learning).
I am trying to control a Triac through an ATMega16 running with Xtal of 11,0592MHz.
I have already built a zero crossing detector, generating a 120Hz signal and I attached them to the INT0. All right, INT0 is working and I am using the falling edge of the zero crossing signal. My main source is 60Hz, so each period have 16,666 ms. The Triac's gate is optocoupled through PD5.
Well, I would like to enable the Timer 1 every time that a zero cross were detected, to count at least 5 ms and after this to count a variable period between 0 and 4,5 ms (or almost that). The aim is to control the Triac's gate to obtain a kind of dimming.
Ok, I wrote the following code to do the first part of this issue. But the Timer1 is varying it period.
I will appreciate if anybody could help me to find my error. As I said, I am new in AVR and I really would like to learn with you.
// Initializations ------------------ // void X0_Init(void) // Init INT0 (is working) { DDRD &= ~_BV(PD2); // PD2 as input (120Hz) PORTD &= ~_BV(PD2); // Disable pullups MCUCR |= (1<<ISC01); // Interrupt on falling edge GIFR |= (1<<INTF0); // Clear interrupt flag of INT0 GICR |= _BV(INT0); // Enable INT0 } // void T1_Init(void) // Init Timer 1 { TIMSK |= _BV(OCIE1A); // Output compare int. enable TCCR1B |= _BV(CS12) // Prescaler of 256 | _BV(WGM12); // CTC mode, TOP = OCR1A OCR1A = 150; // Any value, just for test } // Interrupts vectors ---------------- // // For INT0 interrupt // SIGNAL (SIG_INTERRUPT0) { cli(); // Disable all interrupts OCR1A = 150; // Any value, just for test PORTD |= _BV(PD5); // Gate ON sei(); // Enable all interrupts } // // For Timer 1 interrupt // SIGNAL (SIG_OUTPUT_COMPARE1A) { PORTD &= ~_BV(PD5); // Gate OFF } // Main program: // int main(void) { cli(); // Disable all interrupts DDRD |= (1<<PD5); // PD5 as output PORTD |= (1<<PD5); // Drive Hi PORTD &= ~_BV(PD5); // Gate OFF (PD5) OCR1A = 0; // I don't know why I wrote this // but seems do none difference sei(); // Enable all interrupts for (; ;) // Infinite loop (do nothing) { } cli(); // Never reached return(0); // May be reset }
When I attach a scope to the PD2 and to the PD2, the Timer1 signal (PD5 = Triac's gate) is phased with the PD2 signal (zero cross), but is varying the period. What is wrong ?
Best regards.
PS: I am using Timer 0 in output compare mode to generate interrupts every 5 ms (system tickets) to build a kind of RTC (only seconds, minutes and hours). Is working.