Ambient 2 click is a breakout board for the OPT3001 Ambient Light sensor from Texas Instruments, a single-chip lux meter that measures the intensity of light, as seen by the human eye. It has a strong IR rejection and a spectral response that matches the human vision.
This blog post is inspired from a project I had to complete last week, involving some measurements of the ambient light over an extended period. As the project was focused mainly on the changes in light intensity, I came with the idea of building an ambient light data logger. My approach was to use the Ambient2 click, one microSD card click and one (3.3V) Arduino Pro. Something like this:

The hardware was just a matter of minutes to complete. But the software proved to be a big, nasty issue. A major headache came from the OPT3001 sensor: none of the libraries I found on the Internet worked fine…
While testing my data logger, I had two other devices to compare against: one Mastech MS6610 light meter, and my Sekonic flash meter, which is also able to measure light intensity.
The Mastech is more than ten years old, so it’s probably a bit decalibrated. The newer Sekonic is build mainly to measure short pulses of light, and it’s not so precise on measuring ambient light in lux. Anyway, both instruments have provided measurements that are reasonably close to each other (somewhere in a 20% margin). That was expected, as each instrument has a different spectral sensitivity. The angle of incidence of the light was also different for each instrument. Moreover, the Sekonic has two settings for the incidence angle (I used the wide-angle setting).
And then came the surprise: with several code libraries for OPT3001 the measurements were way off. And when I say way off I mean at least one order of magnitude. Even the code example provided by MikroElektronika didn’t provide the expected results – there’s a mistake in the code that messes up the computation of lux values. Other code libraries had even bigger isues – like computing the lux values as uint16_t instead of casting to float.
So, I had to start from zero – and I wrote my own code. But this time I decided to do a little bit more, and I released the code as a library so that anyone can include it easily into their projects.
I can confirm that my library works fine on Arduino Pro (3.3V version) and the ChipKIT Uno32. It doesn’t with the Arduino Due or the Flip & Click, the reason being the flawed I2C library on SAM3X8E microcontrollers.
The download link is https://github.com/Electronza/Ambient2-Click
Using the code library
After downloading and installing the library, one can run the following Arduino IDE code example:
/* MikroeElektronika Ambient2 Click Demo Example * * Created by Teodor Costachioiu, August 2017 * https://electronza.com * */ #include <Wire.h> #include "Ambient2.h" Opt3001 Ambient2; float reading; void setup() { Serial.begin(115200); delay(100); // Start I2C communication Wire.begin(); // Start communication with OPT3001 Serial.println("Initializing..."); Ambient2.begin(); Serial.println("Default sensor setings:"); // Display configuration values Serial.print("CONFIG register is: 0x"); Serial.println(Ambient2.read_Config(),HEX); // Display device ID Serial.print("Device ID is: 0x"); Serial.println(Ambient2.read_DeviceID(),HEX); // Display manufacturer ID Serial.print("Manufacturer ID is: 0x"); Serial.println(Ambient2.read_ManufacturerID(),HEX); // Display HIGH limit Serial.print("HIGH limit is: 0x"); Serial.println(Ambient2.read_HighLimit(),HEX); Serial.print("This means a High limit of "); Serial.print(Ambient2.register2Lux(OPT3001_HIGHLIMIT_REG)); Serial.println (" lux"); // Display LOW limit Serial.print("Low limit is: 0x"); Serial.println(Ambient2.read_LowLimit(),HEX); Serial.print("This means a Low limit of "); Serial.print(Ambient2.register2Lux(OPT3001_LOWLIMIT_REG)); Serial.println (" lux"); Serial.println("------------------------------------"); // Sensor configuration // Set the conversion time to 800ms // This is the default, you can skip it Ambient2.set_time800(); // Set the conversion time to 100ms // Ambient2.set_time100(); // Start the sensor in continuous mode Ambient2.start_continuous(); // Other options are // Perform a single measurement // Ambient2.start_single(); // Shutdown // Ambient2.shutdown(); // Print the new configuration Serial.println("Configuration completed. New settings are:"); // Display configuration values Serial.print("CONFIG register is: 0x"); Serial.println(Ambient2.read_Config(),HEX); // Display device ID Serial.print("Device ID is: 0x"); Serial.println(Ambient2.read_DeviceID(),HEX); // Display manufacturer ID Serial.print("Manufacturer ID is: 0x"); Serial.println(Ambient2.read_ManufacturerID(),HEX); // Display HIGH limit Serial.print("HIGH limit is: 0x"); Serial.println(Ambient2.read_HighLimit(),HEX); // Display LOW limit Serial.print("Low limit is: 0x"); Serial.println(Ambient2.read_LowLimit(),HEX); Serial.println("------------------------------------"); Serial.println(" "); } void loop() { // Wait for measurement while(Ambient2.is_Measuring()){ //Serial.println("Waiting..."); delay(50); } // Do we have overflow? if (Ambient2.is_Overflow()){ Serial.println("Overflow detected"); } else{ // Read the measurement reading = Ambient2.measure_Lux(); Serial.print("Ambient light is: "); Serial.print(reading); Serial.println(" lux"); } }
The OPT3001 code is configured in autoscale mode, which is the simplest way to use this sensor.
Some configurations that can be done by commenting/ uncommenting the appropriate lines:
Measurement time can be either 800ms (default) or 100ms. However, running at 100ms will result in some loss of resolution – how much is lost is explained in the datasheet.
Measurement mode is set to continuous. Other options are a single measurement and shut down.
When a measurement is completed, the CRF flag in the CONFIG register of OPT3001 is set. My code example polls this flag, and when a measurement is completed it first checks if the Overflow bit is set.
If an overflow is detected, an error message is shown. If there’s no overflow, we read the result register, compute lux values and the result is shown in the serial terminal. Simple as that.
Questions, bugs, feature requests? Use the comment field below or the contact form!