Ambient Light Monitor: Zero-Cross Detection

August 16, 2015 by Robert Keim

Part 4 in the “How to Make an Ambient Light Monitor” series

Part 4 in the “How to Make an Ambient Light Monitor” series

Recommended Level


Previous Articles in This Series

Required Hardware/Software

Description Quantity Digi-Key p/n
Breadboard 1 377-2094-ND
Receptacle-to-plug jumper wires 5 1471-1231-ND
Ambient light detector 1 425-2778-ND
4.7 kΩ resistor 1 4.7KQBK-ND
General purpose op-amp 1 LT1638CN8#PBF-ND
0.1 µF capacitors 4 399-4266-ND
Comparator 1 LTC1440CN8#PBF-ND
1 MΩ resistor 1 1.0MQBK-ND
10 kΩ resistors 2 10KQBK-ND
2.2 kΩ resistor 1 2.2KQBK-ND
12 V AC/AC wall-mount power supply 1 T1007-ND
5 V AC/DC wall-mount power supply  1 1470-2771-ND

Project Overview

In the previous project, we succeeded in generating and digitizing reliable ambient light measurements using the GA1A2S100 optical sensor. There are various ways we could use these measurements: for example, assessing indoor illuminance in relation to time of day and weather conditions, tracking occupants’ use of artificial lighting, or correlating ambient light levels with different types of bulbs or lamps. A more proactive application is to use the ambient light data to adjust, in real time, the amount of illumination provided by a light fixture. In other words, we can implement a lamp dimmer that is controlled not by a manual switch but by the EFM8, based on ambient light measurements from the GA1A2S100.

Our lamp dimmer consists of two main sections. First is the zero-cross detection circuit, which outputs a digital signal to the EFM8 every time the AC input voltage crosses 0 V. Second is a control circuit in which the EFM8 uses a device called a triac to limit the amount of AC current passing through the lamp. The zero-cross detection circuit allows the EFM8 to synchronize its triac drive signal with the beginning of the AC cycle, and by increasing or decreasing the delay between the start of the cycle and the signal that enables the triac, firmware can control the average power delivered to the lamp. We will discuss the triac-based control circuit in the next article; here we will focus on the zero-cross detection portion. Note: this dimmer implementation is intended for incandescent bulbs—standard compact fluorescent bulbs are not compatible with this circuit.


Comparators are perhaps somewhat overlooked in this age of single-supply, rail-to-rail op-amps and fully integrated ADCs. But comparators still have their place: they are optimized for their stated purpose—comparing, not amplifying—and they sometimes incorporate such useful features as an integrated voltage reference and conveniently adjustable hysteresis. In this circuit we will use the LTC1440 from Linear Technology, which includes the features just mentioned as well as separate pins for signal ground and negative supply. This means that we can use bipolar (i.e., +/- 5 V) supplies but still have the comparator’s output signal referenced to ground; this is important, because we don’t want to send -5 V to an EFM8 general purpose input/output (GPIO) pin. The circuits discussed in this article make use of this separate ground reference pin, which is why the outputs transition between +5 V and 0 V rather than +5 V and -5 V. The positive 5 V supply is not a concern because the EFM8’s GPIO circuitry, though powered by 3.3 V, is designed to safely accept 5 V input.


Theoretically, a dimmer circuit like this would operate on the standard 120 V power coming out of an electrical outlet. But we don’t want to bring 120 V onto a breadboard (safety first), and we don’t need that kind of power simply to demonstrate the functionality of the circuit. Hence, we will bring in AC voltage using a 12 V wall-mount AC/AC transformer.

In addition to this we will need three other voltages: 3.3 V for the optical sensor and +/- 5 V for the comparator (we will also use 5 V instead of 3.3 V to power the op-amp, mainly because this makes better use of the two positive power rails available on the breadboard). The 3.3 V and +5 V supplies come from the EFM8 evaluation board via the expansion header, and the -5 V is easily obtained from a second wall-mount power supply:


These slim devices are an inexpensive (about $7) and convenient way to provide bipolar power to a breadboard or prototype PCB: you simply connect the positive line to the existing ground node and then the negative wire becomes, in this case, -5 V.


Comparator circuits are fairly straightforward: If the voltage at the positive input is higher than the voltage at the negative input, the output is driven to the positive supply rail. If the voltage at the positive input is lower than the voltage at the negative input, the output is driven to the negative supply rail or to the circuit’s ground potential. (Actually, some comparators use an open-drain/open-collector output stage and thus do not actually “drive” the output to the positive supply voltage.) But a comparator circuit this simple might have a serious problem with noise, and this is where hysteresis comes in. Consider the following basic circuit:

With an ideal sine wave input, the output is as follows:

So far so good, but ideal sine waves are in short supply; if we add 50 mV of 100 kHz noise to the input signal, we get the following output transitions:              

Though the signal of interest (i.e., the theoretically noise-free 60 Hz sine wave) makes only one transition above or below the comparator threshold (in this case, 0 V), the noise signal causes spurious input transitions that lead to equally spurious output transitions. Of course the 100 kHz noise in this example could easily be suppressed with a low-pass filter, but a real-life input signal might be afflicted by many frequencies of noise as well as unpredictable transients. Thus, we turn to hysteresis, which in this particular application is the technique whereby the comparator threshold for negative-to-positive transitions is different from the threshold for positive-to-negative transitions:

