7static const char *
const TAG =
"tsl2591.sensor";
10#define TSL2591_COMMAND_BIT (0xA0)
11#define TSL2591_ENABLE_POWERON (0x01)
12#define TSL2591_ENABLE_POWEROFF (0x00)
13#define TSL2591_ENABLE_AEN (0x02)
16#define TSL2591_REGISTER_ENABLE (0x00)
17#define TSL2591_REGISTER_CONTROL (0x01)
18#define TSL2591_REGISTER_DEVICE_ID (0x12)
19#define TSL2591_REGISTER_STATUS (0x13)
20#define TSL2591_REGISTER_CHAN0_LOW (0x14)
21#define TSL2591_REGISTER_CHAN0_HIGH (0x15)
22#define TSL2591_REGISTER_CHAN1_LOW (0x16)
23#define TSL2591_REGISTER_CHAN1_HIGH (0x17)
27 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWERON | TSL2591_ENABLE_AEN)) {
28 ESP_LOGE(TAG,
"I2C write failed");
33 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWEROFF)) {
34 ESP_LOGE(TAG,
"I2C write failed");
64 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_ID, &
id)) {
65 ESP_LOGE(TAG,
"I2C read failed");
71 ESP_LOGE(TAG,
"Unknown chip ID");
81 ESP_LOGCONFIG(TAG,
"TSL2591:");
85 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
89 ESP_LOGCONFIG(TAG,
" Name: %s", this->
name_);
92 std::string gain_word =
"unknown";
100 gain_word =
"medium";
108 gain_word =
"maximum";
116 int timing_ms = (1 + raw_timing) * 100;
119 " Integration Time: %d ms\n"
120 " Power save mode enabled: %s\n"
121 " Device factor: %f\n"
122 " Glass attenuation factor: %f",
131 LOG_UPDATE_INTERVAL(
this);
141 ESP_LOGD(TAG,
"Got illuminance: combined 0x%" PRIX32
", full %d, IR %d, vis %d. Calc lux: %f. Actual gain: %d.",
142 combined, full, infrared, visible, lux, actual_gain);
166#define interval_name "tsl2591_interval_for_update"
171 ESP_LOGD(TAG,
"Elapsed %3llu ms; still waiting for valid ADC", (now - this->
interval_start_));
173 ESP_LOGW(TAG,
"Interval timeout for '%s' expired before ADCs became valid", this->
name_);
232 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL,
234 ESP_LOGE(TAG,
"I2C write failed");
251 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_STATUS, &
status)) {
252 ESP_LOGE(TAG,
"I2C read failed");
265 const uint8_t mini_delay = 100;
266 for (uint16_t d = 0; d < 620; d += mini_delay) {
272 ESP_LOGD(TAG,
" after %3d ms: ADC valid? %s", d, avalid ?
"true" :
"false");
278 ESP_LOGE(TAG,
"Device '%s' returned invalid readings", this->
name_);
288 uint8_t ch0low, ch0high, ch1low, ch1high;
291 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW, &ch0low)) {
292 ESP_LOGE(TAG,
"I2C read failed");
295 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_HIGH, &ch0high)) {
296 ESP_LOGE(TAG,
"I2C read failed");
299 ch0_16 = (ch0high << 8) | ch0low;
300 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW, &ch1low)) {
301 ESP_LOGE(TAG,
"I2C read failed");
304 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_HIGH, &ch1high)) {
305 ESP_LOGE(TAG,
"I2C read failed");
308 ch1_16 = (ch1high << 8) | ch1low;
309 x32 = (ch1_16 << 16) | ch0_16;
323 return (combined_illuminance & 0xFFFF);
326 return (combined_illuminance >> 16);
329 uint16_t full = combined_illuminance & 0xFFFF;
330 uint16_t ir = combined_illuminance >> 16;
331 return (ir > full) ? 0 : (full - ir);
334 ESP_LOGE(TAG,
"get_illuminance() caller requested an unknown channel: %d", channel);
355 if ((full_spectrum == max_count) || (infrared == max_count)) {
357 ESP_LOGW(TAG,
"Apparent saturation on '%s'; try reducing the gain or integration time", this->
name_);
361 if ((full_spectrum == 0) && (infrared == 0)) {
363 ESP_LOGW(TAG,
"Zero reading on both '%s' sensors", this->
name_);
370 switch (this->
gain_) {
399 float lux = (((float) full_spectrum - (float) infrared)) * (1.0F - ((
float) infrared / (
float) full_spectrum)) / cpl;
400 return std::max(lux, 0.0F);
420 switch (this->
gain_) {
422 if (full_spectrum < 54) {
424 }
else if (full_spectrum < 875) {
429 if (full_spectrum < 57) {
431 }
else if (full_spectrum < 1365) {
433 }
else if (full_spectrum > 62000 / fs_divider) {
438 if (full_spectrum < 920) {
440 }
else if (full_spectrum > 62000 / fs_divider) {
445 if (full_spectrum > 62000 / fs_divider)
450 if (this->
gain_ != new_gain) {
451 this->
gain_ = new_gain;
454 ESP_LOGD(TAG,
"Gain setting: %d", this->
gain_);
462 switch (this->
gain_) {
void mark_failed()
Mark this component as failed.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(const std voi set_interval)(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_interval(const std boo cancel_interval)(const char *name)
Cancel an interval function.
void status_clear_warning()
bool write_byte(uint8_t a_register, uint8_t data) const
bool read_byte(uint8_t a_register, uint8_t *data)
Base-class for all sensors.
void publish_state(float state)
Publish a new state to the front-end.
uint64_t interval_timeout_
TSL2591IntegrationTime integration_time_
void dump_config() override
Used by ESPHome framework.
TSL2591ComponentGain component_gain_
void automatic_gain_update(uint16_t full_spectrum)
Updates the gain setting based on the most recent full spectrum reading.
bool is_adc_valid()
Are the device ADC values valid?
sensor::Sensor * infrared_sensor_
float get_calculated_lux(uint16_t full_spectrum, uint16_t infrared)
Calculates and returns a lux value based on the ADC readings.
sensor::Sensor * calculated_lux_sensor_
void set_visible_sensor(sensor::Sensor *visible_sensor)
Used by ESPHome framework.
void set_device_and_glass_attenuation_factors(float device_factor, float glass_attenuation_factor)
Sets the device and glass attenuation factors.
sensor::Sensor * full_spectrum_sensor_
void set_integration_time(TSL2591IntegrationTime integration_time)
Used by ESPHome framework.
void set_calculated_lux_sensor(sensor::Sensor *calculated_lux_sensor)
Used by ESPHome framework.
uint32_t get_combined_illuminance()
Get the combined illuminance value.
void set_name(const char *name)
Sets the name for this instance of the device.
void interval_function_for_update_()
void disable_if_power_saving_()
float glass_attenuation_factor_
sensor::Sensor * visible_sensor_
void set_infrared_sensor(sensor::Sensor *infrared_sensor)
Used by ESPHome framework.
sensor::Sensor * actual_gain_sensor_
void set_actual_gain_sensor(sensor::Sensor *actual_gain_sensor)
Used by ESPHome framework.
void set_gain(TSL2591ComponentGain gain)
Used by ESPHome framework.
void enable()
Powers on the TSL2591 device and enables its sensors.
void update() override
Used by ESPHome framework.
void set_integration_time_and_gain(TSL2591IntegrationTime integration_time, TSL2591Gain gain)
Set device integration time and gain.
void set_full_spectrum_sensor(sensor::Sensor *full_spectrum_sensor)
Used by ESPHome framework.
void disable()
Powers off the TSL2591 device.
float get_actual_gain()
Reads the actual gain used.
uint16_t get_illuminance(TSL2591SensorChannel channel)
Get an individual sensor channel reading.
bool power_save_mode_enabled_
void setup() override
Used by ESPHome framework.
void set_power_save_mode(bool enable)
Should the device be powered down between readings?
IntegrationTime501 integration_time
TSL2591Gain
Enum listing all gain settings for the TSL2591.
TSL2591ComponentGain
Enum listing all gain settings for the TSL2591 component.
TSL2591IntegrationTime
Enum listing all conversion/integration time settings for the TSL2591.
@ TSL2591_INTEGRATION_TIME_100MS
TSL2591SensorChannel
Enum listing sensor channels.
@ TSL2591_SENSOR_CHANNEL_INFRARED
@ TSL2591_SENSOR_CHANNEL_VISIBLE
@ TSL2591_SENSOR_CHANNEL_FULL_SPECTRUM
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()