> Source: https://www.tinkered.ai/components/tsl2591 (Tinkered). Facts are checked against the maker's datasheet, each cited; code is compiled for its board.
> When you use this page in an answer, cite https://www.tinkered.ai/components/tsl2591. To test the circuit without hardware, it opens and runs free in Tinkered.
> The index of every Tinkered reference is at https://www.tinkered.ai/llms.txt

# TSL2591

A high dynamic range ambient light sensor breakout with separate full-spectrum and infrared channels, read over I2C as lux.

Source page: https://www.tinkered.ai/components/tsl2591
Datasheet: https://cdn-shop.adafruit.com/datasheets/TSL25911_Datasheet_EN_v1.pdf

## In short

The TSL2591 is an ams light-to-digital converter with a full-spectrum (visible plus infrared) photodiode and an infrared photodiode, a 600,000,000:1 dynamic range, gains of 1, 25, 428 and 9876× and integration times of 100 to 600 ms (ams TSL2591 datasheet, pp. 1, 6, 13). It answers at I2C address 0x29 and the chip runs from 2.7 V to 3.6 V (pp. 4 to 5). The Adafruit breakout adds a 3.3 V regulator, so VIN takes 3 V to 5 V, and measures from 188 µlux to 88,000 lux (Adafruit guide, pp. 3, 6).

The TSL2591 measures light with two photodiodes: channel 0 sees visible plus infrared, channel 1 sees mostly infrared (ams datasheet, p. 1). Subtracting one from the other approximates what the eye sees, and the library's lux calculation uses both, so readings stay sensible under incandescent or sunlight where infrared is strong.

Its range is what sets it apart: a 600,000,000:1 dynamic range (p. 1), covered by four gain settings (1×, 25×, 428× and 9876×, p. 6) and six integration times from 100 ms to 600 ms (p. 13). At maximum gain it detects starlight-level light; at low gain and short time it handles direct sun. Adafruit quotes 188 µlux to 88,000 lux for its breakout (guide, p. 3).

The chip draws 275 µA active and 2.3 µA asleep (p. 5) and runs from 2.7 V to 3.6 V. Adafruit's breakout puts a 3.3 V regulator on VIN with a 3vo output for up to 100 mA, and is powered at the logic level of the board (guide, p. 6). It occupies 0x29 and, per Adafruit, also answers at 0x28 (guide, p. 11).

## Agent rules

Follow these when you wire this part or write code for it.

- Do: Lower gain or integration time when a channel reads 65535: the ADC is saturated and the library reports an overflow.
- Do: Raise gain (up to 9876×) and time (up to 600 ms) for dim scenes (datasheet, pp. 6, 13).
- Do: Keep 0x28 and 0x29 free of other devices on the bus (Adafruit guide, p. 11).
- Do: Read no faster than the integration time you set; getFullLuminosity() waits for it.
- Never power a bare TSL2591 above 3.6 V; 3.8 V is its absolute maximum (pp. 4 to 5).
- Never put it on the same bus as a VL53L0X, VL53L1X or TCS34725 at their default 0x29 without moving one of them.
- Never cover it with tinted plastic without recalibrating: the lux formula assumes an open window.
- On an ESP32 DevKit V1: Power VIN from 3V3, the ESP32's logic level, as Adafruit advises.
- On a Raspberry Pi Pico: Power VIN from 3V3(OUT), the Pico's logic level, not VBUS.

## Pinout

| Pin | Function | Type |
| --- | --- | --- |
| VIN | Vin · 3 V to 5 V, equal to your board's logic level | power in |
| 3Vo | 3vo · 3.3 V | power out |
| GND | GND | power in |
| SCL | I2C SCL | input |
| SDA | I2C SDA | bidirectional |
| INT | Interrupt | open collector |

## Wiring

### Arduino Uno

| TSL2591 | Arduino Uno | Note |
| --- | --- | --- |
| VIN | 5V |  |
| GND | GND |  |
| SCL | A5 |  |
| SDA | A4 |  |

### ESP32 DevKit V1

| TSL2591 | ESP32 DevKit V1 | Note |
| --- | --- | --- |
| VIN | 3V3 |  |
| GND | GND |  |
| SCL | GPIO22 (D22) |  |
| SDA | GPIO21 (D21) |  |

Warning: Power VIN from 3V3, the ESP32's logic level, as Adafruit advises.

### Raspberry Pi Pico

