mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	LTR390 separate ALS and UV gain and resolution (#7026)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 Jesse Hills
						Jesse Hills
					
				
			
			
				
	
			
			
			
						parent
						
							0c2f9b9dbb
						
					
				
				
					commit
					316a0e1c96
				
			| @@ -214,7 +214,7 @@ esphome/components/lightwaverf/* @max246 | |||||||
| esphome/components/lilygo_t5_47/touchscreen/* @jesserockz | esphome/components/lilygo_t5_47/touchscreen/* @jesserockz | ||||||
| esphome/components/lock/* @esphome/core | esphome/components/lock/* @esphome/core | ||||||
| esphome/components/logger/* @esphome/core | esphome/components/logger/* @esphome/core | ||||||
| esphome/components/ltr390/* @sjtrny | esphome/components/ltr390/* @latonita @sjtrny | ||||||
| esphome/components/ltr_als_ps/* @latonita | esphome/components/ltr_als_ps/* @latonita | ||||||
| esphome/components/matrix_keypad/* @ssieb | esphome/components/matrix_keypad/* @ssieb | ||||||
| esphome/components/max31865/* @DAVe3283 | esphome/components/max31865/* @DAVe3283 | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ static const uint8_t LTR390_MAIN_STATUS = 0x07; | |||||||
|  |  | ||||||
| static const float GAINVALUES[5] = {1.0, 3.0, 6.0, 9.0, 18.0}; | static const float GAINVALUES[5] = {1.0, 3.0, 6.0, 9.0, 18.0}; | ||||||
| static const float RESOLUTIONVALUE[6] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125}; | static const float RESOLUTIONVALUE[6] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125}; | ||||||
|  | static const uint8_t RESOLUTION_BITS[6] = {20, 19, 18, 17, 16, 13}; | ||||||
|  |  | ||||||
| // Request fastest measurement rate - will be slowed by device if conversion rate is slower. | // Request fastest measurement rate - will be slowed by device if conversion rate is slower. | ||||||
| static const float RESOLUTION_SETTING[6] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50}; | static const float RESOLUTION_SETTING[6] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50}; | ||||||
| @@ -74,7 +75,7 @@ void LTR390Component::read_als_() { | |||||||
|   uint32_t als = *val; |   uint32_t als = *val; | ||||||
|  |  | ||||||
|   if (this->light_sensor_ != nullptr) { |   if (this->light_sensor_ != nullptr) { | ||||||
|     float lux = ((0.6 * als) / (GAINVALUES[this->gain_] * RESOLUTIONVALUE[this->res_])) * this->wfac_; |     float lux = ((0.6 * als) / (GAINVALUES[this->gain_als_] * RESOLUTIONVALUE[this->res_als_])) * this->wfac_; | ||||||
|     this->light_sensor_->publish_state(lux); |     this->light_sensor_->publish_state(lux); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -90,7 +91,7 @@ void LTR390Component::read_uvs_() { | |||||||
|   uint32_t uv = *val; |   uint32_t uv = *val; | ||||||
|  |  | ||||||
|   if (this->uvi_sensor_ != nullptr) { |   if (this->uvi_sensor_ != nullptr) { | ||||||
|     this->uvi_sensor_->publish_state((uv / this->sensitivity_) * this->wfac_); |     this->uvi_sensor_->publish_state((uv / this->sensitivity_uv_) * this->wfac_); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (this->uv_sensor_ != nullptr) { |   if (this->uv_sensor_ != nullptr) { | ||||||
| @@ -107,9 +108,23 @@ void LTR390Component::read_mode_(int mode_index) { | |||||||
|   ctrl[LTR390_CTRL_EN] = true; |   ctrl[LTR390_CTRL_EN] = true; | ||||||
|   this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); |   this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); | ||||||
|  |  | ||||||
|  |   uint32_t int_time{0}; | ||||||
|  |   // Set gain, resolution and measurement rate | ||||||
|  |   switch (mode) { | ||||||
|  |     case LTR390_MODE_ALS: | ||||||
|  |       this->reg(LTR390_GAIN) = this->gain_als_; | ||||||
|  |       this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_als_]; | ||||||
|  |       int_time = ((uint32_t) RESOLUTIONVALUE[this->res_als_]) * 100; | ||||||
|  |       break; | ||||||
|  |     case LTR390_MODE_UVS: | ||||||
|  |       this->reg(LTR390_GAIN) = this->gain_uv_; | ||||||
|  |       this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_uv_]; | ||||||
|  |       int_time = ((uint32_t) RESOLUTIONVALUE[this->res_uv_]) * 100; | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // After the sensor integration time do the following |   // After the sensor integration time do the following | ||||||
|   this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, |   this->set_timeout(int_time + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, [this, mode_index]() { | ||||||
|                     [this, mode_index]() { |  | ||||||
|     // Read from the sensor |     // Read from the sensor | ||||||
|     std::get<1>(this->mode_funcs_[mode_index])(); |     std::get<1>(this->mode_funcs_[mode_index])(); | ||||||
|  |  | ||||||
| @@ -151,16 +166,10 @@ void LTR390Component::setup() { | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Set gain |  | ||||||
|   this->reg(LTR390_GAIN) = gain_; |  | ||||||
|  |  | ||||||
|   // Set resolution and measurement rate |  | ||||||
|   this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_]; |  | ||||||
|  |  | ||||||
|   // Set sensitivity by linearly scaling against known value in the datasheet |   // Set sensitivity by linearly scaling against known value in the datasheet | ||||||
|   float gain_scale = GAINVALUES[this->gain_] / GAIN_MAX; |   float gain_scale_uv = GAINVALUES[this->gain_uv_] / GAIN_MAX; | ||||||
|   float intg_scale = (RESOLUTIONVALUE[this->res_] * 100) / INTG_MAX; |   float intg_scale_uv = (RESOLUTIONVALUE[this->res_uv_] * 100) / INTG_MAX; | ||||||
|   this->sensitivity_ = SENSITIVITY_MAX * gain_scale * intg_scale; |   this->sensitivity_uv_ = SENSITIVITY_MAX * gain_scale_uv * intg_scale_uv; | ||||||
|  |  | ||||||
|   // Set sensor read state |   // Set sensor read state | ||||||
|   this->reading_ = false; |   this->reading_ = false; | ||||||
| @@ -176,7 +185,13 @@ void LTR390Component::setup() { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void LTR390Component::dump_config() { LOG_I2C_DEVICE(this); } | void LTR390Component::dump_config() { | ||||||
|  |   LOG_I2C_DEVICE(this); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  ALS Gain: X%.0f", GAINVALUES[this->gain_als_]); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  ALS Resolution: %u-bit", RESOLUTION_BITS[this->res_als_]); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  UV Gain: X%.0f", GAINVALUES[this->gain_uv_]); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  UV Resolution: %u-bit", RESOLUTION_BITS[this->res_uv_]); | ||||||
|  | } | ||||||
|  |  | ||||||
| void LTR390Component::update() { | void LTR390Component::update() { | ||||||
|   if (!this->reading_ && !mode_funcs_.empty()) { |   if (!this->reading_ && !mode_funcs_.empty()) { | ||||||
|   | |||||||
| @@ -49,8 +49,10 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { | |||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   void update() override; |   void update() override; | ||||||
|  |  | ||||||
|   void set_gain_value(LTR390GAIN gain) { this->gain_ = gain; } |   void set_als_gain_value(LTR390GAIN gain) { this->gain_als_ = gain; } | ||||||
|   void set_res_value(LTR390RESOLUTION res) { this->res_ = res; } |   void set_uv_gain_value(LTR390GAIN gain) { this->gain_uv_ = gain; } | ||||||
|  |   void set_als_res_value(LTR390RESOLUTION res) { this->res_als_ = res; } | ||||||
|  |   void set_uv_res_value(LTR390RESOLUTION res) { this->res_uv_ = res; } | ||||||
|   void set_wfac_value(float wfac) { this->wfac_ = wfac; } |   void set_wfac_value(float wfac) { this->wfac_ = wfac; } | ||||||
|  |  | ||||||
|   void set_light_sensor(sensor::Sensor *light_sensor) { this->light_sensor_ = light_sensor; } |   void set_light_sensor(sensor::Sensor *light_sensor) { this->light_sensor_ = light_sensor; } | ||||||
| @@ -71,9 +73,11 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { | |||||||
|   // a list of modes and corresponding read functions |   // a list of modes and corresponding read functions | ||||||
|   std::vector<std::tuple<LTR390MODE, std::function<void()>>> mode_funcs_; |   std::vector<std::tuple<LTR390MODE, std::function<void()>>> mode_funcs_; | ||||||
|  |  | ||||||
|   LTR390GAIN gain_; |   LTR390GAIN gain_als_; | ||||||
|   LTR390RESOLUTION res_; |   LTR390GAIN gain_uv_; | ||||||
|   float sensitivity_; |   LTR390RESOLUTION res_als_; | ||||||
|  |   LTR390RESOLUTION res_uv_; | ||||||
|  |   float sensitivity_uv_; | ||||||
|   float wfac_; |   float wfac_; | ||||||
|  |  | ||||||
|   sensor::Sensor *light_sensor_{nullptr}; |   sensor::Sensor *light_sensor_{nullptr}; | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ from esphome.const import ( | |||||||
|     UNIT_LUX, |     UNIT_LUX, | ||||||
| ) | ) | ||||||
|  |  | ||||||
| CODEOWNERS = ["@sjtrny"] | CODEOWNERS = ["@sjtrny", "@latonita"] | ||||||
| DEPENDENCIES = ["i2c"] | DEPENDENCIES = ["i2c"] | ||||||
|  |  | ||||||
| ltr390_ns = cg.esphome_ns.namespace("ltr390") | ltr390_ns = cg.esphome_ns.namespace("ltr390") | ||||||
| @@ -76,8 +76,24 @@ CONFIG_SCHEMA = cv.All( | |||||||
|                 accuracy_decimals=1, |                 accuracy_decimals=1, | ||||||
|                 device_class=DEVICE_CLASS_EMPTY, |                 device_class=DEVICE_CLASS_EMPTY, | ||||||
|             ), |             ), | ||||||
|             cv.Optional(CONF_GAIN, default="X18"): cv.enum(GAIN_OPTIONS), |             cv.Optional(CONF_GAIN, default="X18"): cv.Any( | ||||||
|             cv.Optional(CONF_RESOLUTION, default=20): cv.enum(RES_OPTIONS), |                 cv.enum(GAIN_OPTIONS), | ||||||
|  |                 cv.Schema( | ||||||
|  |                     { | ||||||
|  |                         cv.Required(CONF_AMBIENT_LIGHT): cv.enum(GAIN_OPTIONS), | ||||||
|  |                         cv.Required(CONF_UV): cv.enum(GAIN_OPTIONS), | ||||||
|  |                     } | ||||||
|  |                 ), | ||||||
|  |             ), | ||||||
|  |             cv.Optional(CONF_RESOLUTION, default=20): cv.Any( | ||||||
|  |                 cv.enum(RES_OPTIONS), | ||||||
|  |                 cv.Schema( | ||||||
|  |                     { | ||||||
|  |                         cv.Required(CONF_AMBIENT_LIGHT): cv.enum(RES_OPTIONS), | ||||||
|  |                         cv.Required(CONF_UV): cv.enum(RES_OPTIONS), | ||||||
|  |                     } | ||||||
|  |                 ), | ||||||
|  |             ), | ||||||
|             cv.Optional(CONF_WINDOW_CORRECTION_FACTOR, default=1.0): cv.float_range( |             cv.Optional(CONF_WINDOW_CORRECTION_FACTOR, default=1.0): cv.float_range( | ||||||
|                 min=1.0 |                 min=1.0 | ||||||
|             ), |             ), | ||||||
| @@ -101,11 +117,25 @@ async def to_code(config): | |||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|     await i2c.register_i2c_device(var, config) |     await i2c.register_i2c_device(var, config) | ||||||
|  |  | ||||||
|     cg.add(var.set_gain_value(config[CONF_GAIN])) |  | ||||||
|     cg.add(var.set_res_value(config[CONF_RESOLUTION])) |  | ||||||
|     cg.add(var.set_wfac_value(config[CONF_WINDOW_CORRECTION_FACTOR])) |     cg.add(var.set_wfac_value(config[CONF_WINDOW_CORRECTION_FACTOR])) | ||||||
|  |  | ||||||
|     for key, funcName in TYPES.items(): |     for key, funcName in TYPES.items(): | ||||||
|         if key in config: |         if key in config: | ||||||
|             sens = await sensor.new_sensor(config[key]) |             sens = await sensor.new_sensor(config[key]) | ||||||
|             cg.add(getattr(var, funcName)(sens)) |             cg.add(getattr(var, funcName)(sens)) | ||||||
|  |  | ||||||
|  |     gain_value = config[CONF_GAIN] | ||||||
|  |     if isinstance(gain_value, dict): | ||||||
|  |         cg.add(var.set_als_gain_value(gain_value[CONF_AMBIENT_LIGHT])) | ||||||
|  |         cg.add(var.set_uv_gain_value(gain_value[CONF_UV])) | ||||||
|  |     else: | ||||||
|  |         cg.add(var.set_als_gain_value(gain_value)) | ||||||
|  |         cg.add(var.set_uv_gain_value(gain_value)) | ||||||
|  |  | ||||||
|  |     res_value = config[CONF_RESOLUTION] | ||||||
|  |     if isinstance(res_value, dict): | ||||||
|  |         cg.add(var.set_als_res_value(res_value[CONF_AMBIENT_LIGHT])) | ||||||
|  |         cg.add(var.set_uv_res_value(res_value[CONF_UV])) | ||||||
|  |     else: | ||||||
|  |         cg.add(var.set_als_res_value(res_value)) | ||||||
|  |         cg.add(var.set_uv_res_value(res_value)) | ||||||
|   | |||||||
| @@ -18,3 +18,21 @@ sensor: | |||||||
|     window_correction_factor: 1.0 |     window_correction_factor: 1.0 | ||||||
|     address: 0x53 |     address: 0x53 | ||||||
|     update_interval: 60s |     update_interval: 60s | ||||||
|  |   - platform: ltr390 | ||||||
|  |     uv: | ||||||
|  |       name: LTR390 UV | ||||||
|  |     uv_index: | ||||||
|  |       name: LTR390 UVI | ||||||
|  |     light: | ||||||
|  |       name: LTR390 Light | ||||||
|  |     ambient_light: | ||||||
|  |       name: LTR390 ALS | ||||||
|  |     gain: | ||||||
|  |       ambient_light: X9 | ||||||
|  |       uv: X3 | ||||||
|  |     resolution: | ||||||
|  |       ambient_light: 18 | ||||||
|  |       uv: 13 | ||||||
|  |     window_correction_factor: 1.0 | ||||||
|  |     address: 0x53 | ||||||
|  |     update_interval: 60s | ||||||
|   | |||||||
| @@ -13,7 +13,9 @@ sensor: | |||||||
|       name: LTR390 Light |       name: LTR390 Light | ||||||
|     ambient_light: |     ambient_light: | ||||||
|       name: LTR390 ALS |       name: LTR390 ALS | ||||||
|     gain: X3 |     gain: | ||||||
|  |       ambient_light: X9 | ||||||
|  |       uv: X3 | ||||||
|     resolution: 18 |     resolution: 18 | ||||||
|     window_correction_factor: 1.0 |     window_correction_factor: 1.0 | ||||||
|     address: 0x53 |     address: 0x53 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user