mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 09:18:00 +01:00
tcs34725: implement irradiance output per color channel
- Extracted responsivty curves for red, green, blue and clear channel from the specs - Simulated three lights, specified in the spec sheet, emitting light onto clear responsivity curve, to get a median conversion factor for responsivity (in the graph) to counts/irradiance. - Determine red, green, blue, clear channel range by FWHM - Get the average responsivity for red, green, blue channels from the spec sheet curves and convert the units by the conversion factor determined ealier to counts/irradiance. - Use channel range by FWHM to scale the responses accordingly - Implement conversion from counts by the sensor to irradiance
This commit is contained in:
parent
03cf2452e1
commit
21dd69719a
10 changed files with 192 additions and 95 deletions
|
@ -16,6 +16,7 @@ from esphome.const import (
|
||||||
ICON_THERMOMETER,
|
ICON_THERMOMETER,
|
||||||
UNIT_KELVIN,
|
UNIT_KELVIN,
|
||||||
UNIT_LUX,
|
UNIT_LUX,
|
||||||
|
UNIT_IRRADIANCE,
|
||||||
)
|
)
|
||||||
|
|
||||||
DEPENDENCIES = ["i2c"]
|
DEPENDENCIES = ["i2c"]
|
||||||
|
@ -24,6 +25,9 @@ CONF_RED_CHANNEL = "red_channel"
|
||||||
CONF_GREEN_CHANNEL = "green_channel"
|
CONF_GREEN_CHANNEL = "green_channel"
|
||||||
CONF_BLUE_CHANNEL = "blue_channel"
|
CONF_BLUE_CHANNEL = "blue_channel"
|
||||||
CONF_CLEAR_CHANNEL = "clear_channel"
|
CONF_CLEAR_CHANNEL = "clear_channel"
|
||||||
|
CONF_RED_CHANNEL_IRRADIANCE = "red_channel_irradiance"
|
||||||
|
CONF_GREEN_CHANNEL_IRRADIANCE = "green_channel_irradiance"
|
||||||
|
CONF_BLUE_CHANNEL_IRRADIANCE = "blue_channel_irradiance"
|
||||||
CONF_SENSOR_SATURATION = "sensor_saturation"
|
CONF_SENSOR_SATURATION = "sensor_saturation"
|
||||||
|
|
||||||
tcs34725_ns = cg.esphome_ns.namespace("tcs34725")
|
tcs34725_ns = cg.esphome_ns.namespace("tcs34725")
|
||||||
|
@ -62,8 +66,8 @@ TCS34725_GAINS = {
|
||||||
"60X": TCS34725Gain.TCS34725_GAIN_60X,
|
"60X": TCS34725Gain.TCS34725_GAIN_60X,
|
||||||
}
|
}
|
||||||
|
|
||||||
color_channel_schema = sensor.sensor_schema(
|
color_channel_irradiance_schema = sensor.sensor_schema(
|
||||||
unit_of_measurement=UNIT_PERCENT,
|
unit_of_measurement=UNIT_IRRADIANCE,
|
||||||
icon=ICON_LIGHTBULB,
|
icon=ICON_LIGHTBULB,
|
||||||
accuracy_decimals=1,
|
accuracy_decimals=1,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
@ -91,12 +95,21 @@ CONFIG_SCHEMA = (
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(TCS34725Component),
|
cv.GenerateID(): cv.declare_id(TCS34725Component),
|
||||||
cv.Optional(CONF_RED_CHANNEL): color_channel_schema,
|
cv.Optional(CONF_RED_CHANNEL): cv.invalid(
|
||||||
cv.Optional(CONF_GREEN_CHANNEL): color_channel_schema,
|
"The 'red_channel' configuration option has been removed. Use 'red_channel_irradiance' instead."
|
||||||
cv.Optional(CONF_BLUE_CHANNEL): color_channel_schema,
|
),
|
||||||
|
cv.Optional(CONF_GREEN_CHANNEL): cv.invalid(
|
||||||
|
"The 'green_channel' configuration option has been removed. Use 'green_channel_irradiance' instead."
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_BLUE_CHANNEL): cv.invalid(
|
||||||
|
"The 'blue_channel' configuration option has been removed. Use 'blue_channel_irradiance' instead."
|
||||||
|
),
|
||||||
cv.Optional(CONF_CLEAR_CHANNEL): cv.invalid(
|
cv.Optional(CONF_CLEAR_CHANNEL): cv.invalid(
|
||||||
"The 'clear_channel' configuration option has been removed. Use 'sensor_saturation' instead."
|
"The 'clear_channel' configuration option has been removed. Use 'sensor_saturation' instead."
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_RED_CHANNEL_IRRADIANCE): color_channel_irradiance_schema,
|
||||||
|
cv.Optional(CONF_GREEN_CHANNEL_IRRADIANCE): color_channel_irradiance_schema,
|
||||||
|
cv.Optional(CONF_BLUE_CHANNEL_IRRADIANCE): color_channel_irradiance_schema,
|
||||||
cv.Optional(CONF_SENSOR_SATURATION): sensor_saturation_schema,
|
cv.Optional(CONF_SENSOR_SATURATION): sensor_saturation_schema,
|
||||||
cv.Optional(CONF_ILLUMINANCE): illuminance_schema,
|
cv.Optional(CONF_ILLUMINANCE): illuminance_schema,
|
||||||
cv.Optional(CONF_COLOR_TEMPERATURE): color_temperature_schema,
|
cv.Optional(CONF_COLOR_TEMPERATURE): color_temperature_schema,
|
||||||
|
@ -123,15 +136,15 @@ async def to_code(config):
|
||||||
cg.add(var.set_gain(config[CONF_GAIN]))
|
cg.add(var.set_gain(config[CONF_GAIN]))
|
||||||
cg.add(var.set_glass_attenuation_factor(config[CONF_GLASS_ATTENUATION_FACTOR]))
|
cg.add(var.set_glass_attenuation_factor(config[CONF_GLASS_ATTENUATION_FACTOR]))
|
||||||
|
|
||||||
if CONF_RED_CHANNEL in config:
|
if CONF_RED_CHANNEL_IRRADIANCE in config:
|
||||||
sens = await sensor.new_sensor(config[CONF_RED_CHANNEL])
|
sens = await sensor.new_sensor(config[CONF_RED_CHANNEL_IRRADIANCE])
|
||||||
cg.add(var.set_red_sensor(sens))
|
cg.add(var.set_red_irradiance_sensor(sens))
|
||||||
if CONF_GREEN_CHANNEL in config:
|
if CONF_GREEN_CHANNEL_IRRADIANCE in config:
|
||||||
sens = await sensor.new_sensor(config[CONF_GREEN_CHANNEL])
|
sens = await sensor.new_sensor(config[CONF_GREEN_CHANNEL_IRRADIANCE])
|
||||||
cg.add(var.set_green_sensor(sens))
|
cg.add(var.set_green_irradiance_sensor(sens))
|
||||||
if CONF_BLUE_CHANNEL in config:
|
if CONF_BLUE_CHANNEL_IRRADIANCE in config:
|
||||||
sens = await sensor.new_sensor(config[CONF_BLUE_CHANNEL])
|
sens = await sensor.new_sensor(config[CONF_BLUE_CHANNEL_IRRADIANCE])
|
||||||
cg.add(var.set_blue_sensor(sens))
|
cg.add(var.set_blue_irradiance_sensor(sens))
|
||||||
if CONF_SENSOR_SATURATION in config:
|
if CONF_SENSOR_SATURATION in config:
|
||||||
sens = await sensor.new_sensor(config[CONF_SENSOR_SATURATION])
|
sens = await sensor.new_sensor(config[CONF_SENSOR_SATURATION])
|
||||||
cg.add(var.set_sensor_saturation(sens))
|
cg.add(var.set_sensor_saturation(sens))
|
||||||
|
|
|
@ -17,6 +17,9 @@ static const uint8_t TCS34725_REGISTER_ATIME = TCS34725_COMMAND_BIT | 0x01;
|
||||||
static const uint8_t TCS34725_REGISTER_CONTROL = TCS34725_COMMAND_BIT | 0x0F;
|
static const uint8_t TCS34725_REGISTER_CONTROL = TCS34725_COMMAND_BIT | 0x0F;
|
||||||
static const uint8_t TCS34725_REGISTER_ENABLE = TCS34725_COMMAND_BIT | 0x00;
|
static const uint8_t TCS34725_REGISTER_ENABLE = TCS34725_COMMAND_BIT | 0x00;
|
||||||
static const uint8_t TCS34725_REGISTER_CRGBDATAL = TCS34725_COMMAND_BIT | 0x14;
|
static const uint8_t TCS34725_REGISTER_CRGBDATAL = TCS34725_COMMAND_BIT | 0x14;
|
||||||
|
static const float RED_CHANNEL_COUNTS_TO_IRRADIANCE = 0.030895152730118627f; // counts/µW/cm²
|
||||||
|
static const float GREEN_CHANNEL_COUNTS_TO_IRRADIANCE = 0.032402966993759885f; // counts/µW/cm²
|
||||||
|
static const float BLUE_CHANNEL_COUNTS_TO_IRRADIANCE = 0.03695911040578352f; // counts/µW/cm²
|
||||||
|
|
||||||
void TCS34725Component::setup() {
|
void TCS34725Component::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up TCS34725...");
|
ESP_LOGCONFIG(TAG, "Setting up TCS34725...");
|
||||||
|
@ -52,14 +55,39 @@ void TCS34725Component::dump_config() {
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
|
||||||
LOG_SENSOR(" ", "Sensor Saturation", this->sensor_saturation_);
|
LOG_SENSOR(" ", "Sensor Saturation", this->sensor_saturation_);
|
||||||
LOG_SENSOR(" ", "Red Channel", this->red_sensor_);
|
LOG_SENSOR(" ", "Red Channel Irradiance", this->red_irradiance_sensor_);
|
||||||
LOG_SENSOR(" ", "Green Channel", this->green_sensor_);
|
LOG_SENSOR(" ", "Green Channel Irradiance", this->green_irradiance_sensor_);
|
||||||
LOG_SENSOR(" ", "Blue Channel", this->blue_sensor_);
|
LOG_SENSOR(" ", "Blue Channel Irradiance", this->blue_irradiance_sensor_);
|
||||||
LOG_SENSOR(" ", "Illuminance", this->illuminance_sensor_);
|
LOG_SENSOR(" ", "Illuminance", this->illuminance_sensor_);
|
||||||
LOG_SENSOR(" ", "Color Temperature", this->color_temperature_sensor_);
|
LOG_SENSOR(" ", "Color Temperature", this->color_temperature_sensor_);
|
||||||
}
|
}
|
||||||
float TCS34725Component::get_setup_priority() const { return setup_priority::DATA; }
|
float TCS34725Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Determines the minimum raw value threshold for color channels at which the sensor is considered underexposed
|
||||||
|
*
|
||||||
|
* @return Minimum raw value threshold
|
||||||
|
*/
|
||||||
|
uint16_t TCS34725Component::get_min_raw_limit_() const {
|
||||||
|
// Minimum raw value below 1 is considered too low, return NaN
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Determines the saturation threshold at which the sensor is considered overexposed
|
||||||
|
*
|
||||||
|
* @return The saturation limit as a percentage (between 0.0 and 100.0).
|
||||||
|
*/
|
||||||
|
float TCS34725Component::get_saturation_limit_() const {
|
||||||
|
// Return 99.99f if integration time is below 153.6ms, else return 75.0f
|
||||||
|
if ((256 - this->integration_reg_) < TCS34725_INTEGRATION_TIME_154MS) {
|
||||||
|
return 99.99f;
|
||||||
|
} else {
|
||||||
|
/* Adjust sat limit to 75% to avoid analog saturation if atime < 153.6ms */
|
||||||
|
return 75.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Converts the raw R/G/B values to color temperature in degrees
|
* @brief Converts the raw R/G/B values to color temperature in degrees
|
||||||
* Kelvin using the algorithm described in DN40 from Taos (now AMS).
|
* Kelvin using the algorithm described in DN40 from Taos (now AMS).
|
||||||
|
@ -77,9 +105,6 @@ float TCS34725Component::get_setup_priority() const { return setup_priority::DAT
|
||||||
*/
|
*/
|
||||||
void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, uint16_t b, float current_saturation,
|
void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, uint16_t b, float current_saturation,
|
||||||
uint16_t min_raw_value) {
|
uint16_t min_raw_value) {
|
||||||
float sat_limit;
|
|
||||||
uint16_t min_raw_limit;
|
|
||||||
|
|
||||||
this->illuminance_ = NAN;
|
this->illuminance_ = NAN;
|
||||||
this->color_temperature_ = NAN;
|
this->color_temperature_ = NAN;
|
||||||
|
|
||||||
|
@ -94,8 +119,7 @@ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, u
|
||||||
static const float MAX_COLOR_TEMPERATURE = 15000.0f; // Maximum expected color temperature in Kelvin
|
static const float MAX_COLOR_TEMPERATURE = 15000.0f; // Maximum expected color temperature in Kelvin
|
||||||
static const float MIN_COLOR_TEMPERATURE = 1000.0f; // Maximum reasonable color temperature in Kelvin
|
static const float MIN_COLOR_TEMPERATURE = 1000.0f; // Maximum reasonable color temperature in Kelvin
|
||||||
|
|
||||||
// Minimum raw value below 1 is considered too low, return NaN
|
uint16_t min_raw_limit = get_min_raw_limit_();
|
||||||
min_raw_limit = 1;
|
|
||||||
|
|
||||||
if (min_raw_value < min_raw_limit) {
|
if (min_raw_value < min_raw_limit) {
|
||||||
ESP_LOGW(TAG,
|
ESP_LOGW(TAG,
|
||||||
|
@ -118,12 +142,7 @@ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, u
|
||||||
* the count reaches 65535.
|
* the count reaches 65535.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Adjust sat limit to 75% to avoid analog saturation if atime < 153.6ms */
|
float sat_limit = get_saturation_limit_();
|
||||||
if ((256 - this->integration_reg_) < 192) {
|
|
||||||
sat_limit = 99.99f;
|
|
||||||
} else {
|
|
||||||
sat_limit = 75.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ripple rejection:
|
/* Ripple rejection:
|
||||||
*
|
*
|
||||||
|
@ -146,13 +165,12 @@ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, u
|
||||||
/* Check for saturation and mark the sample as invalid if true */
|
/* Check for saturation and mark the sample as invalid if true */
|
||||||
if (current_saturation >= sat_limit) {
|
if (current_saturation >= sat_limit) {
|
||||||
if (this->integration_time_auto_) {
|
if (this->integration_time_auto_) {
|
||||||
ESP_LOGI(TAG, "Saturation too high, sample discarded, autogain ongoing");
|
ESP_LOGI(TAG, "Saturation too high, skip Lux/color temperature calculation, autogain ongoing");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG,
|
ESP_LOGW(TAG,
|
||||||
"Saturation too high, sample with saturation %.1f above limit (%.1f). Lux/color"
|
"Saturation too high, sample with saturation %.1f above limit (%.1f). Lux/color temperature cannot be "
|
||||||
"temperature cannot reliably calculated, reduce integration/gain or use a grey"
|
"reliably calculated, reduce integration/gain or use a grey filter.",
|
||||||
"filter.",
|
|
||||||
current_saturation, sat_limit);
|
current_saturation, sat_limit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -192,6 +210,64 @@ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Calculates the irradiance per channel (R/G/B) using fixed conversion factors.
|
||||||
|
* @param r
|
||||||
|
* Red raw value
|
||||||
|
* @param g
|
||||||
|
* Green raw value
|
||||||
|
* @param b
|
||||||
|
* Blue raw value
|
||||||
|
* @param current_saturation
|
||||||
|
* Sensor saturation in percent
|
||||||
|
* @param min_raw_value
|
||||||
|
* Lowest raw value reported by the sensor
|
||||||
|
*/
|
||||||
|
void TCS34725Component::calculate_irradiance_(uint16_t r, uint16_t g, uint16_t b, float current_saturation,
|
||||||
|
uint16_t min_raw_value) {
|
||||||
|
this->irradiance_r_ = NAN;
|
||||||
|
this->irradiance_g_ = NAN;
|
||||||
|
this->irradiance_b_ = NAN;
|
||||||
|
|
||||||
|
uint16_t min_raw_limit = get_min_raw_limit_();
|
||||||
|
float sat_limit = get_saturation_limit_();
|
||||||
|
|
||||||
|
if (min_raw_value < min_raw_limit) {
|
||||||
|
ESP_LOGW(TAG,
|
||||||
|
"Saturation too low, sample with saturation %d (raw value) below limit (%d). Irradiance cannot be "
|
||||||
|
"reliably calculated.",
|
||||||
|
min_raw_value, min_raw_limit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for saturation and mark the sample as invalid if true */
|
||||||
|
if (current_saturation >= sat_limit) {
|
||||||
|
if (this->integration_time_auto_) {
|
||||||
|
ESP_LOGI(TAG, "Saturation too high, skip irradiance calculation, autogain ongoing");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG,
|
||||||
|
"Saturation too high, sample with saturation %.1f above limit (%.1f). Irradiance cannot be reliably "
|
||||||
|
"calculated, reduce integration/gain or use a grey filter.",
|
||||||
|
current_saturation, sat_limit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the scaling factor for integration time
|
||||||
|
float integration_time_scaling = this->integration_time_ / 2.4f;
|
||||||
|
|
||||||
|
// Calculate irradiance for each channel using predefined conversion factors
|
||||||
|
this->irradiance_r_ = std::max(r / (RED_CHANNEL_COUNTS_TO_IRRADIANCE * integration_time_scaling * this->gain_), 0.0f);
|
||||||
|
this->irradiance_g_ =
|
||||||
|
std::max(g / (GREEN_CHANNEL_COUNTS_TO_IRRADIANCE * integration_time_scaling * this->gain_), 0.0f);
|
||||||
|
this->irradiance_b_ =
|
||||||
|
std::max(b / (BLUE_CHANNEL_COUNTS_TO_IRRADIANCE * integration_time_scaling * this->gain_), 0.0f);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Calculated irradiance - R: %.2f µW/cm2, G: %.2f µW/cm2, B: %.2f µW/cm2", this->irradiance_r_,
|
||||||
|
this->irradiance_g_, this->irradiance_b_);
|
||||||
|
}
|
||||||
|
|
||||||
void TCS34725Component::update() {
|
void TCS34725Component::update() {
|
||||||
uint8_t data[8]; // Buffer to hold the 8 bytes (2 bytes for each of the 4 channels)
|
uint8_t data[8]; // Buffer to hold the 8 bytes (2 bytes for each of the 4 channels)
|
||||||
|
|
||||||
|
@ -214,9 +290,6 @@ void TCS34725Component::update() {
|
||||||
uint16_t peak_raw_value = std::max({raw_r, raw_g, raw_b});
|
uint16_t peak_raw_value = std::max({raw_r, raw_g, raw_b});
|
||||||
uint16_t min_raw_value = std::min({raw_r, raw_g, raw_b});
|
uint16_t min_raw_value = std::min({raw_r, raw_g, raw_b});
|
||||||
uint16_t max_count;
|
uint16_t max_count;
|
||||||
float channel_r;
|
|
||||||
float channel_g;
|
|
||||||
float channel_b;
|
|
||||||
|
|
||||||
/* sensor counts up to 1024 for each 2.4 ms of integration time, until 65535 is hit, which is the
|
/* sensor counts up to 1024 for each 2.4 ms of integration time, until 65535 is hit, which is the
|
||||||
* maximum which can be stored in the counter. This happens at 153.6 ms integration time. */
|
* maximum which can be stored in the counter. This happens at 153.6 ms integration time. */
|
||||||
|
@ -228,15 +301,9 @@ void TCS34725Component::update() {
|
||||||
|
|
||||||
current_saturation = clamp(current_saturation, 0.0f, 100.0f);
|
current_saturation = clamp(current_saturation, 0.0f, 100.0f);
|
||||||
|
|
||||||
// FIXME: sum calculation cannot be done here anymore, so we publish 0 values for now
|
if (this->red_irradiance_sensor_ || this->green_irradiance_sensor_ || this->blue_irradiance_sensor_) {
|
||||||
channel_r = channel_g = channel_b = 0.0f;
|
calculate_irradiance_(raw_r, raw_g, raw_b, current_saturation, min_raw_value);
|
||||||
|
}
|
||||||
if (this->red_sensor_ != nullptr)
|
|
||||||
this->red_sensor_->publish_state(channel_r);
|
|
||||||
if (this->green_sensor_ != nullptr)
|
|
||||||
this->green_sensor_->publish_state(channel_g);
|
|
||||||
if (this->blue_sensor_ != nullptr)
|
|
||||||
this->blue_sensor_->publish_state(channel_b);
|
|
||||||
|
|
||||||
if (this->illuminance_sensor_ || this->color_temperature_sensor_) {
|
if (this->illuminance_sensor_ || this->color_temperature_sensor_) {
|
||||||
calculate_temperature_and_lux_(raw_r, raw_g, raw_b, current_saturation, min_raw_value);
|
calculate_temperature_and_lux_(raw_r, raw_g, raw_b, current_saturation, min_raw_value);
|
||||||
|
@ -251,19 +318,23 @@ void TCS34725Component::update() {
|
||||||
(this->gain_reg_ == 0 && this->integration_time_ < 200)) {
|
(this->gain_reg_ == 0 && this->integration_time_ < 200)) {
|
||||||
if (this->illuminance_sensor_ != nullptr)
|
if (this->illuminance_sensor_ != nullptr)
|
||||||
this->illuminance_sensor_->publish_state(this->illuminance_);
|
this->illuminance_sensor_->publish_state(this->illuminance_);
|
||||||
|
|
||||||
if (this->color_temperature_sensor_ != nullptr)
|
if (this->color_temperature_sensor_ != nullptr)
|
||||||
this->color_temperature_sensor_->publish_state(this->color_temperature_);
|
this->color_temperature_sensor_->publish_state(this->color_temperature_);
|
||||||
|
if (this->sensor_saturation_ != nullptr)
|
||||||
if (this->sensor_saturation_ != nullptr) {
|
|
||||||
this->sensor_saturation_->publish_state(current_saturation);
|
this->sensor_saturation_->publish_state(current_saturation);
|
||||||
}
|
if (this->red_irradiance_sensor_ != nullptr)
|
||||||
|
this->red_irradiance_sensor_->publish_state(this->irradiance_r_);
|
||||||
|
if (this->green_irradiance_sensor_ != nullptr)
|
||||||
|
this->green_irradiance_sensor_->publish_state(this->irradiance_g_);
|
||||||
|
if (this->blue_irradiance_sensor_ != nullptr)
|
||||||
|
this->blue_irradiance_sensor_->publish_state(this->irradiance_b_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG,
|
ESP_LOGD(TAG,
|
||||||
"Got Red=%.1f%%,Green=%.1f%%,Blue=%.1f%%,Sensor Saturation=%.1f%% Illuminance=%.1flx Color "
|
"Calculated: Red Irad=%.2f µW/cm², Green Irad=%.2f µW/cm², Blue Irad=%.2f µW/cm², Sensor Sat=%.2f%%, "
|
||||||
"Temperature=%.1fK",
|
"Illum=%.1f lx, Color Temp=%.1f K",
|
||||||
channel_r, channel_g, channel_b, current_saturation, this->illuminance_, this->color_temperature_);
|
this->irradiance_r_, this->irradiance_g_, this->irradiance_b_, current_saturation, this->illuminance_,
|
||||||
|
this->color_temperature_);
|
||||||
|
|
||||||
if (this->integration_time_auto_) {
|
if (this->integration_time_auto_) {
|
||||||
// change integration time an gain to achieve maximum resolution an dynamic range
|
// change integration time an gain to achieve maximum resolution an dynamic range
|
||||||
|
|
|
@ -43,9 +43,15 @@ class TCS34725Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
void set_glass_attenuation_factor(float ga);
|
void set_glass_attenuation_factor(float ga);
|
||||||
|
|
||||||
void set_sensor_saturation(sensor::Sensor *sensor_saturation) { sensor_saturation_ = sensor_saturation; }
|
void set_sensor_saturation(sensor::Sensor *sensor_saturation) { sensor_saturation_ = sensor_saturation; }
|
||||||
void set_red_sensor(sensor::Sensor *red_sensor) { red_sensor_ = red_sensor; }
|
void set_red_irradiance_sensor(sensor::Sensor *red_irradiance_sensor) {
|
||||||
void set_green_sensor(sensor::Sensor *green_sensor) { green_sensor_ = green_sensor; }
|
red_irradiance_sensor_ = red_irradiance_sensor;
|
||||||
void set_blue_sensor(sensor::Sensor *blue_sensor) { blue_sensor_ = blue_sensor; }
|
}
|
||||||
|
void set_green_irradiance_sensor(sensor::Sensor *green_irradiance_sensor) {
|
||||||
|
green_irradiance_sensor_ = green_irradiance_sensor;
|
||||||
|
}
|
||||||
|
void set_blue_irradiance_sensor(sensor::Sensor *blue_irradiance_sensor) {
|
||||||
|
blue_irradiance_sensor_ = blue_irradiance_sensor;
|
||||||
|
}
|
||||||
void set_illuminance_sensor(sensor::Sensor *illuminance_sensor) { illuminance_sensor_ = illuminance_sensor; }
|
void set_illuminance_sensor(sensor::Sensor *illuminance_sensor) { illuminance_sensor_ = illuminance_sensor; }
|
||||||
void set_color_temperature_sensor(sensor::Sensor *color_temperature_sensor) {
|
void set_color_temperature_sensor(sensor::Sensor *color_temperature_sensor) {
|
||||||
color_temperature_sensor_ = color_temperature_sensor;
|
color_temperature_sensor_ = color_temperature_sensor;
|
||||||
|
@ -68,21 +74,27 @@ class TCS34725Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
return this->write_register(a_register, &data, 1);
|
return this->write_register(a_register, &data, 1);
|
||||||
}
|
}
|
||||||
sensor::Sensor *sensor_saturation_{nullptr};
|
sensor::Sensor *sensor_saturation_{nullptr};
|
||||||
sensor::Sensor *red_sensor_{nullptr};
|
sensor::Sensor *red_irradiance_sensor_{nullptr};
|
||||||
sensor::Sensor *green_sensor_{nullptr};
|
sensor::Sensor *green_irradiance_sensor_{nullptr};
|
||||||
sensor::Sensor *blue_sensor_{nullptr};
|
sensor::Sensor *blue_irradiance_sensor_{nullptr};
|
||||||
sensor::Sensor *illuminance_sensor_{nullptr};
|
sensor::Sensor *illuminance_sensor_{nullptr};
|
||||||
sensor::Sensor *color_temperature_sensor_{nullptr};
|
sensor::Sensor *color_temperature_sensor_{nullptr};
|
||||||
float integration_time_{2.4};
|
float integration_time_{2.4};
|
||||||
float gain_{1.0};
|
float gain_{1.0};
|
||||||
float glass_attenuation_{1.0};
|
float glass_attenuation_{1.0};
|
||||||
float illuminance_;
|
float illuminance_{NAN};
|
||||||
float color_temperature_;
|
float color_temperature_{NAN};
|
||||||
|
float irradiance_r_{NAN};
|
||||||
|
float irradiance_g_{NAN};
|
||||||
|
float irradiance_b_{NAN};
|
||||||
bool integration_time_auto_{true};
|
bool integration_time_auto_{true};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void calculate_temperature_and_lux_(uint16_t r, uint16_t g, uint16_t b, float current_saturation,
|
void calculate_temperature_and_lux_(uint16_t r, uint16_t g, uint16_t b, float current_saturation,
|
||||||
uint16_t min_raw_value);
|
uint16_t min_raw_value);
|
||||||
|
void calculate_irradiance_(uint16_t r, uint16_t g, uint16_t b, float current_saturation, uint16_t min_raw_value);
|
||||||
|
float get_saturation_limit_() const;
|
||||||
|
uint16_t get_min_raw_limit_() const;
|
||||||
uint16_t integration_reg_;
|
uint16_t integration_reg_;
|
||||||
uint8_t gain_reg_{TCS34725_GAIN_1X};
|
uint8_t gain_reg_{TCS34725_GAIN_1X};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1048,6 +1048,7 @@ UNIT_GRAMS_PER_CUBIC_METER = "g/m³"
|
||||||
UNIT_HECTOPASCAL = "hPa"
|
UNIT_HECTOPASCAL = "hPa"
|
||||||
UNIT_HERTZ = "Hz"
|
UNIT_HERTZ = "Hz"
|
||||||
UNIT_HOUR = "h"
|
UNIT_HOUR = "h"
|
||||||
|
UNIT_IRRADIANCE = "µW/cm²"
|
||||||
UNIT_KELVIN = "K"
|
UNIT_KELVIN = "K"
|
||||||
UNIT_KILOGRAM = "kg"
|
UNIT_KILOGRAM = "kg"
|
||||||
UNIT_KILOMETER = "km"
|
UNIT_KILOMETER = "km"
|
||||||
|
|
|
@ -5,12 +5,12 @@ i2c:
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: tcs34725
|
- platform: tcs34725
|
||||||
red_channel:
|
red_channel_irradiance:
|
||||||
name: Red Channel
|
name: Red Channel Irradiance
|
||||||
green_channel:
|
green_channel_irradiance:
|
||||||
name: Green Channel
|
name: Green Channel Irradiance
|
||||||
blue_channel:
|
blue_channel_irradiance:
|
||||||
name: Blue Channel
|
name: Blue Channel Irradiance
|
||||||
sensor_saturation:
|
sensor_saturation:
|
||||||
name: Sensor Saturation
|
name: Sensor Saturation
|
||||||
illuminance:
|
illuminance:
|
||||||
|
|
|
@ -5,12 +5,12 @@ i2c:
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: tcs34725
|
- platform: tcs34725
|
||||||
red_channel:
|
red_channel_irradiance:
|
||||||
name: Red Channel
|
name: Red Channel Irradiance
|
||||||
green_channel:
|
green_channel_irradiance:
|
||||||
name: Green Channel
|
name: Green Channel Irradiance
|
||||||
blue_channel:
|
blue_channel_irradiance:
|
||||||
name: Blue Channel
|
name: Blue Channel Irradiance
|
||||||
sensor_saturation:
|
sensor_saturation:
|
||||||
name: Sensor Saturation
|
name: Sensor Saturation
|
||||||
illuminance:
|
illuminance:
|
||||||
|
|
|
@ -5,12 +5,12 @@ i2c:
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: tcs34725
|
- platform: tcs34725
|
||||||
red_channel:
|
red_channel_irradiance:
|
||||||
name: Red Channel
|
name: Red Channel Irradiance
|
||||||
green_channel:
|
green_channel_irradiance:
|
||||||
name: Green Channel
|
name: Green Channel Irradiance
|
||||||
blue_channel:
|
blue_channel_irradiance:
|
||||||
name: Blue Channel
|
name: Blue Channel Irradiance
|
||||||
sensor_saturation:
|
sensor_saturation:
|
||||||
name: Sensor Saturation
|
name: Sensor Saturation
|
||||||
illuminance:
|
illuminance:
|
||||||
|
|
|
@ -5,12 +5,12 @@ i2c:
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: tcs34725
|
- platform: tcs34725
|
||||||
red_channel:
|
red_channel_irradiance:
|
||||||
name: Red Channel
|
name: Red Channel Irradiance
|
||||||
green_channel:
|
green_channel_irradiance:
|
||||||
name: Green Channel
|
name: Green Channel Irradiance
|
||||||
blue_channel:
|
blue_channel_irradiance:
|
||||||
name: Blue Channel
|
name: Blue Channel Irradiance
|
||||||
sensor_saturation:
|
sensor_saturation:
|
||||||
name: Sensor Saturation
|
name: Sensor Saturation
|
||||||
illuminance:
|
illuminance:
|
||||||
|
|
|
@ -5,12 +5,12 @@ i2c:
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: tcs34725
|
- platform: tcs34725
|
||||||
red_channel:
|
red_channel_irradiance:
|
||||||
name: Red Channel
|
name: Red Channel Irradiance
|
||||||
green_channel:
|
green_channel_irradiance:
|
||||||
name: Green Channel
|
name: Green Channel Irradiance
|
||||||
blue_channel:
|
blue_channel_irradiance:
|
||||||
name: Blue Channel
|
name: Blue Channel Irradiance
|
||||||
sensor_saturation:
|
sensor_saturation:
|
||||||
name: Sensor Saturation
|
name: Sensor Saturation
|
||||||
illuminance:
|
illuminance:
|
||||||
|
|
|
@ -5,12 +5,12 @@ i2c:
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: tcs34725
|
- platform: tcs34725
|
||||||
red_channel:
|
red_channel_irradiance:
|
||||||
name: Red Channel
|
name: Red Channel Irradiance
|
||||||
green_channel:
|
green_channel_irradiance:
|
||||||
name: Green Channel
|
name: Green Channel Irradiance
|
||||||
blue_channel:
|
blue_channel_irradiance:
|
||||||
name: Blue Channel
|
name: Blue Channel Irradiance
|
||||||
sensor_saturation:
|
sensor_saturation:
|
||||||
name: Sensor Saturation
|
name: Sensor Saturation
|
||||||
illuminance:
|
illuminance:
|
||||||
|
|
Loading…
Reference in a new issue