
Fig. 1: Zero-crossing pulse timing relative to the AC sine wave.
In AC power control applications like dimmers or motor speed controllers, "firing" a Triac at the wrong time—such as at the peak of the voltage cycle—can cause massive current surges and EMI (Electromagnetic Interference). A zero-crossing detector is essential to synchronize firing pulses to the precise moment the AC voltage crosses zero, ensuring smooth, efficient power regulation.
The H11AA1: A Bidirectional Solution
The H11AA1 is uniquely suited for this task. Unlike standard optocouplers that require a diode bridge to rectify AC, the H11AA1 contains back-to-back LEDs at the input. This allows it to respond to both the positive and negative half-cycles of the AC line directly, providing a clean 120 Hz pulse train (in a 60 Hz system) that marks every time the voltage passes through zero.

Fig. 2: H11AA1 zero-crossing detector.
Arduino Implementation & Safety
When interfacing with the AC line, isolation is paramount. The optocoupler provides the necessary galvanic isolation between the lethal mains voltage and your low-voltage microcontroller. By connecting the output of the detector to an Arduino interrupt pin (e.g., INT0), you can precisely time the delay required to fire the Triac, thereby controlling the RMS power delivered to the load.
Arduino Sketch: Triac Power Control
/*
Zero-crossing triac control
INT0 (pin 2) = zero-crossing pulse
Pin 5 = triac gate
Pot on A0 sets power (phase delay)
*/
#define TRIAC_PIN 5
volatile bool fireTriac = false;
void setup() {
pinMode(TRIAC_PIN, OUTPUT);
// Interrupt triggers on every pulse
attachInterrupt(digitalPinToInterrupt(2), zeroCross, FALLING);
}
void loop() {
if (fireTriac) {
// Phase delay logic (0 to 8.3ms for 60Hz)
int delayTime = (analogRead(A0) * 8) + 200;
delayMicroseconds(delayTime);
digitalWrite(TRIAC_PIN, HIGH);
delayMicroseconds(50); // Pulse duration
digitalWrite(TRIAC_PIN, LOW);
fireTriac = false;
}
}
void zeroCross() { fireTriac = true; }