Highly Sensitive Arduino Light Sensor




In the Bioluminescence Community Project at BioCurious, we've been working with a number of bioluminescent bacteria and algae. We'd love to be able to measure accurately how much light these organisms produce. Unfortunately, the amount of light they produce is quite faint, and although the human eye can easily detect them after adapting to the dark, photographing them in action takes very long exposures (check out our Bioluminescent Hourglass instructable!), and/or professional camera equipment.

Needless to say, quantifying the light output of these faintly glowing moicroorganisms in a small test tube takes some specialized equipment...

What we ended up with is an Arduino with a highly sensitive light sensor inside a copper pipe (to isolate the sample from outside light contamination) writing results to an SD card.  We also added an LCD so that we could see results displayed real time.

Step 1: Materials

Total cost: ~$65, not including shipping costs ($75 for version with LCD display).
Most of this is the Arduino Uno ($30) + data logging shield ($20). Everything else is dirt cheap.

At the heart of our light meter is the TSL237S-LF, a highly sensitive Light-to-Frequency converter. This isn't your ordinary photoresistor or photodiode, mind you. Those devices measure light intensity based on voltage or current changes, which means that the smallest light intensity is determined by the smallest voltages or currents you are able to measure. A light-to-frequency converter like the TSL237, on the other hand, converts light intensity into a series of square-wave pulses. The lower the light, the slower the pulses. That means you can trivially increase the sensitivity by increasing the amount of time across which you count the pulses. Which means the lowest intensity is determined by the on-chip noise inside the sensor, resulting in occasional spurious pulses even without light coming in.

This particular sensor has a typical dark frequency of 0.1 Hz - one pulse every 10 seconds (and in practice, we've seen far fewer than that). With an irradiance responsivity of 2.3 kHz / (μW/cm2), that would correspond to 0.000043 μW/cm2. Converting from irradiance to illuminance (Lux) gets complicated because the latter depends on human brightness perception, but that would work out to no more than 0.0003 Lux. In comparison, other commercial light sensors typically bottom out around 0.1-0.2 Lux. If you want to go any more sensitive, you'd have to go to a photomultiplier tube that can literally count individual photons, but that puts you in a very different price range...

To illustrate how sensitive this sensor really is, as I was hooking up the sensor to the arduino, I was covering the sensor with my hand to see the signal drop, and I noticed that it didn't drop to zero - not even close. So I covered the sensor with my second hand... and it still didn't drop to zero! And of course, when we put the sensor inside the copper tube, it *does* go to zero. That means this sensor can see through both my hands - maybe 1.5-2 inch of meat and bones. Not bad for a $3.33 sensor!

Step 2: Preparing Sensor Housing

The sensor housing consist of a piece of copper tube, cut to the dimensions of the test tubes we wanted to use. Get yourself a cheap pipe cutter. I always get a childish glee out of using one of these: just clamp onto your tube where you want to cut, and tighten the screw on the cutter every couple of turns. After tightening a few times, the tube will fall apart effortlessly.

*Carefully* drill a hole in one of the endcaps, either through the bottom of the cap, or as low as possible on the side. Use eye protection, and a vice or pair of plyers to hold the cap in place - metal shavings in the eye are no fun! After you've drilled the hole, stick the endcap onto the copper pipe, and mark how far you can push it down without obstructing the hole.

A 0.1-μF ceramic decoupling capacitor was soldered between the GND and Vdd leads of the sensor (as recommended in the data sheet). We're using a 12 inch piece of stereo cable from an old pair of earbuds to connect the sensor to the arduino (the data sheet recommends using a buffer or line driver for distances over 12".) The stereo jack also provides us with a very simple 3-wire connector. The cable on these earbuds often looks like it contains two wires, but it actually contains *four*: left channel, right channel, and one or two ground wires. Remember to thread the cable through the hole in the endcap *before* soldering the wires onto the sensor.

The light sensor + capacitor is potted in the endcap using black Sugru. The leads of the sensor were doubled back underneath the sensor to save space. See the cross section above for how everything is packed in. The Sugru serves a bunch of different purposes here:
  • Holds sensor, cap and wires firmly in place - important because we'll be shaking the heck out of this housing!
  • Acts as insulator between the leads
  • Provides a "bumper" so the test tube doesn't bang into the sensor while shaking
  • Prevents light leaking in through the hole in the copper endcap
  • Prevents copper tube from cutting off the cable carrying the signal
  • Provides stress relief for the cable
  • Provides some water proofing (in case we need it)
To encase the sensor, start by putting a layer of Sugru in the bottom of the endcap. Then squish a ball of Sugru onto the back of the sensor+capacitor, and fold the leads of the sensor over that ball. Make sure the Sugru gets in between all the leads and insulates everything. If you're paranoid, you could apply some thin shrink tube or liquid tape on the leads first, but that will take up more space in that very tight endcap. Once you're happy with how you've encapsulated the back of the sensor and all the wires, pull the earbud cable through the hole in the endcap to take up all the slack, and very gently press the sensor wad into the layer of Sugru at the bottom of the endcap. Now form a little donut of Sugru, sick that on the end of a retracted ballpoint pen, and seat that litle donut as a bumper around the front of sensor. Make sure the little dome of the sensor is completely unobstructed. Wet the copper pipe, and push it down into the endcap, stopping before the pipe reaches the hole in the side of the endcap (that's why you marked that level on the outside of the pipe earlier). Gently pull the pipe back out and check it has indented some of the Sugru around the inside edge of the endcap (if not, add a little ribbon of Sugru around the outside edge and try again), without disturbing the sensor itself. As a final touch, squish a tiny bit of Sugru into the hole the earbud cable is coming out until you are confident the metal won't cut the cable there, and then add a good dollop of Sugru more on the outside of the hole, to act as stress relief on the cable.

