In any automatic night light circuit that's meant to switch on perimeter security lights, the time period we are most interested in is dusk and dawn. We want the lights to be switched on at dusk and turned off at dawn. (Whether the lights are turned on/off earlier or later is dependent on the user.) During the night we want the lights on regardless of lightning flashes or car headlamps shining on the sensor or bright city lights being reflected by the clouds or a full moon or what have you. During the daytime we want the lights off regardless of clouds rolling in and out and thus momentarily blocking the sun, or a very overcast day, or a heavy downpour. Of course we would want the lights turned on even during the middle of the day if for some reason utter darkness descended such as during a (near) total solar eclipse, or--if we wanted to test the circuit--if we covered the sensor with some opaque material.
here and here. Just a summary of how it works: R1 and LDR form a voltage divider. When the voltage across LDR is greater than across the 10uF capacitor, the cap gets charged via D1. When voltage across the cap is greater than across LDR, the capacitor discharges via R2. Given how D1 shunts R2 during charging and given that R1 has a much lower value than R2, the net result is that charging rate is faster than discharge rate. This means that when there is an abrupt and large increase in the level of ambient light (LDR resistance decreases) the voltage across the cap decreases slower compared to when there is sudden and large decrease in light level (LDR resistance increases). In other words, the circuit has a greater inertia to positive changes in light level than to negative changes in light level. During daytime, assuming the sensor were located outdoors and were we to shroud it with a black opaque bag, the voltage output would within seconds rise close to VDD. Were we then to take off the bag, the voltage would drop back to near ground level but a slower rate than when darkness fell upon the LDR.
Recently I provided an update on the MCU-based ANLC I'm testing. It's still a work in progress but I thought I'd provide more information on the algorithm I'm using to try and mimic the asymmetric filtering action of the analog circuit above.
One way of implementing a low pass filter digitally is to compute for the moving average (MA). We can read the ambient light level at fixed time intervals and store the values in a one-dimensional array. Every time a new reading is performed the oldest reading is discarded and the new reading stored. The readings are summed and average computed.
One problem with the MA filter is that it will not provide the asymmetric filtering. As the graphs below show, an MA filter reacts the same way whether the light level is increasing or decreasing. Another characteristic of the MA filter is that a large number of readings are required to sufficiently attenuate light level changes that have a high dV/dt (change in voltage over change in time). Having a large number of readings is analogous to having large capacitance. A large cap takes longer to charge/discharge. More readings means there is more inertia to new readings. But lots of stored readings translates to memory guzzling, specially because 16-bit values are going to be stored. Because it can't meet the specs we have to conclude that the MA filter is unsuitable for this application.
Because the charge and discharge rates of the capacitor in the analog circuit above is what provides the filtering action, we can implement this digitally by limiting the dV/dt of light level readings. Here dt translates to the interval between reads by the analog-to-digital converter. If this interval is fixed then we need only deal with dV. Because we want to have more inertia against increasing light levels we can limit the dV when it is positive much more strongly when dV is negative. This is easily done in firmware by comparing the previous and current light level readings. If the difference exceeds the maximum positive (or negative dV), then we only store a value equal to the previous reading plus the positive dV (or minus the negative dV).
dV+ = maximum permitted change in voltage if voltage is increasing
dV- = maximum permitted change in voltage if voltage is decreasing
Vi = current voltage reading -- will be adjusted to meet max dV
Vi-1 = previous voltage reading -- already adjusted to meet max dV
and assuming that Vi contains the latest raw/unmanipulated ADC reading, the algorithm for what we can call an asymmetric dV attentuation or ADVA filter is as follows (written in pseudo C):
if (Vi > Vi-1 && Vi - Vi-1 > dV+)
Vi = Vi-1 + dV+
if (Vi < Vi-1 && Vi-1 - Vi > dV-)
Vi = Vi-1 - dV-
Manipulation of the light reading is performed only if and when either of the dV limits are exceeded. Otherwise the raw reading is accepted as is.
From a record of ambient light levels during dawn and dusk we can determine that the maximum dV/dt = ~4V / 15min = ~4.5mV/s @VDD = 5V. Therefore, assuming dt = 1s, we can let dV+ equal to some value close to 4.5mV while dV- can be much larger in order to create the asymmetry.
To see how the MA and ADVA compare with one another I did a simulation using a spreadsheet. Check it out to see the numerical values used. Below I've pasted the graphs from the simulation. For the MA the number of readings averaged = 16. For the ADVA, dV+ = 0.01V, dV- = 0.25V. These dV values are the ones I'm currently using in a bench test.
The above simulates night condition where a transient bright light condition occurs (eg. a flashlight is shone directly at the sensor for many seconds). The light level is the blue rectangular pulse. The red curve is the MA response, while the yellow-orange curve is the ADVA output. Compared to the ADVA the MA has a much steeper slope. Because the MA averages 16 readings, after a time interval of 16, the MA output = to the sensor output. The ADVA on the other hand barely budges from its initial value.
Now let's say the sensor output voltage at which the load is turned on is 1V and the hysteresis band = 1V (and so the load turn-off voltage = 2V). With the MA the load will be turned on and then off with this particular burst of light on the sensor. The ADVA meanwhile will be immune to it. For the transient to get the ADVA to trip the load, it has to be sustained for a much much longer time.
Note the MA and ADVA waveforms: triangular and sawtooth, respectively. As we will see the waveforms will change depending on the input signal.
The above simulates daytime condition with the sensor suddenly immersed in darkness (eg. it was covered with a thick black plastic bag). The results are interesting. The MA and ADVA overlap each other during the downward slope. But this is just a coincidence. For a different number of readings for the MA or a different dV-, each of them will have a different negative slope. Nevertheless, with either filter the load will be turned on (assuming, as before that the trip levels are 1V and 2V). But when the light level returns to "normal," you can see how the ADVA takes its time rising. This means that it will be a very long while (about a hundred seconds in an actual bench test with dt = 1sec and dV+ and dV- as per simulation values) before the load is switched off.
Any light level increase with a rate of change greater than those during dusk or dawn will be attenuated by the ADVA. What surprised me in the above is how a triangular input to the MA results in a (quasi?) Gaussian waveform.
Because the rate of decrease in the light level above is less than dV- the ADVA tracks the light level while it is decreasing and thus we see the waveforms overlapping. However, the two part ways when light level begins to increase.
Out of curiosity I tried out geometric changes in light level. The one above and below use a factor of 1.05. The ADVA tracks the increase in light level until the point where it exceeds dV+.
Because the negative rate of change of the light level is well below dV- the light level and ADVA waveforms overlap.