Skip to content

2020-02-18 light meter

Light meter

As a small starting project this week, I made a simple (and uncalibrated) light meter.

It has been previously described that as unshielded semiconductors, LEDs can operate as photodiodes to measure light. They are not ideal for this purpose because the irradiated area is very small (i.e. they cannot capture much energy); this means they are less efficient at being sensors than proper photodiodes with large areas. Where photodiodes typically have a broad spectral responsivity, LEDs are more limited and have their best response near their designed emission wavelength, also reducing the amount of energy they can convert to signal.

When used as sensors, LEDs are typically operated with a reverse bias (i.e. voltage applied opposite to how it would be for light emission). In this regime, the semiconductor behaves similar to a capacitor as long as the voltage applied is lower than the reverse bias breakdown voltage; any light that hits the semiconductor releases charge and reduces the voltage on the "capacitor". Light intensity can then be read by charging the "capacitor", removing the voltage, waiting for an appropriate integration time, and then measuring the residual voltage on the LED using an analog to digital converter (ADC). Since LEDs are not optimized to be sensors, this means large integration times are required, especially in dimly-lit environments without much light to reduce the charge.

To counter these limitations I operated the LED in a Photovoltaic (unbiased) mode rather than the photoconductive mode (reverse biased). I simply connected the anode to an analog input and the cathode to ground.

As my LED I chose a 7-segment display with an extra dot/period element. This allowed me to use an LED device as both an input and output! I connected all of the numeric segments to GPIO pins on the ItsyBitsy, and connected the dot to an analog input. The display LEDs have a shared common, which I connected to ground through a 10K potentiometer to limit current.

In the course of this reviewing the pin layout for the ItsyBitsy to figure out why one segment was brighter than all of the others, I learned pin D5 is special: it outputs 5V rather than the 3.3V output of all of the other GPIO pins.

I chose to program the ItsyBitsy using CircuitPython because it allows for rapid iteration—the microcontroller loads new code almost immediately upon save rather than after the delay of a compilation and upload step.

Light meter demo video

Here is a video of the light meter in operation:

The responsivity of the detector is fairly non-linear; it seems to take much more light to advance a step at the high end than at the low end. I could correct for this by taking measurements of the output signal produced when a constant light source of known intensity is applied with a series of neutral density filters of known attenuation. The resulting light-to-reading map could be used to interpolate a tone transfer curve or look-up table that could relate numeric readings to more linear and calibrated output. Of course human eyes do not have linear response, so perhaps a calibrated reading is unnecessary since this is only a test device and will never be used for radiometry.

I added a button input, to confirm I could read it in via CircuitPython. It works, but I learned CircuitPython does not have interrupts so we can only check the button state in the normal course of the program loop.

I briefly tried to get the SPI red-green-blue LED of the ItsyBitsy to work, but was unable to do so using the DotStar library provided by Adafruit. Something to follow up on in the future.

Light meter code

The light meter code is as follows:

To see the output of print() commands (i.e. light level in this case) on a Mac, we can connect to the serial terminal exposed by the ItsyBitsy (the tty device may be different on your machine):

screen /dev/tty.usbmodem14201 115200
# (ctrl+A; ctrl+d to detach)