It's a bit more complicated than I may have led you to believe, but not all that much so. Let's take a look at the blocks.
Memory:
The memory is nearly as expected straight off the data sheet. I have the address and write protect lines wired low to make life simpler. R7 & R8 provide the expected pull up resistors for the I2C protocol but there is an LED in parallel with the SCL signal. D2 is basically my status LED and the only means by which I can communicate with a user. The SCL signal is used because the memory chip will not respond to "spurious" changes on that line. An I2C start condition requires the SDA line to go low while the SCL line stays high. So as long as the SDA signal stays high, the memory chip will ignore changes on the SCL line.
Communication:
Q1 & Q4 are setup so that no current flows while not sending or receiving data. Since the device will spend most of the time logging, it's prudent not to have any excess idle current draw. Q1 didn't have to be a FET, but it just made it easier to deal with inputs that could range something like +/-12 volts. The TX pin of the MCU is combined with another feature of the circuit, so Q4 will turn on during normal operation for small amounts of time, but R3 was sized to reduce power consumption.
Detector:
The first major change to the detector is the addition of Q3. It takes only small amount of time to measure a light sample, so the circuit really spends most of its time idle. The amplifier has a quiescent current of 230uA which isn't half bad, but not as good as zero. The ambient light sensor is much worse, drawing several mA in full sunlight. So Q3 is only turned on just prior to reading sample, which in turn supplies power to the light sensor and amplifier. As a side effect, Q3 also turns on, but hey, I only had so many I/O pins to work with. I also added a pot to adjust the sensitivity of the sensor. The sensor will try to allow a current proportional to the amount of light (voltage source permitting) so the amount of resistance will directly have an effect on the voltage seen by the ADC. A lower resistance will provide less sensitivity, and a wider input range, while a higher resistance will max out and clip quite quickly. R2 is included only so that while programming the PIC12F1572, the amplifier output and data line of the programming tool don't drive each other directly. You may have noticed that the memory is never powered off; it has a standby current of only 1uA, and more importantly, the signal for Q3 cannot be used to turn it off and on while also being used as the TX line for communications.
Microcontroller:
As stated before, the PIC12F1572 doesn't have a ton to do, but it does make this whole thing work, and keeps the batteries alive. When power is turned on, LED D2 lights up and the device sits in a "ready" state. At this point it will accept requests from a PC to dump previous logging data, and assists in calibration. By exposing the light to full sunlight, the potentiometer can be adjusted by a watching the LED. Steady on means that the ADC is maxed out, and a rhythmic blink indicates that the ADC is reading between max and min values. So ideally, one would adjust the pot until the LED is steady, then back off slightly until it blinks. A slow blink indicates the battery is low.
How does the micro know that battery is low? Well I think the solution is rather ingenious, but I strongly doubt I'm the only person to come up with it. I already discussed the fixed voltage reference used to ensure consistent ADC results over varying levels of battery. So why not measure the voltage reference using the battery as the upper ADC voltage. As the voltage of the batteries drops, the measured value of the fixed reference gets larger. Consider an 8-bit ADC result (0-255) with the voltage reference set tot 2.048 and the battery supply at a nominal 3V. We can come up with the equation Vref/Vbat*resolution = result. By substitution we get 2.048/3*255 = 174. That means a reading of 174 indicates a full battery. Our low end is unfortunately only 2.7V (that's the minimum input supply of our op amp, I would/will change op amps for future revisions, but it was one that I had on hand), but we can calculate that value too. 2.048/2.7*255 = 193. If we reada value larger than 193, we cannot assume that our op amp is properly biased. And that is all there is to it, just periodically make the measurement and blink the LED if necessary.
Now that covers the "ready" state of the device. but how do we get it to take light readings? By pushing reset button S1. Yes, the reset button. And yes, it does reset the device. This is another clever trick that I will pat myself on the back for. The PIC12F1572 has a control register that keeps track of the cause of a reset. Early in the code, that register is read to determine whether power was just supplied or the button was pushed. If the button was pushed, the device skips the "ready" state and starts a 16 second timer to allow a user to place the sensor. Then, for the next 24 hours, the circuit takes sunlight readings at approximately two minute intervals, after which it goes into a permanent sleep state.
Here is a screenshot of the program I made to accompany the project. It lets you connect to the device via a serial port and download the light data, as well as save or import the data as a CSV file. You can see that this particular data set is for a rather sunny day with little shade (though I hadn't calibrated it before running this test). It should also be noticeable that I began logging on the latter part of sunset as the beginning of the graph is mostly nighttime. Sunrise should be pretty obvious by that dramatic ramp up in recorded light. I'm actually quite proud of my background that I drew up.
Although it's an embarrassingly ugly construction, I'll show the working prototype anyway. There was definitely a lot of design after the fact leading to a bit of chaos. But I temporarily stuck it to the lid of a salsa jar (my "weatherproofing") using a little putty and it works just fine. We can look into a few of the design hurdles in the next post.























