You can easily wire this breakout to any microcontroller, we'll be using an Arduino. For another kind of microcontroller, just make sure it has I2C, then port the code - its pretty simple stuff!
  • Connect Vin to the power supply, 3-5V is fine. (red wire on STEMMA QT version) Use the same voltage that the microcontroller logic is based off of. For most Arduinos, that is 5V
  • Connect GND to common power/data ground (black wire on STEMMA QT version)
  • Connect the SCL pin to the I2C clock SCL pin on your Arduino. (yellow wire on STEMMA QT version) On an UNO & '328 based Arduino, this is also known as A5, on a Mega it is also known as digital 21 and on a Leonardo/Micro, digital 3
  • Connect the SDA pin to the I2C data SDA pin on your Arduino. (blue wire on STEMMA QT version) On an UNO & '328 based Arduino, this is also known as A4, on a Mega it is also known as digital 20 and on a Leonardo/Micro, digital 2

The TSL2591 has a default I2C address of BOTH  0x29 and 0x28 (which we don't use in code but it definitely is taken) and these cannot be changed!

Install Adafruit_TSL2591 library

To begin reading sensor data, you will need to install the Adafruit_TSL2591 library (code on our github repository). It is available from the Arduino library manager so we recommend using that.

From the IDE open up the library manager...

And type in adafruit tsl2591 to locate the library. Click Install

We also have a great tutorial on Arduino library installation at:

Install Adafruit_Sensor

The TSL2591 library uses the Adafruit_Sensor support backend so that readings can be normalized between sensors.

Search the library manager for Adafruit Unified Sensor and install that too (you may have to scroll a bit)

Load Demo

Open up File->Examples->Adafruit_TSL2591->tsl2591 and upload to your Arduino wired up to the sensor
Thats it! Now open up the serial terminal window at 9600 speed to begin the test.
Try covering with your hand or shining a lamp onto the sensor to experiment with the light levels!

Library Reference

The Adafruit_TSL2591 library contains a number of public functions to help you get started with this sensor.


To create an instance of the Adafruit_TSL2591 driver, simple declare an appropriate object, along with a 32-bit numeric value to identify this sensor (in case you have several TSL2591s and want to track them separately in a logging system).
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);

Gain and Timing

You can adjust the gain settings and integration time of the sensor to make it more or less sensitive to light, depending on the environment where the sensor is being used.

The gain can be set to one of the following values (though the last value, MAX, has limited use in the real world given the extreme amount of gain applied):
  • TSL2591_GAIN_LOW: Sets the gain to 1x (bright light)
  • TSL2591_GAIN_MEDIUM: Sets the gain to 25x (general purpose)
  • TSL2591_GAIN_HIGH: Sets the gain to 428x (low light)
  • TSL2591_GAIN_MAX: Sets the gain to 9876x (extremely low light)
Gain can be read or set via the following functions:
  • void setGain(tsl2591Gain_t gain);
  • tsl2591Gain_t getGain();
The integration time can be set between 100 and 600ms, and the longer the integration time the more light the sensor is able to integrate, making it more sensitive in low light the longer the integration time. The following values can be used:
The integration time can be read or set via the following functions:
  • void setTiming (tsl2591IntegrationTime_t integration);
  • tsl2591IntegrationTime_t getTiming();
An example showing how these functions are used can be seen in the code below:
    Configures the gain and integration time for the TSL2561
void configureSensor(void)
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  //tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
  tsl.setGain(TSL2591_GAIN_MED);      // 25x gain
  //tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
  //tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)

  /* Display the gain and integration time for reference sake */  
  Serial.print  ("Gain:         ");
  tsl2591Gain_t gain = tsl.getGain();
    case TSL2591_GAIN_LOW:
      Serial.println("1x (Low)");
    case TSL2591_GAIN_MED:
      Serial.println("25x (Medium)");
    case TSL2591_GAIN_HIGH:
      Serial.println("428x (High)");
    case TSL2591_GAIN_MAX:
      Serial.println("9876x (Max)");
  Serial.print  ("Timing:       ");
  Serial.print((tsl.getTiming() + 1) * 100, DEC); 
  Serial.println(" ms");

Unified Sensor API