Step 3: Hardware Store Project Box

Inspired by the Dirt Cheap Arduino Enclosure Instructable by sonicase, we used a cheap electrical box from the hardware store as a project box. Not bad for a $2 enclosure that fits your Arduino perfectly! You just need to cut a few holes in the side for the power plug on the arduino (conveniently located behind one of the removable tabs on the electrical box), and the USB plug. Plus a slot for the SD card on the data logger shield, and a hole to mount the stereo jack where you plug in the cable coming from the sensor.

If you cram things in really carefully, you can even mount the LCD in the matching plastic cover that you can get at the hardware store as well. However, if you want to use jumper wires to connect the LCD to the Arduino, rather than soldering everything in place, you'll quickly run out of space for all the headers and jumper wires on the data logging shield and LCD. Easy solution: simply get a second electrical box, and mount that one on top of the first! Now you have a double-height project box, with room for one or two more Arduino shields if necessary.

Step 4: Electronics

Hooking up the electronics is fairly straightforward: Mount the Data Logging Shield on top of the Arduino Uno, and install the battery and initialize the Real Time Clock as described on the Adafruit website. Then wire up the stereo jack so GND and Vdd on the sensor are connected to GND and 5V on the Arduino, and the OUT pin from the sensor goes to Digital pin 2, where it can trigger interrupts on the Arduino.

If you're using a 16x2 LCD display, wire it up to headers on the data logging shield as described on the Adafruit website as well (the potentiometer to adjust the LCD contrast can be mounted on the spare prototyping area on the shield). As you can see from the pictures above, connecting the LCD with jumper wires takes a good amount of space. We tried to fold the jumper wires flat to make everything fit under the grey lid, but eventually we wound up stacking a second electrical box, for a double-high enclosure. (Feel free to ignore the additional Cat5 connector that we hooked up to some of the remaining pins. That one is intended for an optional accelerometer - if we're measuring light output of bioluminescent algae in response to shaking, it would be nice to be able to measure exactly how hard we're shaking them. We haven't yet used this feature so far, and the arduino code below doesn't include the accelerometer.)

The Arduino code for the version without LCD can be found here, with LCD here.

Step 5: Results!

The chart above shows the results from one of our experiments, testing how quickly dinoflagellates recuperate after having their bioluminescence exhausted by excessive shaking. Dinoflagellates are bioluminescent single-celled algae that light up when being perturbed. However, each cell only contains a limited amount of luciferin, so if you shake them for too long or too hard, their light output will quickly drop off.

The first peak in the graph above is a control test tube (~5ml) of dinoflagellates placed in the sensor tube, and then vortexed to entice bioluminescence. You can see a sharp peak followed by an exponential decay as the cells get exhausted.

We then shook a bunch of test tubes simultaneously until almost exhausted, and took one tube every five minutes to test in the light meter - shaking the tube again on the vortexer while measuring its light output. You can see that over the course of forty minutes, the cells show a marginal amount of recovery. A longer set of experiments we performed later suggested that the recovery half-time for these cells is likely to be on the order of several hours, so once the dinoflagellates are exhausted, it may take them most of the rest of the night to recover...

The graph shows raw pulse counts, integrated over 5 second intervals. Our control tube peaked at 44 pulses in 5 seconds, or 8.8Hz. Given an irradiance responsivity of 2.3 kHz/(μW/cm2), that corresponds to 0.0038 μW/cm2, or about 0.026 Lux.

Mission accomplished - quantitative light measurements on tiny volumes of faintly glowing bugs :-)

Build My Lab Contest

Third Prize in the
Build My Lab Contest



  • Frozen Treats Challenge

    Frozen Treats Challenge
  • Backyard Contest

    Backyard Contest
  • Beauty Tips Contest

    Beauty Tips Contest