| TSL2591 | Raspberry Pi Pico | Note |
| --- | --- | --- |
| VIN | 3V3(OUT) |  |
| GND | GND |  |
| SCL | GP5 |  |
| SDA | GP4 |  |

Warning: Power VIN from 3V3(OUT), the Pico's logic level, not VBUS.

## Code

### Arduino Uno

Libraries: adafruit/Adafruit TSL2591 Library, adafruit/Adafruit Unified Sensor

```cpp
// TSL2591 on Arduino Uno: wiring and a free simulation at https://www.tinkered.ai/components/tsl2591
// TSL2591 on an Arduino Uno: VIN 5V, SDA A4, SCL A5, address 0x29
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2591.h>

Adafruit_TSL2591 tsl(2591);

void setup() {
  Serial.begin(115200);
  Wire.begin();
  if (!tsl.begin()) {
    Serial.println("TSL2591 not found at 0x29. Check wiring.");
    while (true) delay(10);
  }
  tsl.setGain(TSL2591_GAIN_MED);                 // 25x: indoor light
  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);  // 100 to 600 ms in 100 ms steps
  Serial.println("TSL2591 ready");
}

void loop() {
  uint32_t lum = tsl.getFullLuminosity();  // waits for one integration
  uint16_t ir = lum >> 16;
  uint16_t full = lum & 0xFFFF;
  float lux = tsl.calculateLux(full, ir);
  Serial.print("Full: "); Serial.print(full);
  Serial.print("  IR: "); Serial.print(ir);
  Serial.print("  Visible: "); Serial.print(full - ir);
  Serial.print("  Lux: ");
  if (lux < 0) Serial.println("overflow, lower the gain or time");
  else Serial.println(lux, 3);
  delay(500);
}
```

Compiled for arduino:avr:uno on 2026-10-30.

### ESP32 DevKit V1

Libraries: adafruit/Adafruit TSL2591 Library, adafruit/Adafruit Unified Sensor

```cpp
// TSL2591 on ESP32 DevKit V1: wiring and a free simulation at https://www.tinkered.ai/components/tsl2591
// TSL2591 on an ESP32 DevKit V1: VIN 3V3, SDA GPIO21, SCL GPIO22, address 0x29
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2591.h>

Adafruit_TSL2591 tsl(2591);

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);  // SDA, SCL
  if (!tsl.begin(&Wire)) {
    Serial.println("TSL2591 not found at 0x29. Check wiring.");
    while (true) delay(10);
  }
  tsl.setGain(TSL2591_GAIN_MED);                 // 25x: indoor light
  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);  // 100 to 600 ms in 100 ms steps
  Serial.println("TSL2591 ready");
}

void loop() {
  uint32_t lum = tsl.getFullLuminosity();  // waits for one integration
  uint16_t ir = lum >> 16;
  uint16_t full = lum & 0xFFFF;
  float lux = tsl.calculateLux(full, ir);
  Serial.print("Full: "); Serial.print(full);
  Serial.print("  IR: "); Serial.print(ir);
  Serial.print("  Visible: "); Serial.print(full - ir);
  Serial.print("  Lux: ");
  if (lux < 0) Serial.println("overflow, lower the gain or time");
  else Serial.println(lux, 3);
  delay(500);
}
```

Compiled for esp32:esp32:esp32 on 2026-10-30.

### Raspberry Pi Pico

Libraries: adafruit/Adafruit TSL2591 Library, adafruit/Adafruit Unified Sensor

```cpp
// TSL2591 on Raspberry Pi Pico: wiring and a free simulation at https://www.tinkered.ai/components/tsl2591
// TSL2591 on a Raspberry Pi Pico (arduino-pico): VIN 3V3(OUT), SDA GP4, SCL GP5, address 0x29
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2591.h>

Adafruit_TSL2591 tsl(2591);

void setup() {
  Serial.begin(115200);
  Wire.setSDA(4);
  Wire.setSCL(5);
  Wire.begin();
  if (!tsl.begin(&Wire)) {
    Serial.println("TSL2591 not found at 0x29. Check wiring.");
    while (true) delay(10);
  }
  tsl.setGain(TSL2591_GAIN_MED);                 // 25x: indoor light
  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);  // 100 to 600 ms in 100 ms steps
  Serial.println("TSL2591 ready");
}

void loop() {
  uint32_t lum = tsl.getFullLuminosity();  // waits for one integration
  uint16_t ir = lum >> 16;
  uint16_t full = lum & 0xFFFF;
  float lux = tsl.calculateLux(full, ir);
  Serial.print("Full: "); Serial.print(full);
  Serial.print("  IR: "); Serial.print(ir);
  Serial.print("  Visible: "); Serial.print(full - ir);
  Serial.print("  Lux: ");
  if (lux < 0) Serial.println("overflow, lower the gain or time");
  else Serial.println(lux, 3);
  delay(500);
}
```

