Zero-crossing pulse as related to a AC sine wave.
Fig. 1

Zero-Crossing Detectors Circuits and Applications

by Lewis Loflin

Updated circuits: Improved AC Zero Crossing Detectors for Arduino.

A zero-crossing detector is used to generate a sync pulse related to the AC voltage phase angle often used in power control circuits. Fig. 1 shows the relationship of a zero-crossing pulse to a sine wave. The pulse occurs at 0, 180, and 360 degrees.

Zero-crossing pulse detector circuit using a H11AA1 opto-coupler.
Fig. 2

Fig. 2 shows how to use a H11AA1 opto-coupler to generate a TTL level pulse. During most of the time the photo transistor output is LOW except when the voltage is near zero when the collector goes HIGH. The dual LED emitters of the H11AA1 assures both half-cycles are utilized.

Zero-crossing pulse detector circuit using a 4N25 opto-coupler.
Fig. 3

Fig shows a more common opto-coupler such as a 4N25, but to use both half-cycles will require a diode bridge input.

Arduino with zero-crossing detector for AC power control.
Fig. 4

Fig. 4 shows a direct application of a zero-crossing detector using an Arduino micro-controller to control the power output to a lamp. This variation still uses the H11AA1 but can be directly connected to 120VAC. The sketch is shown below.

The output of the H11AA1 is connected to Arduino DP2 to use its internal interrupt INTR0. When the switch on DP4 is closed a LOW is detected and the program connects interrupt 0 turning on a interrupt service routine acon.

The ISR reads the value of the potentiometer on AN0, divides by 4, then calculates a delay based on that value. The longer the delay (between 200uSec. and 8.3mSec.) the less power delivered to the load. The circuit will act as a lamp dimmer.

When the switch is opened the interrupt is detached and the lamp goes off. See the following related pages:

Purpose: to detect zero crossing pulse at INT0 digital pin 2,
which after delay switches on  a triac. 
Power activate by external switch

#define triacPulse 5
#define SW 4
#define aconLed 13

int val;

void setup()  {
   pinMode(2, INPUT);
   digitalWrite(2, HIGH); // pull up
   pinMode(triacPulse, OUTPUT);
   pinMode(SW, INPUT);
   digitalWrite(SW, HIGH);
   pinMode(aconLed, OUTPUT);
   digitalWrite(aconLed, LOW);

void loop() {
  // check for SW closed
  if (!digitalRead(SW))   {
    // enable power
    attachInterrupt(0, acon, FALLING); 
    // HV indicator on
    digitalWrite(aconLed, HIGH);
  }  // end if
     else if (digitalRead(SW)) { 
       detachInterrupt(0); // disable power
       // HV indicator off
       digitalWrite(aconLed, LOW);
     }  // else
  } // end loop

// begin ac int routine
// delay() will not work!
void acon()  
    delayMicroseconds((analogRead(0) * 7) + 200); // read AD1 
    digitalWrite(triacPulse, HIGH);
    // delay 50 uSec on output pulse to turn on triac
    digitalWrite(triacPulse, LOW);

Web site Copyright Lewis Loflin, All rights reserved.
If using this material on another site, please provide a link back to my site.