DEV Community

Hedy
Hedy

Posted on

How to Drive TSL2591 Light Sensor with STM32?

To interface the TSL2591 high-precision light sensor with an STM32 microcontroller, you can use the I2C interface provided by the sensor. Here's a detailed guide covering hardware setup, initialization, reading data, and calculating lux values.

1. Overview

  • TSL2591: Digital light sensor with high dynamic range (~188µLux to 88,000 Lux).
  • Interface: I2C
  • Key registers: COMMAND, ENABLE, CONTROL, and data registers for channels.

2. Hardware Connection

Pull-up resistors (~4.7kΩ) recommended on SDA/SCL lines.

3. I2C Initialization (STM32CubeMX)

  • Enable I2C1 (or any available)
  • Configure SDA/SCL pins
  • Generate code using HAL drivers

4. I2C Address and Registers
I2C Address: 0x29 << 1 = 0x52 (for HAL)

Command Bit: OR 0xA0 to register address when reading/writing

Key Registers:

  • 0x00: ENABLE
  • 0x01: CONTROL
  • 0x14~0x19: ADC data registers (2 channels, 16-bit each)

5. Basic Initialization Sequence
a) Enable Sensor

c

// Enable ALS (Ambient Light Sensing)
HAL_I2C_Mem_Write(&hi2c1, 0x52, 0xA0 | 0x00, 1, (uint8_t[]){0x03}, 1, HAL_MAX_DELAY); // Power ON + ALS Enable
Enter fullscreen mode Exit fullscreen mode

b) Set Integration Time and Gain

c

// Set CONTROL register: Gain = Medium, Integration = 100ms
// Gain = 01 (Medium), Integration = 100ms (0x01)
// CONTROL = 0x10 | 0x01 = 0x11
HAL_I2C_Mem_Write(&hi2c1, 0x52, 0xA0 | 0x01, 1, (uint8_t[]){0x11}, 1, HAL_MAX_DELAY);
Enter fullscreen mode Exit fullscreen mode

6. Reading Data

c

uint8_t buffer[2];
uint16_t ch0, ch1;

// Read CH0 (Full Spectrum)
HAL_I2C_Mem_Read(&hi2c1, 0x52, 0xA0 | 0x14, 1, buffer, 2, HAL_MAX_DELAY);
ch0 = buffer[0] | (buffer[1] << 8);

// Read CH1 (Infrared)
HAL_I2C_Mem_Read(&hi2c1, 0x52, 0xA0 | 0x16, 1, buffer, 2, HAL_MAX_DELAY);
ch1 = buffer[0] | (buffer[1] << 8);
Enter fullscreen mode Exit fullscreen mode

7. Lux Calculation (Simplified)
Use Adafruit’s algorithm for TSL2591:

c

float lux;
if (ch0 == 0xFFFF || ch1 == 0xFFFF) {
    lux = -1; // sensor saturated
} else {
    float atime = 100.0f; // integration time in ms
    float again = 25.0f;  // medium gain
    float cpl = (atime * again) / 408.0f;

    lux = ((float)ch0 - (float)ch1) * (1.0f - ((float)ch1 / (float)ch0)) / cpl;
}
Enter fullscreen mode Exit fullscreen mode

This is a simplified version. For accurate lux calculation, consider full spectral response compensation.

8. Best Practices

  • Wait after enabling sensor (integration time + margin) before reading data.
  • Check for saturation (0xFFFF).
  • Use HAL_Delay() or non-blocking timing to ensure measurement is ready.
  • Power down sensor when idle to save energy.

Optional: Create Driver
You can encapsulate the initialization and reading functions in a TSL2591 driver (tsl2591.h/.c).

Top comments (0)