8static const char *
const TAG =
"tsl2591.sensor";
11#define TSL2591_COMMAND_BIT (0xA0)
12#define TSL2591_ENABLE_POWERON (0x01)
13#define TSL2591_ENABLE_POWEROFF (0x00)
14#define TSL2591_ENABLE_AEN (0x02)
17#define TSL2591_REGISTER_ENABLE (0x00)
18#define TSL2591_REGISTER_CONTROL (0x01)
19#define TSL2591_REGISTER_DEVICE_ID (0x12)
20#define TSL2591_REGISTER_STATUS (0x13)
21#define TSL2591_REGISTER_CHAN0_LOW (0x14)
22#define TSL2591_REGISTER_CHAN0_HIGH (0x15)
23#define TSL2591_REGISTER_CHAN1_LOW (0x16)
24#define TSL2591_REGISTER_CHAN1_HIGH (0x17)
28 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWERON | TSL2591_ENABLE_AEN)) {
29 ESP_LOGE(TAG,
"I2C write failed");
34 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWEROFF)) {
35 ESP_LOGE(TAG,
"I2C write failed");
65 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_ID, &
id)) {
66 ESP_LOGE(TAG,
"I2C read failed");
72 ESP_LOGE(TAG,
"Unknown chip ID");
82 ESP_LOGCONFIG(TAG,
"TSL2591:");
86 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
90 ESP_LOGCONFIG(TAG,
" Name: %s", this->
name_);
93 std::string gain_word =
"unknown";
101 gain_word =
"medium";
109 gain_word =
"maximum";
117 int timing_ms = (1 + raw_timing) * 100;
120 " Integration Time: %d ms\n"
121 " Power save mode enabled: %s\n"
122 " Device factor: %f\n"
123 " Glass attenuation factor: %f",
132 LOG_UPDATE_INTERVAL(
this);
142 ESP_LOGD(TAG,
"Got illuminance: combined 0x%" PRIX32
", full %d, IR %d, vis %d. Calc lux: %f. Actual gain: %d.",
143 combined, full, infrared, visible, lux, actual_gain);
167#define interval_name "tsl2591_interval_for_update"
172 ESP_LOGD(TAG,
"Elapsed %3llu ms; still waiting for valid ADC", (now - this->
interval_start_));
174 ESP_LOGW(TAG,
"Interval timeout for '%s' expired before ADCs became valid", this->
name_);
233 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL,
235 ESP_LOGE(TAG,
"I2C write failed");
252 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_STATUS, &
status)) {
253 ESP_LOGE(TAG,
"I2C read failed");
266 const uint8_t mini_delay = 100;
267 for (uint16_t d = 0; d < 620; d += mini_delay) {
273 ESP_LOGD(TAG,
" after %3d ms: ADC valid? %s", d, avalid ?
"true" :
"false");
279 ESP_LOGE(TAG,
"Device '%s' returned invalid readings", this->
name_);
289 uint8_t ch0low, ch0high, ch1low, ch1high;
292 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW, &ch0low)) {
293 ESP_LOGE(TAG,
"I2C read failed");
296 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_HIGH, &ch0high)) {
297 ESP_LOGE(TAG,
"I2C read failed");
300 ch0_16 = (ch0high << 8) | ch0low;
301 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW, &ch1low)) {
302 ESP_LOGE(TAG,
"I2C read failed");
305 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_HIGH, &ch1high)) {
306 ESP_LOGE(TAG,
"I2C read failed");
309 ch1_16 = (ch1high << 8) | ch1low;
310 x32 = (ch1_16 << 16) | ch0_16;
324 return (combined_illuminance & 0xFFFF);
327 return (combined_illuminance >> 16);
330 return ((combined_illuminance & 0xFFFF) - (combined_illuminance >> 16));
333 ESP_LOGE(TAG,
"get_illuminance() caller requested an unknown channel: %d", channel);
354 if ((full_spectrum == max_count) || (infrared == max_count)) {
356 ESP_LOGW(TAG,
"Apparent saturation on '%s'; try reducing the gain or integration time", this->
name_);
360 if ((full_spectrum == 0) && (infrared == 0)) {
362 ESP_LOGW(TAG,
"Zero reading on both '%s' sensors", this->
name_);
369 switch (this->
gain_) {
398 float lux = (((float) full_spectrum - (float) infrared)) * (1.0F - ((
float) infrared / (
float) full_spectrum)) / cpl;
399 return std::max(lux, 0.0F);
419 switch (this->
gain_) {
421 if (full_spectrum < 54) {
423 }
else if (full_spectrum < 875) {
428 if (full_spectrum < 57) {
430 }
else if (full_spectrum < 1365) {
432 }
else if (full_spectrum > 62000 / fs_divider) {
437 if (full_spectrum < 920) {
439 }
else if (full_spectrum > 62000 / fs_divider) {
444 if (full_spectrum > 62000 / fs_divider)
449 if (this->
gain_ != new_gain) {
450 this->
gain_ = new_gain;
453 ESP_LOGD(TAG,
"Gain setting: %d", this->
gain_);
461 switch (this->
gain_) {
virtual 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
Providing packet encoding functions for exchanging data with a remote host.
void IRAM_ATTR HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()