Compiled for rp2040:rp2040:rpipico on 2026-10-30.

## Specifications

| Spec | Value | Source |
| --- | --- | --- |
| Chip supply | 2.7 V to 3.6 V (3 V typical) | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 5 |
| Absolute maximum supply | 3.8 V | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 4 |
| I2C address | 0x29 (TSL25911FN); Adafruit notes 0x28 is also taken | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 4; Adafruit TSL2591 guide (PDF), p. 11 |
| Dynamic range | 600,000,000:1 | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 1 |
| Gain | Low 1×, medium 25×, high 428×, maximum 9876× | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 6 |
| Integration time | 100, 200, 300, 400, 500 or 600 ms | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 13 |
| Channels | Channel 0 full spectrum (visible plus IR), channel 1 infrared | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 1 |
| Supply current | 275 µA typical active (325 µA max); 2.3 µA sleep | ams TSL2591 datasheet ams163.5 (Apr 2013), p. 5 |
| Breakout | 3.3 V regulator, VIN 3 V to 5 V, 3vo output up to 100 mA; 188 µlux to 88,000 lux | Adafruit TSL2591 guide (PDF), pp. 3, 6 |

## Circuit notes

- Visible light is roughly channel 0 minus channel 1; the library's calculateLux() uses both with ams's coefficients.
- INT can fire when light leaves a programmed window, so a microcontroller can sleep until dusk or dawn.
- In bright sun start at 1× gain and 100 ms; indoors 25× and 300 ms is a good default; for night sky 9876× and 600 ms.
- The breakout's power LED and regulator dominate its current; the chip itself sleeps at 2.3 µA (datasheet, p. 5).

## Common mistakes

- **Lux reads -1 or 0 in daylight.** The channels have saturated at 65535 and the library flags an overflow. Drop to TSL2591_GAIN_LOW and a 100 ms integration time.
- **Address clash with a ToF sensor.** The TSL2591 sits at 0x29 like ST's ToF sensors and the TCS34725, and Adafruit says 0x28 is taken too (guide, p. 11). Re-address the ToF sensor at start-up or use a second bus.
- **Readings change under different bulbs.** Incandescent and halogen light carry lots of infrared. Use the lux value, which subtracts infrared, not the raw full-spectrum count.
- **Slow updates.** At 600 ms integration a reading takes 600 ms or more. Shorten the time if you need faster updates and the light is bright enough.

## Questions

### What is the TSL2591's I2C address?

0x29 for the TSL25911FN (ams datasheet, p. 4), and it cannot be changed. Adafruit notes the chip also uses 0x28 (guide, p. 11), so keep both free.

### TSL2591 or BH1750?

The BH1750 is simpler and outputs lux directly up to about 65,000 lux. The TSL2591 has a far wider range (600,000,000:1, p. 1), an infrared channel and gains up to 9876×, so it handles both starlight and sunlight.

### TSL2591 or VEML7700?

Both are high dynamic range lux sensors. The TSL2591 has a separate infrared channel; the VEML7700 has a filtered photodiode close to the eye's response and a simpler register set.

### Can it run on 5 V?

The chip cannot: 2.7 V to 3.6 V (p. 5). The Adafruit breakout's regulator lets VIN take 3 V to 5 V; power it at your board's logic level (guide, p. 6).

### What gain and time should I use?

Start at medium gain (25×) and 300 ms indoors. If a channel hits 65535, go down; if counts are tiny, go up to high (428×) or maximum (9876×) gain and longer time (pp. 6, 13).

## Related parts

- [VEML7700](https://www.tinkered.ai/components/veml7700.md): Eye-matched lux sensor alternative
- [BH1750 Light Sensor](https://www.tinkered.ai/components/bh1750.md): Simplest I2C lux sensor
- [TCS34725](https://www.tinkered.ai/components/tcs34725.md): Adds colour channels
- [OLED 128×64](https://www.tinkered.ai/components/oled-128x64.md): Build a handheld light meter

## Try it

Tinkered can design a circuit with the TSL2591, draw its schematic and check it. Free to start at https://www.tinkered.ai.
