mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 15:08:10 +01: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:
parent
0c2f9b9dbb
commit
316a0e1c96
6 changed files with 110 additions and 41 deletions
|
@ -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,24 +108,38 @@ 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();
|
||||||
|
|
||||||
// After the sensor integration time do the following
|
uint32_t int_time{0};
|
||||||
this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME,
|
// Set gain, resolution and measurement rate
|
||||||
[this, mode_index]() {
|
switch (mode) {
|
||||||
// Read from the sensor
|
case LTR390_MODE_ALS:
|
||||||
std::get<1>(this->mode_funcs_[mode_index])();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// If there are more modes to read then begin the next
|
// After the sensor integration time do the following
|
||||||
// otherwise stop
|
this->set_timeout(int_time + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, [this, mode_index]() {
|
||||||
if (mode_index + 1 < (int) this->mode_funcs_.size()) {
|
// Read from the sensor
|
||||||
this->read_mode_(mode_index + 1);
|
std::get<1>(this->mode_funcs_[mode_index])();
|
||||||
} else {
|
|
||||||
// put sensor in standby
|
// If there are more modes to read then begin the next
|
||||||
std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get();
|
// otherwise stop
|
||||||
ctrl[LTR390_CTRL_EN] = false;
|
if (mode_index + 1 < (int) this->mode_funcs_.size()) {
|
||||||
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
this->read_mode_(mode_index + 1);
|
||||||
this->reading_ = false;
|
} else {
|
||||||
}
|
// put sensor in standby
|
||||||
});
|
std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get();
|
||||||
|
ctrl[LTR390_CTRL_EN] = false;
|
||||||
|
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
||||||
|
this->reading_ = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LTR390Component::setup() {
|
void LTR390Component::setup() {
|
||||||
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue