OPT3001 Digital Ambient Light Sensor and ESP8266 example

In this example we will connect an OPT3001 to a Wemos, this sensor measures light intensity – so you can easily create a lux meter

You can read about lux at https://en.wikipedia.org/wiki/Lux

The OPT3001 is a sensor that measures the intensity of visible light. The spectral response of the sensor tightly matches the photopic response of the human eye and includes significant infrared rejection.

The OPT3001 is a single-chip lux meter, measuring the intensity of light as visible by the human eye. The precision spectral response and strong IR rejection of the device enables the OPT3001 to accurately meter the intensity of light as seen by the human eye regardless of light source. The strong IR rejection also aids in maintaining high accuracy when industrial design calls for mounting the sensor under dark glass for aesthetics. The OPT3001 is designed for systems that create light-based experiences for humans, and an ideal preferred replacement for photodiodes, photoresistors, or other ambient light sensors with less human eye matching and IR rejection.

Measurements can be made from 0.01 lux up to 83k lux without manually selecting full-scale ranges by using the built-in, full-scale setting feature. This capability allows light measurement over a 23-bit effective dynamic range.

The digital operation is flexible for system integration. Measurements can be either continuous or single-shot. The control and interrupt system features autonomous operation, allowing the processor to sleep while the sensor searches for appropriate wake-up events to report via the interrupt pin. The digital output is reported over an I2C- and SMBus-compatible, two-wire serial interface.



  • Precision Optical Filtering to Match Human Eye:
    • Rejects > 99% (typ) of IR
  • Automatic Full-Scale Setting Feature Simplifies Software and Ensures Proper Configuration
  • Measurements: 0.01 lux to 83 k lux
  • 23-Bit Effective Dynamic Range With
    Automatic Gain Ranging
  • 12 Binary-Weighted Full-Scale Range Settings:
    < 0.2% (typ) Matching Between Ranges
  • Low Operating Current: 1.8 µA (typ)
  • Operating Temperature Range: –40°C to +85°C
  • Wide Power-Supply Range: 1.6 V to 3.6 V
  • 5.5-V Tolerant I/O




Wemos MIni  CJMCU-3001
3v3 Vcc
Gnd Gnd


This example uses the following library https://github.com/closedcube/ClosedCube_OPT3001_Arduino

[codesyntax lang=”cpp”]

#include <Wire.h>
#include <ClosedCube_OPT3001.h>

ClosedCube_OPT3001 opt3001;

#define OPT3001_ADDRESS 0x44

void setup()
	Serial.println("ClosedCube OPT3001 Arduino Test");

	Serial.print("OPT3001 Manufacturer ID");
	Serial.print("OPT3001 Device ID");

	printResult("High-Limit", opt3001.readHighLimit());
	printResult("Low-Limit", opt3001.readLowLimit());

void loop()
	OPT3001 result = opt3001.readResult();
	printResult("OPT3001", result);

void configureSensor() {
	OPT3001_Config newConfig;
	newConfig.RangeNumber = B1100;	
	newConfig.ConvertionTime = B0;
	newConfig.Latch = B1;
	newConfig.ModeOfConversionOperation = B11;

	OPT3001_ErrorCode errorConfig = opt3001.writeConfig(newConfig);
	if (errorConfig != NO_ERROR)
		printError("OPT3001 configuration", errorConfig);
	else {
		OPT3001_Config sensorConfig = opt3001.readConfig();
		Serial.println("OPT3001 Current Config:");
		Serial.print("Conversion ready (R):");

		Serial.print("Conversion time (R/W):");
		Serial.println(sensorConfig.ConvertionTime, HEX);

		Serial.print("Fault count field (R/W):");
		Serial.println(sensorConfig.FaultCount, HEX);

		Serial.print("Flag high field (R-only):");
		Serial.println(sensorConfig.FlagHigh, HEX);

		Serial.print("Flag low field (R-only):");
		Serial.println(sensorConfig.FlagLow, HEX);

		Serial.print("Latch field (R/W):");
		Serial.println(sensorConfig.Latch, HEX);

		Serial.print("Mask exponent field (R/W):");
		Serial.println(sensorConfig.MaskExponent, HEX);

		Serial.print("Mode of conversion operation (R/W):");
		Serial.println(sensorConfig.ModeOfConversionOperation, HEX);

		Serial.print("Polarity field (R/W):");
		Serial.println(sensorConfig.Polarity, HEX);

		Serial.print("Overflow flag (R-only):");
		Serial.println(sensorConfig.OverflowFlag, HEX);

		Serial.print("Range number (R/W):");
		Serial.println(sensorConfig.RangeNumber, HEX);


void printResult(String text, OPT3001 result) {
	if (result.error == NO_ERROR) {
		Serial.print(": ");
		Serial.println(" lux");
	else {

void printError(String text, OPT3001_ErrorCode error) {
	Serial.print(": [ERROR] Code #");




Open the serial monitor and you should see something like this

OPT3001: 7.09 lux
OPT3001: 13.30 lux
OPT3001: 21.46 lux
OPT3001: 77.02 lux
OPT3001: 186.72 lux
OPT3001: 322.96 lux
OPT3001: 371.68 lux
OPT3001: 129.60 lux
OPT3001: 9.83 lux
OPT3001: 12.87 lux
OPT3001: 6.92 lux
OPT3001: 4.42 lux

From wikipedia

Illuminance (lux) Surfaces illuminated by
0.0001 Moonless, overcast night sky (starlight)
0.002 Moonless clear night sky with airglow
0.05–0.3 Full moon on a clear night[4]
3.4 Dark limit of civil twilight under a clear sky
20–50 Public areas with dark surroundings
50 Family living room lights
80 Office building hallway/toilet lighting
100 Very dark overcast day
150 Train station platforms
320–500 Office lighting
400 Sunrise or sunset on a clear day.
1000 Overcast day; typical TV studio lighting
10,000–25,000 Full daylight (not direct sun)[3]
32,000–100,000 Direct sunlight



OPT3001 CJMCU-3001 ambient light sensor eye like measurement light intensity single chip illumination meter


Please enter your comment!
Please enter your name here