Hello
I have an arduino uno, and I need to create a firing angle control.
I can detect zero crossing with an edge triggered interrupt, but how can I use Timer2, so that any new ZeroCossing initiatez a new counting cycle?
I guess using delays would be easier but I don't want to casue delays on my main loop.
Thanks for your suggestions.
I can detect zero crossing with an edge triggered interrupt, but how can I use Timer2, so that any new ZeroCossing initiatez a new counting cycle?
Here is the Arduino tutorial on AC phase control. It uses Timer 1 to control the turn on timing.
https://playground.arduino.cc/Main/ACPhaseControl
@OP
The following diagram and the associated codes may be helpful for you.

bool flag1 = LOW;
void setup()
{
Serial.begin(9600);
pinMode(8, OUTPUT); //Gate pin
digitalWrite(8, LOW);
//----------------------------
TCCR2A = 0x00; //normal counting mode
TCCR2B = 0x00; //TC2 is OFF ; 0x06 is for divide factor /256
TCNT2 = 0x83; //preload count (at /256) to occur overflow after 2 ms
pinMode(2, INPUT_PULLUP); //internal pull-up with INT)-pin
attachInterrupt(digitalPinToInterrupt(2), ISRINT0, FALLING);
bitSet(EIMSK, 0);
interrupts();
}
void loop()
{
if (flag1 == HIGH)
{
//--genertae Fire pulse
digitalWrite(8, HIGH);
delayMicroseconds(100); //fire pulse width
digitalWrite(8, LOW);
flag1 = LOW;
}
}
void ISRINT0()
{
flag1 = HIGH;
TCCR2B = 0x06; //TC2 is ON /256 ; clkTC2 = 16 MHz/256 = 62500 Hz.
while (bitRead(TIFR2, 0) != HIGH)//checking TC2 overflow flag
;
bitSet(TIFR2, 0); //clear TC2 overflow flag
TCNT2 = 0x83; //reload preload count (variable depending on feedback)
}
BTW: The firing pulse of DPin-8 must drive the gate of the SCR via opt-coupler.


I guess using delays would be easier but I don't want to cause delays on my main loop.
The following diagram and the associated codes may be helpful for you.
There are several problems with the code you have provided
First, the OP asked for a non blocking routine but this will block like delay()
while (bitRead(TIFR2, 0) != HIGH)//checking TC2 overflow flag
Second, Timer2 is 8 bit, and the max time to overflow at 256 prescaler is 4 ms. The half cycle sine wave at 50 Hz is 10 ms, so the range of control is limited.
Third, Timer2 is in normal mode and will continue to run after the first time the interrupt sets the prescaler. The ISR would need to set TCCR2B to 0 to stop the timer, right before setting the preload TCNT2 value.
cattledog:
There are several problems with the code you have provided
First, the OP asked for a non blocking routine but this will block like delay()
while (bitRead(TIFR2, 0) != HIGH)//checking TC2 overflow flag
Second, Timer2 is 8 bit, and the max time to overflow at 256 prescaler is 4 ms. The half cycle sine wave at 50 Hz is 10 ms, so the range of control is limited.
Third, Timer2 is in normal mode and will continue to run after the first time the interrupt sets the prescaler. The ISR would need to set TCCR2B to 0 to stop the timer, right before setting the preload TCNT2 value.
Thank you for the critical observation and remarks. Things can always be adjusted/improved once we start from somewhere.
BTW: Will the 'writing on the fly' not be working for re-loading preset value into TCNT2?
BTW: Will the 'writing on the fly' not be working for re-loading preset value into TCNT2?
I believe the preload will work fine, but that value is loaded on overflow. The timer continues to run from that point and there will be another overflow and counts starting from 0 during the next half cycle. By the time you zero cross trigger again, and expect to delay the triac trigger by the difference between TCNT2 and overflow, you have no certainty of the TCNT2 value.
See the previously referenced AC phase control example. The timer controlling the delay is stopped before being started again by the zero cross interrupt.
@cattledog
1. Yes, the 8-bit TC2 will limit the firing angle within 00(0 ms) to 36.8640(4.096 ms). To have wider control of the firing angle, the OP is being recommended to use TC1 (16-bit resolution).
2. By the following saying/para, I am not defending myself; I am just expressing my opinion if this could be an alternative solution of the issue that you have raised without stopping the TC2.
Let the TC2 be generating (in the background) as many overflows as are permitted by the present codes of mine of Post#2. I am interested only for that overflow which will appear after the zero-crossing point where the desired firing delay would be proportional to the preset value of TCNT2. Therefore, I would like to re-arrange the codes of the ISRINT0() as follows:
void ISRINT0()
{
flag1 = HIGH;
TCNT2 = 0x83; //reload preset[s]load[/s] count (variable depending on feedback)
TCCR2B = 0x06; //TC2 is ON /256 ; clkTC2 = 16 MHz/256 = 62500 Hz.
while (bitRead(TIFR2, 0) != HIGH)//checking TC2 overflow flag
;
bitSet(TIFR2, 0); //clear TC2 overflow flag (TOV2)
// TCNT2 = 0x83; //reload preset[s]load [/s]count (variable depending on feedback)
}
3. I am thinking to replace the following blocking codes by TOV2 interrupt; but, I am also aware that the proposed interrupt arrangement is going to complicate the situation. Someone might have better idea!
while (bitRead(TIFR2, 0) != HIGH)//checking TC2 overflow flag
;
Therefore, I would like to re-arrange the codes of the ISRINT0() as follows:
Yes, I think it works to set TCNT2 to the preload count right before the while loop waiting for overflow flag.
cattledog:
Yes, I think it works to set TCNT2 to the preload count right before the while loop waiting for overflow flag.
Appreciate a lot with K+.