The unit is very efficient - I use 4x AA NiMH batteries which last over a month in typical use. The circuit uses a high-brightness LED, but driven at a lower current. The firmware makes use of the Picaxe's "SLEEP" command, so that the CPU is only running for a fraction of the total uptime.
I don't want to put a dollar figure on the parts, because each user will have different sources for their parts (I'll provide some links later). By fabricating my own circuit board I built the whole thing for under ten US dollars.
Step 1: Design
It's a pretty simple circuit, based on an 8 pin Picaxe 08M. This was what I had on hand, you could also use the newer 08M2.
It uses an LDR and a 1M2 resistor to form a voltage divider on pin 1 of the Picaxe. There's an orange LED connected to pin 4 of the Picaxe via a 1k2 resistor. This limits the current through the LED to about 5mA. This reduces the LED brightness, but it's still sufficient to provide a dim light if your eyes are adjusted to the darkness (I use it in my hallway so I can avoid tripping over at night, but not wake the household by turning on the main light)
Pulldown resistors are used on the unused Picaxe pins - it's good practice not to allow I/O pins on a microcontroller to "float" and I think it also reduces current consumption very slightly. I used 110k resistors for the pulldowns, because I had a lot on hand. You could use anything around 100k.
The LED is driven straight from the Picaxe so it's important to limit the total current from this pin to under 20mA.
The cicruit draws less than 1mA when the LED is off, and about 5.5mA when the LED is on. I run mine from 4 AA NiMH rechargeable batteries (which supply about 5V) which last about a month on average, before I need to recharge them.
The software spends most of its time in "sleep" mode, and only wakes up every 2.3s to check the state of the LDR. Before reading the LDR, it turns off the LED so that its light output doesn't affect the reading. The reading happens so quickly the LED can hardly be seen to flicker when it is very briefly turned off. In order to avoid the LED turning on and off repeatedly around dusk, some hysteresis is built into the code. This is done very roughly by calculating an average value for the ambient light, so that changes in the ambient light take a while to propagate in the code. The raw ADC reading is also divided by 10 to minimise noise.
The code I have attached works on the Picaxe 08M. You should be able to convert it to run on the 08M2 by using the wizard built-in to the Picaxe software
CPU: Picaxe 08M.
LDR: Simliar to Philips ORP12. I used the RD3480 from www.jaycar.com.au
LED: high-brightness 5mm amber LED. I used the ZD0295 from www.jaycar.com.au
PCB: A custom board I designed in Eagle and etched myself. All the design files are attached to this Instructable
Case: I designed the above PCB to mount in a HB6005 clear plastic case from www.jaycar.com.au
Capacitors: 1x 100uF 16v; 1x 100nF, 50v.
Resistors: 1x 1M2; 2x 110k; 1x 22k; 1x 10k; 1x 1k2. all are 1/4w meetal film types (but it probably doesn't matter)
Miscellaneous: Power socket, battery holder (the circuit requires 5V - I used 4x 1.2V AA rechargeable batteries), programming header, about 15cm of insulated hookup wire
If there's a lot of interest for this circuit, I'll get a batch of PCBs and make a kit available.
Below are the Eagle files for the schematic and PCB. There's also a full-size PDF of the PCB tracks if you're etching your own PCB.
Step 2: Construction
If you've never made your own PCBs before, search right here on instructables, or read the process described by my local hackerspace: http://www.makehackvoid.com/projects/pc-pcb-under-30-minutes-quick-n-easy-pcb-fabrication.
If you're using a double-sided board, there's only one track on the top layer. If you're using a single-sided board, you'll have to replace this track with a wire link.
I used a small IC socket socket to mount the Picaxe chip itself.
I used a 3pin header for the Picaxe programming cable. Change this to suit your programming cable - some cables use a 3.5mm stereo plug.
In the photos you can see that the LDR is mounted on the other side of the PCB from all the other components. This is because my original firmware didn't switch off the LED before measuring ambient light, therefore the LDR had to be physically shielded from the LED. It didn't work well, which is why I fixed the firmware. The LDR can now be mounted on either side of the PCB, it doesn't matter.
The PCB is sized to fit in the popular UB5 project box. I used a clear box so the light from the LED is soft and diffuse.
Step 3: Downloads
Cadsoft Eagle schematic & PCB suite
This might be the last Instructable that I publish that relies on the software above. In the interests of supporting open-source software, I'm trying to move to Arduino for the microcontrollers and Kicad for the schematic and PCB design. Both these packages have become very user-friendly in the last few years and I highly recommend them. Have a look at http://www.arduino.cc and http://www.kicad-pcb.org/ for more info.
Copy and paste the text below into the Picaxe Programming Editor. It should work as-is for the Picaxe 08M. Use the wizard built in to the Programming Editor to convert to 08M2-compatible code.
'LED night light for Picaxe 08M.
'Written by Nick West 2012 & 2013.
'Released under a Creative Commons Attribution & Sharealike licence.
symbol AVE_ADC = w0 'moving average of ADC connected to LDR
symbol ADC_READ = b2
symbol LED = 4 'LED is on this pin
symbol LED_FLAG = b3
symbol TWILIGHT_THRESHHOLD = 20 'change this to change the light levels that trigger the LED
pause 20 'let everything stabilise after waking up.
if pin4 = 1 then let LED_FLAG = 1
else let LED_FLAG = 0
low LED 'briefly power down LED to take ambient light reading.
readadc 1,ADC_READ 'voltage divider using LDR & 1M2 resistor on pin1
if LED_FLAG = 1 then high LED'if the LED was on before the ADC reading, turn it back on, so it doesn't flicker so noticeably
ADC_READ = ADC_READ /10 'decrease resolution of ADC to improve hysteresis
AVE_ADC = AVE_ADC + ADC_READ 'moving average of ADC
AVE_ADC = AVE_ADC / 2
if AVE_ADC > TWILIGHT_THRESHHOLD then high LED 'bright LED & 1k limiting resistor on pin4
elseif AVE_ADC <= TWILIGHT_THRESHHOLD then low LED
disableBOD 'brownout detection disabled to minimise sleep current
sleep 1 'minimal current draw for ~2.3sec