some errata fixes

This commit is contained in:
Anton Viktorov 2024-03-22 18:35:42 +01:00
parent a59610b96d
commit db1e641fcb
3 changed files with 92 additions and 15 deletions

View file

@ -152,8 +152,8 @@ void AS7343Component::dump_config() {
LOG_SENSOR(" ", "F8", this->f8_);
LOG_SENSOR(" ", "NIR", this->nir_);
LOG_SENSOR(" ", "Clear", this->clear_);
LOG_SENSOR(" ", "Clear", this->clear_);
LOG_SENSOR(" ", "Clear", this->clear_);
// LOG_SENSOR(" ", "Clear", this->clear_);
// LOG_SENSOR(" ", "Clear", this->clear_);
}
float AS7343Component::get_setup_priority() const { return setup_priority::DATA; }
@ -197,7 +197,7 @@ void AS7343Component::loop() {
if (this->is_data_ready()) {
this->read_all_channels();
this->enable_spectral_measurement(false);
log13_s(TAG, "Channel", CHANNEL_NAMES);
log13_f(TAG, "Nm", CHANNEL_NM);
log13_d(TAG, "Counts", this->readings_.raw_counts);
@ -243,34 +243,44 @@ void AS7343Component::calculate_and_publish() {
float lux;
float ppfd;
float cct, duv, lux2;
this->calculate_irradiance(irradiance, irradiance_photopic, lux);
this->calculate_ppfd(ppfd);
this->calculate_color_params(cct, duv, lux2);
ESP_LOGD(TAG, "BEFORE GLASS ATTENUATION");
ESP_LOGD(TAG, " ,Irradiance , %f, W/m²", irradiance);
ESP_LOGD(TAG, " ,Irradiance(photopic), %f, W/m²", irradiance_photopic);
ESP_LOGD(TAG, " ,Lux(solar coeff) , %f, lx", lux);
ESP_LOGD(TAG, " ,PPFD , %.2f, µmol/s⋅m²", ppfd);
// ESP_LOGD(TAG, "BEFORE GLASS ATTENUATION");
// ESP_LOGD(TAG, " ,Irradiance , %f, W/m²", irradiance);
// ESP_LOGD(TAG, " ,Irradiance(photopic), %f, W/m²", irradiance_photopic);
// ESP_LOGD(TAG, " ,Lux(solar coeff) , %f, lx", lux);
// ESP_LOGD(TAG, " ,PPFD , %f, µmol/s⋅m²", ppfd);
irradiance *= this->glass_attenuation_factor_;
irradiance_photopic *= this->glass_attenuation_factor_;
lux *= this->glass_attenuation_factor_;
lux2 *= this->glass_attenuation_factor_;
ppfd *= this->glass_attenuation_factor_;
ESP_LOGD(TAG, "AFTER GLASS ATTENUATION");
ESP_LOGD(TAG, " ,Irradiance , %f, W/m²", irradiance);
ESP_LOGD(TAG, " ,Irradiance(photopic), %f, W/m²", irradiance_photopic);
ESP_LOGD(TAG, " ,PPFD , %f, µmol/s⋅m²", ppfd);
ESP_LOGD(TAG, " ,Lux(solar coeff) , %f, lx", lux);
ESP_LOGD(TAG, " ,PPFD , %.2f, µmol/s⋅m²", ppfd);
ESP_LOGD(TAG, " ,Lux(XYZ) , %f, lx", lux2);
ESP_LOGD(TAG, " ,Color temp(XYZ) , %f, K", cct);
if (this->illuminance_ != nullptr) {
this->illuminance_->publish_state(lux);
this->illuminance_->publish_state(lux2);
}
if (this->irradiance_ != nullptr) {
this->irradiance_->publish_state(irradiance);
}
if (this->irradiance_photopic_ != nullptr) {
this->irradiance_photopic_->publish_state(irradiance_photopic);
}
if (this->ppfd_ != nullptr) {
this->ppfd_->publish_state(ppfd);
}
@ -326,7 +336,7 @@ void AS7343Component::calculate_and_publish() {
this->nir_->publish_state(normalized_readings[11]);
}
if (this->clear_ != nullptr) {
float clear = (this->readings_.basic_counts[AS7343_CHANNEL_CLEAR]);
float clear = (this->readings_.basic_counts[AS7343_CHANNEL_CLEAR_0]);
this->clear_->publish_state(clear);
}
if (this->saturated_ != nullptr) {
@ -425,11 +435,19 @@ void AS7343Component::calculate_ppfd(float &ppfd) {
// Iλ(λ)
float irradiance_in_w_per_m2 = this->readings_.basic_counts[i] * CHANNEL_IRRAD_MW_PER_BASIC_COUNT[i] / 1000;
float photon_flux = irradiance_in_w_per_m2 * CHANNEL_NM[i] * 0.836e-2;
// hack?
irradiance_in_w_per_m2 *= 10;
// float photon_flux = irradiance_in_w_per_m2 * CHANNEL_NM[i] * 0.836e-2;
// // ESP_LOGD(TAG, "Photon flux (%.0f) = %.2f", CHANNEL_NM[i], photon_flux);
// // assume channels cover whole range
// ppfd += photon_flux * CHANNEL_NM_WIDTH[i] / 1e9f; // nm to meters
// assume channels cover whole range
ppfd += photon_flux * CHANNEL_NM_WIDTH[i] / 1e9f; // nm to meters
ppfd += irradiance_in_w_per_m2;
}
// https://www.controlledenvironments.org/wp-content/uploads/sites/6/2017/06/Ch01.pdf
ppfd *= 4.6; // good approximation 1 W/m2 ≈ 4.6 μmole.m2/s.
}
void AS7343Component::calculate_irradiance(float &irradiance_in_w_per_m2, float &irradiance_in_w_per_m2_photopic,
@ -443,7 +461,13 @@ void AS7343Component::calculate_irradiance(float &irradiance_in_w_per_m2, float
// walk through all bands except for Clear (VIS)
for (uint8_t i = 0; i < AS7343_NUM_CHANNELS - 1; i++) {
//
irr_band = this->readings_.basic_counts[i] * CHANNEL_IRRAD_MW_PER_BASIC_COUNT[i] / 1000;
//errata hack???
irr_band *= 10;
irradiance_in_w_per_m2 += irr_band;
// photo_band *= CHANNEL_ENERGY_CONTRIBUTION[i]; ?? ideas
@ -457,6 +481,44 @@ void AS7343Component::calculate_irradiance(float &irradiance_in_w_per_m2, float
lux = irradiance_in_w_per_m2_photopic * 116;
}
void AS7343Component::calculate_color_params(float &cct, float &duv, float &lux) {
float AS7343_XYZ_COEFF[3][AS7343_NUM_CHANNELS - 2] = {
{-0.07879, -0.12235, 1.99879, -0.33364, -0.06795, -0.45419, 0.00000, 5.27242, -0.05072, -0.04666, -0.03931},
{-0.03269, -0.01297, -0.04011, -0.06889, -0.17453, 5.69083, 0.00000, -0.22956, -0.04762, -0.01295, -0.02797},
{-0.31295, -0.57885, 10.00197, -0.31281, -0.19657, -0.11077, 0.00000, -0.06132, -0.03536, -0.06025, -0.12174}};
float XYZ[3] = {0, 0, 0};
for (uint8_t i = 0; i < AS7343_NUM_CHANNELS - 2; i++) {
for (uint8_t j = 0; j < 3; j++) {
XYZ[j] += this->readings_.basic_counts[i] * AS7343_XYZ_COEFF[j][i];
}
}
float epsilon = 0.0001;
float xyz_sum = XYZ[0] + XYZ[1] + XYZ[2];
float x{0}, y{0}, z{0};
if (xyz_sum < epsilon && xyz_sum > -epsilon) {
cct = 0;
duv = 0;
lux = 0;
} else {
duv = 0;
x = XYZ[0] / xyz_sum;
y = XYZ[1] / xyz_sum;
z = XYZ[2] / xyz_sum;
float n = (x - 0.3320) / (0.1858 - y);
cct = 437 * pow(n, 3) + 3601 * pow(n, 2) + 6861 * n + 5517;
// Calc lx from Y CIE1931
lux = XYZ[1] * 683;
}
// ESP_LOGD(TAG, "XYZ: %.2f, %.2f, %.2f", XYZ[0], XYZ[1], XYZ[2]);
// ESP_LOGD(TAG, "x: %.4f, y: %.4f, z: %.4f", x, y, z);
// ESP_LOGD(TAG, "XYZ: CCT: %.2f, lux: %.2f", cct, lux);
}
bool AS7343Component::read_all_channels() {
static constexpr uint8_t CHANNEL_MAP[AS7343_NUM_CHANNELS] = {
AS7343_CHANNEL_405_F1, AS7343_CHANNEL_425_F2, AS7343_CHANNEL_450_FZ, AS7343_CHANNEL_475_F3,
@ -495,7 +557,7 @@ bool AS7343Component::read_all_channels() {
this->readings_.gain_x = get_gain_multiplier(this->readings_.gain);
this->readings_.atime = get_atime();
this->readings_.astep = get_astep();
this->readings_.t_int = (1 + this->readings_.atime) * (1 + this->readings_.astep) * 2.78 / 1000; // us to ms
this->readings_.t_int = (1 + this->readings_.atime) * (1 + this->readings_.astep) * 2.78; // / 1000; // us to ms
this->readings_saturated_ = astatus.asat_status;

View file

@ -32,6 +32,7 @@ class AS7343Component : public PollingComponent, public i2c::I2CDevice {
void set_clear_sensor(sensor::Sensor *clear_sensor) { clear_ = clear_sensor; }
void set_illuminance_sensor(sensor::Sensor *sensor) { illuminance_ = sensor; }
void set_irradiance_sensor(sensor::Sensor *sensor) { irradiance_ = sensor; }
void set_irradiance_photopic_sensor(sensor::Sensor *sensor) { irradiance_photopic_ = sensor; }
void set_ppfd_sensor(sensor::Sensor *sensor) { ppfd_ = sensor; }
void set_saturation_sensor(sensor::Sensor *sensor) { this->saturated_ = sensor; }
@ -57,6 +58,7 @@ class AS7343Component : public PollingComponent, public i2c::I2CDevice {
void calculate_basic_counts();
void calculate_ppfd(float &ppfd);
void calculate_irradiance(float &irradiance, float &irradiance_photopic, float &lux);
void calculate_color_params(float &ct, float &duv, float &lux);
bool is_data_ready();
@ -110,6 +112,7 @@ class AS7343Component : public PollingComponent, public i2c::I2CDevice {
sensor::Sensor *clear_{nullptr};
sensor::Sensor *illuminance_{nullptr};
sensor::Sensor *irradiance_{nullptr};
sensor::Sensor *irradiance_photopic_{nullptr};
sensor::Sensor *ppfd_{nullptr};
sensor::Sensor *saturated_{nullptr};

View file

@ -41,6 +41,7 @@ CONF_F8 = "f8"
CONF_NIR = "nir"
CONF_CLEAR = "clear"
CONF_IRRADIANCE = "irradiance"
CONF_IRRADIANCE_PHOTOPIC = "irradiance_photopic"
CONF_PPFD = "ppfd"
CONF_SATURATION = "saturation"
@ -132,6 +133,16 @@ CONFIG_SCHEMA = (
),
key=CONF_NAME,
),
cv.Optional(CONF_IRRADIANCE_PHOTOPIC): cv.maybe_simple_value(
sensor.sensor_schema(
unit_of_measurement=UNIT_IRRADIANCE,
icon=ICON_BRIGHTNESS_5,
accuracy_decimals=0,
device_class=DEVICE_CLASS_ILLUMINANCE,
state_class=STATE_CLASS_MEASUREMENT,
),
key=CONF_NAME,
),
cv.Optional(CONF_PPFD): cv.maybe_simple_value(
sensor.sensor_schema(
unit_of_measurement=UNIT_PPFD,
@ -174,6 +185,7 @@ SENSORS = {
CONF_CLEAR: "set_clear_sensor",
CONF_ILLUMINANCE: "set_illuminance_sensor",
CONF_IRRADIANCE: "set_irradiance_sensor",
CONF_IRRADIANCE_PHOTOPIC: "set_irradiance_photopic_sensor",
CONF_PPFD: "set_ppfd_sensor",
CONF_SATURATION: "set_saturation_sensor",
}