VEML7700 ambient light sensor

The Vishay VEML7700 light sensor on its I2C breakout: lux as a 16-bit count at 0x10, with gain, integration time and a threshold flag.

Aliases: VEML7700, VEML 7700, Adafruit 4162, lux sensor, ambient light sensor.

Drag the slider above the board to set the light, 0 to 120000 lux. Adafruit_VEML7700.h reads it:

#include "Adafruit_VEML7700.h"

Adafruit_VEML7700 veml = Adafruit_VEML7700();

void setup() {
  Serial.begin(115200);
  if (!veml.begin()) { Serial.println("Sensor not found"); while (1); }
}

void loop() {
  Serial.println(veml.readLux(VEML_LUX_AUTO));
  delay(500);
}

Pins

Pin What it does
VIN Supply, 3 to 5 V: the board has a 3.3 V regulator.
GND Ground.
SCL, SDA I2C, with 10k pull-ups on the board. The address is fixed at 0x10.

The chip has no interrupt pin: the threshold flags are read over I2C.

Properties

Property Default What it is
lux 300 The light on the sensor, 0 to 120000 lux. The slider sets it while it runs.

What the model gets right

The registers. Sixteen bits each, sent low byte first: ALS_CONF (0x00) with the gain (x1, x2, x1/8, x1/4), the integration time (25 to 800 ms), the persistence, the interrupt enable and the shutdown bit; the high and low thresholds (0x01, 0x02); power saving (0x03); the ALS count (0x04); the white count (0x05); the interrupt flags (0x06, cleared by the read); and the ID, 0xC481 (0x07). The sensor comes up shut down and every library turns it on.

The timing. Once on, a new count lands every integration time, plus 500 to 4000 ms when power saving is on. Changing ALS_CONF starts the integration again.

The counts. The resolution is 0.0042 lux a count at gain x2 and 800 ms, from the current datasheet's table (an older revision said 0.0036), and doubles for each halving of gain or integration time, so 0.5376 lux a count at the library's x1/8 and 100 ms. The count saturates at 65535.

The high-light curve. The real sensor reads low as the light rises, and Vishay's application note gives the polynomial that drivers apply to undo it. The model follows that curve, so readLux(VEML_LUX_CORRECTED) and VEML_LUX_AUTO (in its bright branch) give the slider back, and a plain readLux() reads low by the curve: about 2.6 % at 300 lux, 7 % at 1000 lux, more above.

The threshold flags. With the interrupt enabled, a count above ALS_WH or below ALS_WL for the persistence count in a row sets its flag.

What it does not model

The spectrum: the slider is the light in lux, and the white channel reads the same count as the ALS channel, where on the real part their ratio depends on the light source. Noise, the dark count, temperature drift and the 2.5 ms start-up are not modeled either.

Common mistakes

Reading too soon after changing the gain or integration time: the count is the old one until a new integration ends. The library's waiting reads (the default) handle it.

Expecting readLux() to match a lux meter in bright light: use VEML_LUX_AUTO or VEML_LUX_CORRECTED above a few hundred lux, as on the bench.