The Adafruit_TSL2591 library makes use of the Adafruit unified sensor framework to provide sensor data in a standardized format and scale. If you wish to make use of this framweork, the two key functions that you need to work with are getEvent and getSensor, as described below:

void getEvent(sensors_event_t*)

This function will read a single sample from the sensor and return it in a generic sensors_event_t object. To use this function, you simply pass in a sensors_event_t reference, which will be populated by the function, and then read the results, as shown in the following code:
    Performs a read using the Adafruit Unified Sensor API.
void unifiedSensorAPIRead(void)
  /* Get a new sensor event */ 
  sensors_event_t event;
  /* Display the results (light is measured in lux) */
  Serial.print("[ "); Serial.print(event.timestamp); Serial.print(" ms ] ");
  if ((event.light == 0) |
      (event.light > 4294966000.0) | 
      (event.light <-4294966000.0))
    /* If event.light = 0 lux the sensor is probably saturated */
    /* and no reliable data could be generated! */
    /* if event.light is +/- 4294967040 there was a float over/underflow */
    Serial.println("Invalid data (adjust gain or timing)");
    Serial.print(event.light); Serial.println(" lux");
Note that some checks need to be performed on the sensor data in case the sensor saturated. If saturation happens, please adjust the gain and integration time up or down to change the sensor's sensitivity and output range.

void getSensor(sensor_t*)

This function returns some basic information about the sensor, and operates in a similar fashion to getEvent. You pass in an empty sensor_t reference, which will be populated by this function, and we can then read the results and retrieve some key details about the sensor and driver, as shown in the code below:
    Displays some basic information on this sensor from the unified
    sensor API sensor_t type (see Adafruit_Sensor for more information)
void displaySensorDetails(void)
  sensor_t sensor;
  Serial.print  ("Sensor:       "); Serial.println(;
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" lux");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" lux");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" lux");  

Raw Data Access API

If you don't wish to use the Unified Sensor API, you can access the raw data for this sensor via the following three functions:
  • uint16_t getLuminosity (uint8_t channel );
  • uint32_t getFullLuminosity ( );
  • uint32_t calculateLux ( uint16_t ch0, uint16_t ch1 );
getLuminosity can be used to read either the visible spectrum light sensor, or the infrared light sensor. It will return the raw 16-bit sensor value for the specified channel, as shown in the code below:
    Shows how to perform a basic read on visible, full spectrum or
    infrared light (returns raw 16-bit ADC values)
void simpleRead(void)
  // Simple data read example. Just read the infrared, fullspecrtrum diode 
  // or 'visible' (difference between the two) channels.
  // This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
  uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);
  //uint16_t x = tsl.getLuminosity(TSL2561_FULLSPECTRUM);
  //uint16_t x = tsl.getLuminosity(TSL2561_INFRARED);

  Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
  Serial.print("Luminosity: ");
  Serial.println(x, DEC);
getFullLuminosity reads both the IR and full spectrum sensors at the same time to allow tigher correlation between the values, and then separates them in SW. The function returns a 32-bit value which needs to be split into two 16-bit values, as shown in the code below:
    Show how to read IR and Full Spectrum at once and convert to lux
void advancedRead(void)
  // More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
  // That way you can do whatever math and comparisons you want!
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum >> 16;
  full = lum & 0xFFFF;
  Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
  Serial.print("IR: "); Serial.print(ir);  Serial.print("  ");
  Serial.print("Full: "); Serial.print(full); Serial.print("  ");
  Serial.print("Visible: "); Serial.print(full - ir); Serial.print("  ");
  Serial.print("Lux: "); Serial.println(tsl.calculateLux(full, ir));
calculateLux can be used to take both the infrared and visible spectrum sensor data and roughly correlate with the equivalent SI lux value, based on a formula from the silicon vendor that takes into account the sensor properties and the integration time and gain settings of the device.

To calculate the lux, simple call calculateLux(full, ir), where 'full' and 'ir' are raw 16-bit values taken from one of the two raw data functions above. See the code sample above for an example of calculating lux.

This guide was first published on Jul 11, 2014. It was last updated on Jun 14, 2024.

This page (Wiring & Test) was last updated on Mar 08, 2024.

Text editor powered by tinymce.