I needed to log when a light switched on and off during the night as part of debugging an oddly behaving movement sensor. To do that I built a really simple light sensor logger using an Arduino Leonardo, a large LED and a resistor or three. Here it is:
And here's the entire Arduino code:
analogReference(EXTERNAL);
Serial.println(analogRead(A1));
The main loop() just reads the voltage across the LED from analog input A1 and writes it to the serial port. Then it waits for a second. The setup() routine tells the ADC converter to use the voltage on AREF as the reference maximum voltage for the ADC.
The LED has a voltage of between about 0mV and 400mV depending on the amount of light.
By default the voltage range of the ADC on the Arduino Leonardo is 0V to 5V but it's possible to scale it with a call to analogReference().Calling analogReference(INTERNAL) would set the range to 0V to 2.56V which is still a bit large given the small voltage across the LED. AREF to the rescue!
The AREF pin allows a range to be set for the ADC. It has an internal resistance of 32K and I added a 66K resistor (made from three resistors I had lying around) connected to the Arduino's 3.3V pin. The 66K and 32K form a voltage divider giving an AREF of 1.1V (which is the low end of valid AREF values). Then it's just necessary to call analogReference(EXTERNAL).
Here's the output of the program when I had covered the LED with my hand and then uncovered it.
You can also use the built in Arduino Serial Plotter to get an instant chart. Here I covered the LED with my hand, took my hand away and then shone a torch directly into the LED.
To get timestamped output I am using
CoolTerm which will automatically save to a file and add timestamps.
That light sensor via LED relies on the photovoltaic effect: when light strikes the PN junction inside the LED it creates a voltage (albeit a small one). But there's another way to measure the light hitting an LED.
Reverse bias
If the LED is reverse biased (i.e. connected to a voltage source the wrong way round) then it won't light up but it will
act as a capacitor that charges when light hits it. So the idea is to reverse bias the LED using two digital pins on the Arduino (one set HIGH and one set LOW) and then remove the bias and measure how long the LED (acting as a capacitor) takes to discharge. The brighter the light the faster the discharge.
This can be achieved with a single LED connected between two digital pins like this: the +ve lead of the LED goes into the pin identified by LED_P and the -ve into the pin identified by LED_N.
And here's the code.
#define LED_N 4
#define LED_P 5
void setup()
{
Serial.begin(9600);
}
void loop()
{
unsigned long maxtime = 5000;
pinMode(LED_N, OUTPUT);
pinMode(LED_P, OUTPUT);
digitalWrite(LED_N, HIGH);
digitalWrite(LED_P, LOW);
pinMode(LED_N, INPUT);
digitalWrite(LED_N,LOW);
unsigned long elapsed = 0;
unsigned long start = millis();
while ((digitalRead(LED_N) != 0) && (elapsed < maxtime)) {
elapsed = millis() - start;
}
Serial.println(elapsed);
if (elapsed < maxtime) {
delay(maxtime - elapsed);
}
}
I found this worked better than the first version with more sensitive output. Note that smaller numbers mean brighter here (whereas in the previous code smaller meant darker). Here's a plot showing me covering the LED twice with my hand, followed by shining a torch at it. Each time I let the LED be exposed to ambient light between tests.
In action
Certainly looks like that motion sensor is turning the light on in the night uselessly.