diff --git a/esphome/components/tsl2591/sensor.py b/esphome/components/tsl2591/sensor.py index 63a0733365..5435ed4b62 100644 --- a/esphome/components/tsl2591/sensor.py +++ b/esphome/components/tsl2591/sensor.py @@ -24,6 +24,7 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import ( CONF_GAIN, + CONF_ACTUAL_GAIN, CONF_ID, CONF_NAME, CONF_INTEGRATION_TIME, @@ -79,7 +80,6 @@ TSL2591Component = tsl2591_ns.class_( "TSL2591Component", cg.PollingComponent, i2c.I2CDevice ) - CONFIG_SCHEMA = ( cv.Schema( { @@ -106,6 +106,12 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_ACTUAL_GAIN): sensor.sensor_schema( + icon=ICON_BRIGHTNESS_6, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), cv.Optional( CONF_INTEGRATION_TIME, default="100ms" ): validate_integration_time, @@ -150,6 +156,11 @@ async def to_code(config): sens = await sensor.new_sensor(conf) cg.add(var.set_calculated_lux_sensor(sens)) + if CONF_ACTUAL_GAIN in config: + conf = config[CONF_ACTUAL_GAIN] + sens = await sensor.new_sensor(conf) + cg.add(var.set_actual_gain_sensor(sens)) + cg.add(var.set_name(config[CONF_NAME])) cg.add(var.set_power_save_mode(config[CONF_POWER_SAVE_MODE])) cg.add(var.set_integration_time(config[CONF_INTEGRATION_TIME])) diff --git a/esphome/components/tsl2591/tsl2591.cpp b/esphome/components/tsl2591/tsl2591.cpp index e3df467aeb..5086a38408 100644 --- a/esphome/components/tsl2591/tsl2591.cpp +++ b/esphome/components/tsl2591/tsl2591.cpp @@ -130,6 +130,7 @@ void TSL2591Component::dump_config() { LOG_SENSOR(" ", "Infrared:", this->infrared_sensor_); LOG_SENSOR(" ", "Visible:", this->visible_sensor_); LOG_SENSOR(" ", "Calculated lux:", this->calculated_lux_sensor_); + LOG_SENSOR(" ", "Actual gain:", this->actual_gain_sensor_); LOG_UPDATE_INTERVAL(this); } @@ -140,8 +141,9 @@ void TSL2591Component::process_update_() { uint16_t infrared = this->get_illuminance(TSL2591_SENSOR_CHANNEL_INFRARED, combined); uint16_t full = this->get_illuminance(TSL2591_SENSOR_CHANNEL_FULL_SPECTRUM, combined); float lux = this->get_calculated_lux(full, infrared); - ESP_LOGD(TAG, "Got illuminance: combined 0x%X, full %d, IR %d, vis %d. Calc lux: %f", combined, full, infrared, - visible, lux); + uint16_t actual_gain = this->get_actual_gain(); + ESP_LOGD(TAG, "Got illuminance: combined 0x%X, full %d, IR %d, vis %d. Calc lux: %f. Actual gain: %d.", combined, + full, infrared, visible, lux, actual_gain); if (this->full_spectrum_sensor_ != nullptr) { this->full_spectrum_sensor_->publish_state(full); } @@ -154,9 +156,14 @@ void TSL2591Component::process_update_() { if (this->calculated_lux_sensor_ != nullptr) { this->calculated_lux_sensor_->publish_state(lux); } + if (this->component_gain_ == TSL2591_CGAIN_AUTO) { this->automatic_gain_update(full); } + + if (this->actual_gain_sensor_ != nullptr) { + this->actual_gain_sensor_->publish_state(actual_gain); + } this->status_clear_warning(); } @@ -207,6 +214,10 @@ void TSL2591Component::set_calculated_lux_sensor(sensor::Sensor *calculated_lux_ this->calculated_lux_sensor_ = calculated_lux_sensor; } +void TSL2591Component::set_actual_gain_sensor(sensor::Sensor *actual_gain_sensor) { + this->actual_gain_sensor_ = actual_gain_sensor; +} + void TSL2591Component::set_integration_time(TSL2591IntegrationTime integration_time) { this->integration_time_ = integration_time; } @@ -377,7 +388,6 @@ float TSL2591Component::get_calculated_lux(uint16_t full_spectrum, uint16_t infr again = 1.0F; break; } - // This lux equation is copied from the Adafruit TSL2591 v1.4.0 and modified slightly. // See: https://github.com/adafruit/Adafruit_TSL2591_Library/issues/14 // and that library code. @@ -448,5 +458,25 @@ void TSL2591Component::automatic_gain_update(uint16_t full_spectrum) { ESP_LOGD(TAG, "Gain setting: %d", this->gain_); } +/** Reads the actual gain used + * + * Useful for exposing the real gain used when configured in "auto" gain mode + */ +float TSL2591Component::get_actual_gain() { + switch (this->gain_) { + case TSL2591_GAIN_LOW: + return 1.0F; + case TSL2591_GAIN_MED: + return 25.0F; + case TSL2591_GAIN_HIGH: + return 400.0F; + case TSL2591_GAIN_MAX: + return 9500.0F; + default: + // Shouldn't get here, but just in case. + return NAN; + } +} + } // namespace tsl2591 } // namespace esphome diff --git a/esphome/components/tsl2591/tsl2591.h b/esphome/components/tsl2591/tsl2591.h index 5b7eea35ec..d7c5230276 100644 --- a/esphome/components/tsl2591/tsl2591.h +++ b/esphome/components/tsl2591/tsl2591.h @@ -217,14 +217,21 @@ class TSL2591Component : public PollingComponent, public i2c::I2CDevice { * * This gets called on update and tries to keep the ADC readings in the middle of the range */ - void automatic_gain_update(uint16_t full_spectrum); + /** Reads the actual gain used + * + * Useful for exposing the real gain used when configured in "auto" gain mode + */ + float get_actual_gain(); + // ========== INTERNAL METHODS ========== // (In most use cases you won't need these. They're for ESPHome integration use.) /** Used by ESPHome framework. */ void set_full_spectrum_sensor(sensor::Sensor *full_spectrum_sensor); /** Used by ESPHome framework. */ + void set_actual_gain_sensor(sensor::Sensor *actual_gain_sensor); + /** Used by ESPHome framework. */ void set_infrared_sensor(sensor::Sensor *infrared_sensor); /** Used by ESPHome framework. */ void set_visible_sensor(sensor::Sensor *visible_sensor); @@ -249,6 +256,7 @@ class TSL2591Component : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *infrared_sensor_{nullptr}; sensor::Sensor *visible_sensor_{nullptr}; sensor::Sensor *calculated_lux_sensor_{nullptr}; + sensor::Sensor *actual_gain_sensor_{nullptr}; TSL2591IntegrationTime integration_time_; TSL2591ComponentGain component_gain_; TSL2591Gain gain_; diff --git a/esphome/const.py b/esphome/const.py index 5662531a5e..6c898ff3ec 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -26,6 +26,7 @@ CONF_ACTION_ID = "action_id" CONF_ACTION_STATE_TOPIC = "action_state_topic" CONF_ACTIVE = "active" CONF_ACTIVE_POWER = "active_power" +CONF_ACTUAL_GAIN = "actual_gain" CONF_ADDRESS = "address" CONF_ADDRESSABLE_LIGHT_ID = "addressable_light_id" CONF_ADVANCED = "advanced"