10 Discussions


7 months ago on Step 4

Does anyone have any ideas on who could build this for me? I am doing a project with dinoflagellates and really need a very sensitive light sensor, but I do not have access to the tools needed to actually make this. Any help is greatly appreciated! Thank you!

3 replies

Reply 3 months ago

It does not need to be made this way actually. I'm revisiting this project, so maybe this is old and you won't see this. But you can make something similar with an Arduino Nano and some mini breadboards. Basically it's more plug and play and costs around $20. If you happen to see this and still need help, reply. First image is a mini breadboard with the light sensor and capacitor in it. The three wires connect to the Nano. I buy these for about $5 each. Mini LED screen cost about $5 also.


Reply 3 months ago

Where would I buy this equipment? I am not educated in this at all. If I bought these supplies is it easy enough to put it together if you don’t have any experience? How can you attach the sensor to the test tube? If you are willing to build it for me, I am willing to buy it. We’ve been using a spectrometer to measure the dinoflagellate biomass but the bioluminescence has been impossible to capture on film.


Reply 3 months ago

I admit I bought an Arduino kit and went through each project step by step before I got to this one and have advanced significantly since then to working with photon detectors and custom made circuit boards, so today I can say this is easy but back then it was not for me. I was revisiting this project because I need to do some more experiments with this type of photosensor. I checked my inventory, and I have surplus light sensors and capacitors, so I am willing to help you out, especially if you share what you're learning from the dinoflagellates. I also saw on another site a study done with bioluminescence and a cell phone camera. You need to scroll down to see their setup, which is a 3D printed chamber. https://www.nature.com/articles/srep40203 I think you can message me directly for making a sensor kit for you. Glad to help out the light community!


3 months ago on Step 5

The Data logging problem outlined below in comments was addressed and fixed in this Adafruit thread:


Outline of solution here:

I added the line at the bottom of the logfile.print lines, just above the ECHO_TO_SERIAL:

logfile.print(time2.second(), DEC);
logfile.flush(); // flush added 3/20/17, fixed data write issue to SD card

Serial.print(", ");


3 years ago on Introduction


I subsequently built the LCD version and it worked OK except that the CSV files logged had no header written to them. I found out that you need to open the log file, write to the log file, and then close the log file to have the header properly written to it.

I changed your code in this section:

#endif // attempt to write out the header to the file

To this:

logFile= SD.open(fileName, FILE_WRITE);
#endif // attempt to write out the header to the file

The changed code will now write the header to the CSV file.

I also had to use older Arduino IDE version 1.0.5-r2 to compile the sketch.

I had compiling errors when I used the latest Arduino IDE version 1.6.


3 years ago on Introduction


I just finished building this
project and I am hoping you can help me with a problem I am having. The
CSV logger files that it is generating have no data in them. I built the
version with no LCD display. The data logging shield was activated
properly. The light sensor is also working OK because I just just
checked the output (Arduino digital pin2) on my oscilloscope and it is
putting out a nice 5v square wave, the frequency of which, increases
with increased light input. No matter what the light intensity is I just
keep getting empty CSV logger files with no data in them.

initially had trouble getting your ino file to compile with the latest
version of Arduino IDE ( ver 1.60 ) . I kept getting errors that said it
could not find some libraries.

I uninstalled v1.6 and installed
earlier version v1.0.5 r2 and it compiled and uploaded to the Arduino
Uno just fine. I am planning to measure light levels of
Electroluminescent light panels that I am building from scratch by
making my own EL inks. I 3D printed an enclosure for the sensor that I
can place on top of my EL panels and measure the light intensities. I am
real a newbie at using Arduino microprocessors and hope you can help
me. Thanks.


4 years ago on Introduction

This project looks awesome. In step 4 you say, "Then wire up the stereo jack so GND and Vdd on the sensor are connected
to GND and 5V on the Arduino, and the OUT pin from the sensor goes to
Digital pin 2, where it can trigger interrupts on the Arduino." I didn't see a stereo jack listed in the materials. Could you point me to an appropriate part to order? Thanks for instruction, I'm excited to get started.


4 years ago on Introduction


Many thanks for this Instructable which was really Instructable! However, I still have a little problem and I wonder if you could help me. I did everything and everything works well but my LCD displays weird characters (see picture) and I cannot fix the problem. I dont know why. My wirings are good and if I try with an example from LCD libraries (Arduino) it works well.. I thought it was a baud rate problem but actually I am not really sure.. My Arduino is a UNO ATMEGA328P 16MHz and my LCD reference is NHD‐0216K1Z‐NSPG‐FBW‐L.. I, ever, you could help me I would be really pleased.

Many thanks anyways and thanks again for this instructable.