Wednesday, December 16, 2009

It's the season ... to automate

I don't celebrate Christmas but when there's an electronics design opportunity in it I don't complain. There are these Christmas lights which I have to switch on at night and then switch off before midnight. This is a nightly task which will go on till the end of the year. Well, as can be expected there are times when I'm not around to turn the lights on and there are days when I simply forget. And there has been at least one occasion when I forgot to unplug the lights from the outlet (that's what serves as the switch).

Got fed up so I decided to automate it. What I needed was for the circuit to know it's dusk, turn the lights on, keep them lit for several hours, and then have them off until dusk the next day. This is a temporary circuit--one month and it won't be used anymore--so I decided to just keep everything on a breadboard. I also decided that it would be best to keep the main electronics indoors with only the "dusk sensor" somewhere outdoors.

In a nutshell this is how the circuit works. The dusk sensor outputs an analog voltage proportional to the ambient light level. This is fed to a microntroller which switches the load when light level falls below a value determined by the user. After a preset time duration the MCU turns off the load.

The sensor is a simple voltage divider using an LDR and a 300K resistor. Its output is fed to an op amp configured as a voltage follower. The ultra high impedance of this buffer prevents any loading of the signal. The op amp output is then sent to one of the MCU's analog input channels. The analog signal gets digitized by its ADC. The MCU compares this value with the trip level selected by the user. The trip level is adjusted using a 10K potentiometer whose output is connected to another of the MCU's analog channel.

I've chosen an 8-pin Microchip PIC12F615 because the circuit needs only two inputs and one output and I need those inputs to be analog channels. I could've picked one from the PIC10F series but I don't have software to program those in C. I'm just not in the mood right now for assembly language. I have about half a dozen models of single-supply, rail-to-rail Microchip op amps around here. I just opted for the MCP6273.

Because there may be abrupt and transient changes in ambient light level (lightning flash, car headlamp glare, prankster shining a flashlight, etc.) it is necessary to make sure that the sensor/circuit ignores these changes, else intermittent switching of the load occurs. This can be done via hardware by adding a few components--a capacitor, diode, and maybe a resistor. It can also be effected in firmware. The latter is what I opted for--why put to waste all that MCU computing power and memory?

I developed an algorithm for this two years ago and is based on moving averages. Readings are taken at fixed intervals (one to several seconds apart--the longer the interval the more immune to transient changes in light level). Each reading is compared to the previous average. If it exceeds the average by a predetermined amount (meaning there has been an abrupt change in light level) this reading is replaced with the average plus or minus the maximum allowed change (added or subtracted depending on whether the light level has increased or decreased). Thereafter, the last eight readings are averaged and compared to the trip level. If this new average is below the trip level then the MCU turns the load on. A hysteresis value (deadband) is incorporated such that the average light reading must increase beyond the trip level + hysteresis before the firmware resets a flag bit which keeps track of the transition from light to dark and dark to light (analogous to the rising/falling edges of a square wave). If the light level is between the trip level and trip level + hysteresis, then no action is taken.

Power supply is an adapter from my collection of old chargers, adapters, and the like. The one I found suitable is an Ericsson phone charger. It's probably a linear supply--cubelike and heavy, implying a bulky transformer. Its output is around 5.3VDC which drops to around 4.5V when the gas guzzling DC relay (40-ohm coil) is connected. I didn't even bother using an oscilloscope to check ripple voltage. I just used the multimeter to see what the DC voltage was with and without the load. To help Ericsson along I added a 1000uF 10V filter cap. This pulled up the with-load DC to 4.8V. Fortunately the relay still functions at barely 5VDC this adapter outputs. A diode (D1 in the schematic) was placed in series to drop the supply to the chips to <5VDC just to make sure they'll be operating within their supply limits.

The MOSFET transistor I used to switch the relay is a 2N7000. Relay is an Idec 4PDT. Coil: 6VDC, 40-ohms. Contacts: 250VAC 6A. It's plugged into a socket so all the AC and DC wires can be conveniently screwed in and safely secured. I added LEDs to provide visual indicators for the status of the load. A high efficiency blue LED that requires only a couple of milliamps to be visible was used to indicate "on." This choice was made in order to reduce the total current load on the power supply when the relay is on.

The main breadboard and relay were plunked into a plastic box. The sensor was also put in its own small translucent box and situated outdoors some 10 meters from the main electronics. So far so good. I adjusted the potentiometer so the load turns on when the streetlights have already been on for some 15 to 30minutes. The circuit works as required and the MCU timer is right on the money, turning the load off in almost exactly 5 hours even if it's only using its internal clock oscillator.

I love these tiny microcontrollers.

Click on the schematic.


  1. Nice! This is exactly what I thought about sometimes ago.

    Why not connecting the LDR + divider resistor directly on the PIC? I think the little current draw wouldn't affect the measure.

  2. Hi! According to Microchip the input signal to the internal ADC should not exceed 10kohms. The LDR divider network has an impedance of hundreds of kohms. That's why there's a need for a buffer. Also the reason why I chose R1 potentiometer = 10K