AC Phase Control - Zero Cross Detection doesn't work

Hi folks,

A friend and myself are trying to implement the following project:

We’ve checked the wiring several times - it’s exactly like in the schematic. The code is as well - we didn’t change it to 50Hz yet (Austria 230V/50Hz) but since that should just affect the timing we thought that shouldn’t be relevant right now. At the moment we’re working on a prototyping board - yes, I know, it’s not terribly safe and we’re just using it for testing purposes, we’ll improve safety as soon as it works.

For easier viewing I’ll add the schematic and code from the above website:

// AC Control V1.1
// This Arduino sketch is for use with the heater 
// control circuit board which includes a zero 
// crossing detect function and an opto-isolated TRIAC.
// AC Phase control is accomplished using the internal 
// hardware timer1 in the Arduino
// Timing Sequence
// * timer is set up but disabled
// * zero crossing detected on pin 2
// * timer starts counting from zero
// * comparator set to "delay to on" value
// * counter reaches comparator value
// * comparator ISR turns on TRIAC gate
// * counter set to overflow - pulse width
// * counter reaches overflow
// * overflow ISR turns off TRIAC gate
// * TRIAC stops conducting at next zero cross

// The hardware timer runs at 16MHz. Using a
// divide by 256 on the counter each count is 
// 16 microseconds.  1/2 wave of a 60Hz AC signal
// is about 520 counts (8,333 microseconds).

#include <avr/io.h>
#include <avr/interrupt.h>

#define DETECT 2  //zero cross detect
#define GATE 9    //TRIAC gate
#define PULSE 4   //trigger pulse width (counts)
int i=483;

void setup(){

  // set up pins
  pinMode(DETECT, INPUT);     //zero cross detect
  digitalWrite(DETECT, HIGH); //enable pull-up resistor
  pinMode(GATE, OUTPUT);      //TRIAC gate control

  // set up Timer1 
  //(see ATMEGA 328 data sheet pg 134 for more details)
  OCR1A = 100;      //initialize the comparator
  TIMSK1 = 0x03;    //enable comparator A and overflow interrupts
  TCCR1A = 0x00;    //timer control registers set for
  TCCR1B = 0x00;    //normal operation, timer disabled

  // set up zero crossing interrupt
  attachInterrupt(0,zeroCrossingInterrupt, RISING);    
    //IRQ0 is pin 2. Call zeroCrossingInterrupt 
    //on rising signal


//Interrupt Service Routines

void zeroCrossingInterrupt(){ //zero cross detect   
  TCCR1B=0x04; //start timer with divide by 256 input
  TCNT1 = 0;   //reset timer - count from zero

ISR(TIMER1_COMPA_vect){ //comparator match
  digitalWrite(GATE,HIGH);  //set TRIAC gate to high
  TCNT1 = 65536-PULSE;      //trigger pulse width

ISR(TIMER1_OVF_vect){ //timer1 overflow
  digitalWrite(GATE,LOW); //turn off TRIAC gate
  TCCR1B = 0x00;          //disable timer stopd unintended triggers

void loop(){ // sample code to exercise the circuit

OCR1A = i;     //set the compare register brightness desired.
if (i<65){i=483;}                      


OUR PROBLEM IS: The Zero Cross detection doesn’t work. We’ve checked the interrupt-routine and it does do what it’s supposed to do - when it sees a rising edge it is triggered (5V cable directly to arduino pin-2). To test this we just had an integer counting up inside the interrupt routine as follows:

void zeroCrossingInterrupt(){ //zero cross detect   
  TCNT1 = 0;
  j++;  //our integer counter

In the main loop we had this integer printed via Serial.print() to check if the value is rising steadily. I realize that the Serial.print is probably too slow to catch all the values, but it should at least prove that the value is changing, e.g. rising. (+50 per second shouldn’t overflow it soon). The integer was initialized globally with value 0.

As I understand the circuit, the “usual” state of the DETECT-pin (interrupt pin 2, in code 0 for some reason – IRQ0 – but it works anyway) is GND. As soon as the optocoupler sees a phase change the driving voltage is too low to trigger the diodes on the other end - so the internal pull-up of the arduino should pull the DETECT-pin to high. (btw we tried an external 8.2k-pullup as well, same result). The interrupt routine should trigger the timer then AND our variable j++. It doesn’t though - j remains at 0 as it was initially. The timer isn’t triggered either since there’s no ouput (that part of the circuit works).

What’s sort of weird is that the value DOES change when we unplug the 230V-cable from the circuit - it jumps to some random value (45 or so) - I guess unplugging means a few on-offs. So some form of detection between no voltage and voltage is there - which means it shouldn’t be completely bricked (I hope).

any help would be great, we’re out of ideas.
best regards,

p.s. the schematic doesn’t mention that it is important that the MT2 pin of the triac has to be the one connected to the triac-driving-opto, NOT MT1 - which we didn’t know at first and only found out after some research. That part of the circuit works (we can turn a lamp on and off).


TRIAC: Q6015L5

zero-cross detector opto: H11AA1

triac driver opto: MOC3052-M

to add a bit of information: we used standard carbon film resistors (0.25W). We figured that 230V/30k = 7.6mA, so 1.7W...oO :/

I think I just found a problem don't they usually just die when there's too much power right? Because they clearly didn't or at least when I measured them afterwards they were still functional weird

The circuit shown in the link you gave is designed for 120V operation. You'll need to double the values of R1 and R2 to operate it from 230V. If you don't then the LEDs in the optoisolators will remain on (they take a finite time to extinquish, when the current falls to zero), or the phototransistors take a long time to switch off after being turned on so hard. This means you won't detect any zero crossings.

oh, that makes sense, thanks a lot :) i'll try that on friday or so as soon as I can get the parts

just got the parts and tested it and IT WORKS :D

Video (I covered the bulb so the sensor doesn't overexpose)

thank you thank you thank you

I see what you did there with your foot :)

Couldn't you have just used a snubberless TRIAC that does the zero crossing/latching work for you?

Hi everyone.

I've got this setup also and it works kinda.

My pcb though is abit different since i used i think 3-4 different AC Phase Control schematics to build my circuit.

From what i see on my part is that im using H11A1 and MOC3053 (same as you) but i dont have any resistors in my case (im also running 230 AC, here in Sweden).

What would be the impact of this compared to having those resistors?

Below is the schematic: |500x305

Thanks for the input