As indicated by the cursors, the threshold for the negative-to-position input transition is about 50 mV above the nominal threshold, and the threshold for the positive-to-negative transition is 50 mV below the nominal threshold. After the input voltage increases past 50 mV, causing an output transition, the input must then fall below not 50 mV but negative 50 mV in order to cause another output transition. The result is a hysteresis voltage band: after an input transition causes a comparator output transition, the input voltage can fluctuate without triggering another output transition as long as the fluctuations remain within the hysteresis band. In this example, the hysteresis voltage band is 50 mV - (-50 mV) = 100 mV. With hysteresis included in the circuit, the output transition looks like this:

There are various ways to incorporate hysteresis into a comparator circuit; in this project, we will use the LTC1440’s integrated hysteresis functionality. The process of configuring the LTC1440 for the desired hysteresis band is described in the next section.


Here is the schematic for our zero-cross detection circuit:

And here is the breadboard implementation:

R1 and R2 form a resistive divider network that reduces the input voltage to a level that is compatible with the comparator input stage. You may recall that the wall-mount AC/AC transformer is rated for 12 V output, but this refers to the root-mean-square (RMS) voltage. The peak amplitude is

We need to ensure that the input voltage is always within the acceptable input range, so the resistive divider network is designed to produce about 3 V when the input is 17 V.

The hysteresis voltage (i.e., the difference between the nominal threshold and the actual positive-to-negative or negative-to-positive threshold) is equal to the voltage difference between the REF pin and the HYST pin; it follows that the hysteresis voltage band is equal to twice the voltage between REF and HYST. The REF pin is always 1.182 V above the negative supply, so the current through R3 is 1.182 V / (10 kΩ + 1 MΩ) = 1.17 µA (the LTC1440 requires that this current be between 0.1 and 5 µA). Thus, the hysteresis voltage is 1.17 µA × 10 kΩ = 12 mV. We are starting with a moderate amount of hysteresis because the purpose of this circuit is to identify the moment at which the input waveform crosses 0 V, and hysteresis results in a small delay between the input transition and the output signal. If we experience serious problems with spurious transitions, we simply increase the value of R3.


The output signal from the comparator is detected using the EFM8’s two external interrupts, with one sensitive to rising-edge transitions and one sensitive to falling-edge transitions.    

(For some reason the original 8051 architecture included external interrupt configuration bits in a timer control register.) Both of these interrupts can be assigned to the same GPIO pin; one interrupt will fire whenever P0.0 sees a rising edge, and the other will fire when P0.0 sees a falling edge.

The functionality of the current firmware is to count the rising- and falling-edge transitions and display the corresponding frequency. The purpose is simply to confirm that the number of detected transitions corresponds to the expected frequency, i.e., 60 Hz. Here are the two interrupt service routines for the external interrupts:

	//the interrupt flag is cleared by hardware

	//the interrupt flag is cleared by hardware

The primary while loop from the previous project has been modified as follows:


	//wait until the conversion is complete

	//retrieve the 10-bit ADC value and add it to the accumulating sum in RawADCResult
	RawADCResult = RawADCResult + ADC0;

	/*if we have enough measurements to compute an average,
	 shift right to divide the sum by the number of measurements*/
	if(NumberofMeasurements == TWO_POWER_5)
		RawADCResult = RawADCResult >> 5;
		NumberofMeasurements = 0;

		//convert the averaged conversion result to a current measurement and display
		//the actual value of the resistor in the test circuit is 4.6 kOhms
		ADCMeasurement = (RawADCResult*ADCFactor)/4.6;
		//ConvertMeasurementandDisplay(CURRENT, ADCMeasurement);

		//display the number of cycles counted in the last second
		ConvertMeasurementandDisplay(FREQUENCY, RisingEdgeCount);

		RisingEdgeCount = 0;
		FallingEdgeCount = 0;

	/*the value 10700 (rather than 10000) was empirically found 
        to produce a delay closer to one second*/
	SFRPAGE = TIMER3_PAGE; TMR3 = 0; while(TMR3 < (10700/TWO_POWER_5));

Instead of displaying the output current from the optical sensor, we display the number of rising edges counted in one second, which corresponds to the number of sine wave cycles per second. The firmware includes a new pixel data array for the unit Hertz, so we don’t confuse ourselves by displaying frequency using the wrong unit. As you will notice in the video below, there is some variation in the number of cycles from one second to the next. This is attributable primarily to timing irregularities, since we are not using a precise method to measure and synchronize the one-second intervals (this was confirmed by applying a stable 60 Hz square wave to the input pin; similar variations were observed). The important point at this juncture is that the measurements stay near 60 Hz, which indicates that our zero-cross detector is functioning properly.

Next Article in Series: Ambient Light Monitor: Using a Triac to Adjust Lamp Brightness


Give this project a try for yourself! Get the BOM.

1 Comment