mirror of
https://github.com/esphome/esphome.git
synced 2025-01-09 14:21:46 +01:00
more experiments
This commit is contained in:
parent
ac155e6353
commit
63cfcc8725
4 changed files with 2036 additions and 879 deletions
|
@ -17,6 +17,11 @@ static constexpr uint8_t CHANNEL_IDX[NUM_USEFUL_CHANNELS] = {
|
||||||
AS7343_CHANNEL_405_F1, AS7343_CHANNEL_425_F2, AS7343_CHANNEL_450_FZ, AS7343_CHANNEL_475_F3, AS7343_CHANNEL_515_F4,
|
AS7343_CHANNEL_405_F1, AS7343_CHANNEL_425_F2, AS7343_CHANNEL_450_FZ, AS7343_CHANNEL_475_F3, AS7343_CHANNEL_515_F4,
|
||||||
AS7343_CHANNEL_555_FY, AS7343_CHANNEL_550_F5, AS7343_CHANNEL_600_FXL, AS7343_CHANNEL_640_F6, AS7343_CHANNEL_690_F7,
|
AS7343_CHANNEL_555_FY, AS7343_CHANNEL_550_F5, AS7343_CHANNEL_600_FXL, AS7343_CHANNEL_640_F6, AS7343_CHANNEL_690_F7,
|
||||||
AS7343_CHANNEL_745_F8, AS7343_CHANNEL_855_NIR, AS7343_CHANNEL_CLEAR};
|
AS7343_CHANNEL_745_F8, AS7343_CHANNEL_855_NIR, AS7343_CHANNEL_CLEAR};
|
||||||
|
|
||||||
|
// pimoroni
|
||||||
|
static constexpr float CHANNEL_COMPENSATION_GAIN[NUM_USEFUL_CHANNELS] = {1.84, 6.03, 4.88, 13.74, 3.37, 2.82, 6.72,
|
||||||
|
2.22, 3.17, 1.95, 12.25, 1.00, 1};
|
||||||
|
|
||||||
static constexpr float CHANNEL_SENS[NUM_USEFUL_CHANNELS] = {0.19402, 0.26647, 0.35741, 0.41753, 0.52235,
|
static constexpr float CHANNEL_SENS[NUM_USEFUL_CHANNELS] = {0.19402, 0.26647, 0.35741, 0.41753, 0.52235,
|
||||||
0.59633, 0.56242, 0.65645, 0.68882, 0.79980,
|
0.59633, 0.56242, 0.65645, 0.68882, 0.79980,
|
||||||
0.70423, 0.40366, 0.38516};
|
0.70423, 0.40366, 0.38516};
|
||||||
|
@ -34,7 +39,7 @@ static constexpr float CHANNEL_NM_WIDTH[NUM_USEFUL_CHANNELS] = {30, 22, 55, 30,
|
||||||
// Irradiation in mW/m² per basic count
|
// Irradiation in mW/m² per basic count
|
||||||
static constexpr float CHANNEL_IRRAD_MW_PER_BASIC_COUNT[NUM_USEFUL_CHANNELS] = {
|
static constexpr float CHANNEL_IRRAD_MW_PER_BASIC_COUNT[NUM_USEFUL_CHANNELS] = {
|
||||||
767.5101757, 2512.765376, 2034.308898, 5730.41039, 1404.780643, 1177.586336, 2803.31385,
|
767.5101757, 2512.765376, 2034.308898, 5730.41039, 1404.780643, 1177.586336, 2803.31385,
|
||||||
923.8726968, 1322.666667, 811.8520699, 5106.962963, 417.0131368, 4416.832833};
|
923.8726968, 1322.666667, 811.8520699, 5106.962963, 417.0131368, 78.70319635};
|
||||||
|
|
||||||
// E = h*c/lambda
|
// E = h*c/lambda
|
||||||
static constexpr float PHOTON_ENERGIES[NUM_USEFUL_CHANNELS] = {
|
static constexpr float PHOTON_ENERGIES[NUM_USEFUL_CHANNELS] = {
|
||||||
|
@ -43,19 +48,19 @@ static constexpr float PHOTON_ENERGIES[NUM_USEFUL_CHANNELS] = {
|
||||||
|
|
||||||
// static constexpr float CHANNEL_CONTRIB[NUM_USEFUL_CHANNELS] = {
|
// static constexpr float CHANNEL_CONTRIB[NUM_USEFUL_CHANNELS] = {
|
||||||
// 0.0603622, 0.0442656, 0.110664, 0.0603622, 0.0804829, 0.201207, 0.0704225, 0.160966, 0.100604, 0.110664, 0};
|
// 0.0603622, 0.0442656, 0.110664, 0.0603622, 0.0804829, 0.201207, 0.0704225, 0.160966, 0.100604, 0.110664, 0};
|
||||||
static constexpr float CHANNEL_CONTRIBUTION[NUM_USEFUL_CHANNELS] = {0.069385773,
|
static constexpr float CHANNEL_ENERGY_CONTRIBUTION[NUM_USEFUL_CHANNELS] = {0.069385773,
|
||||||
0.04848841,
|
0.04848841,
|
||||||
0.114486525,
|
0.114486525,
|
||||||
0.059160501,
|
0.059160501,
|
||||||
0.072754014,
|
0.072754014,
|
||||||
0.168776203,
|
0.168776203,
|
||||||
0.059608686,
|
0.059608686,
|
||||||
0.124894391,
|
0.124894391,
|
||||||
0.073180307,
|
0.073180307,
|
||||||
0.074665125,
|
0.074665125,
|
||||||
0.075439565,
|
0.075439565,
|
||||||
0.059160501,
|
0.059160501,
|
||||||
0};
|
0};
|
||||||
|
|
||||||
void AS7343Component::setup() {
|
void AS7343Component::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up AS7343...");
|
ESP_LOGCONFIG(TAG, "Setting up AS7343...");
|
||||||
|
@ -85,6 +90,8 @@ void AS7343Component::setup() {
|
||||||
cfg20.auto_smux = 0b11;
|
cfg20.auto_smux = 0b11;
|
||||||
this->reg((uint8_t) AS7343Registers::CFG20) = cfg20.raw;
|
this->reg((uint8_t) AS7343Registers::CFG20) = cfg20.raw;
|
||||||
|
|
||||||
|
this->direct_config_3_chain_();
|
||||||
|
|
||||||
this->setup_atime(this->atime_);
|
this->setup_atime(this->atime_);
|
||||||
this->setup_astep(this->astep_);
|
this->setup_astep(this->astep_);
|
||||||
this->setup_gain(this->gain_);
|
this->setup_gain(this->gain_);
|
||||||
|
@ -123,7 +130,12 @@ void AS7343Component::dump_config() {
|
||||||
float AS7343Component::get_setup_priority() const { return setup_priority::DATA; }
|
float AS7343Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
void AS7343Component::update() {
|
void AS7343Component::update() {
|
||||||
this->read_channels(this->channel_readings_);
|
// this->optimizer_(1000);
|
||||||
|
// delay(20);
|
||||||
|
|
||||||
|
this->enable_spectral_measurement(true);
|
||||||
|
this->read_18_channels(this->channel_readings_);
|
||||||
|
this->enable_spectral_measurement(false);
|
||||||
|
|
||||||
AS7343Gain gain = get_gain();
|
AS7343Gain gain = get_gain();
|
||||||
uint8_t atime = get_atime();
|
uint8_t atime = get_atime();
|
||||||
|
@ -132,10 +144,13 @@ void AS7343Component::update() {
|
||||||
float tint_ms = (1 + atime) * (1 + astep) * 2.78 / 1000; // us to ms
|
float tint_ms = (1 + atime) * (1 + astep) * 2.78 / 1000; // us to ms
|
||||||
float gain_x = get_gain_multiplier(gain);
|
float gain_x = get_gain_multiplier(gain);
|
||||||
|
|
||||||
|
float tint2_ms = this->get_tint_();
|
||||||
|
|
||||||
ESP_LOGD(TAG, " ,Gain , %.1f,X", gain_x);
|
ESP_LOGD(TAG, " ,Gain , %.1f,X", gain_x);
|
||||||
ESP_LOGD(TAG, " ,ATIME, %u,", atime);
|
ESP_LOGD(TAG, " ,ATIME, %u,", atime);
|
||||||
ESP_LOGD(TAG, " ,ASTEP, %u,", astep);
|
ESP_LOGD(TAG, " ,ASTEP, %u,", astep);
|
||||||
ESP_LOGD(TAG, " ,TINT , %.2f,", tint_ms);
|
ESP_LOGD(TAG, " ,TINT , %.2f,", tint_ms);
|
||||||
|
ESP_LOGD(TAG, " ,TINT2 , %.2f,", tint2_ms);
|
||||||
|
|
||||||
ESP_LOGD(TAG, ",nm, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, ", CHANNEL_NM[0],
|
ESP_LOGD(TAG, ",nm, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, ", CHANNEL_NM[0],
|
||||||
CHANNEL_NM[1], CHANNEL_NM[2], CHANNEL_NM[3], CHANNEL_NM[4], CHANNEL_NM[5], CHANNEL_NM[6], CHANNEL_NM[7],
|
CHANNEL_NM[1], CHANNEL_NM[2], CHANNEL_NM[3], CHANNEL_NM[4], CHANNEL_NM[5], CHANNEL_NM[6], CHANNEL_NM[7],
|
||||||
|
@ -169,52 +184,55 @@ void AS7343Component::update() {
|
||||||
this->ppfd_->publish_state(ppfd);
|
this->ppfd_->publish_state(ppfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (uint8_t i = 0; i < NUM_USEFUL_CHANNELS; i++) {
|
float normalized_readings[NUM_USEFUL_CHANNELS];
|
||||||
// this->channel_readings_[CHANNEL_IDX[1]] /= CHANNEL_SENS[i] * 65535;
|
for (uint8_t i = 0; i < NUM_USEFUL_CHANNELS; i++) {
|
||||||
// }
|
normalized_readings[i] = this->channel_readings_[CHANNEL_IDX[i]];
|
||||||
|
normalized_readings[i] /= CHANNEL_SENS[i];
|
||||||
|
normalized_readings[i] *= CHANNEL_SENS[0] / 655.35f;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->f1_ != nullptr) {
|
if (this->f1_ != nullptr) {
|
||||||
this->f1_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_405_F1]);
|
this->f1_->publish_state(normalized_readings[0]);
|
||||||
}
|
}
|
||||||
if (this->f2_ != nullptr) {
|
if (this->f2_ != nullptr) {
|
||||||
this->f2_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_425_F2]);
|
this->f2_->publish_state(normalized_readings[1]);
|
||||||
}
|
}
|
||||||
if (this->fz_ != nullptr) {
|
if (this->fz_ != nullptr) {
|
||||||
this->fz_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_450_FZ]);
|
this->fz_->publish_state(normalized_readings[2]);
|
||||||
}
|
}
|
||||||
if (this->f3_ != nullptr) {
|
if (this->f3_ != nullptr) {
|
||||||
this->f3_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_475_F3]);
|
this->f3_->publish_state(normalized_readings[3]);
|
||||||
}
|
}
|
||||||
if (this->f4_ != nullptr) {
|
if (this->f4_ != nullptr) {
|
||||||
this->f4_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_515_F4]);
|
this->f4_->publish_state(normalized_readings[4]);
|
||||||
}
|
}
|
||||||
if (this->fy_ != nullptr) {
|
if (this->fy_ != nullptr) {
|
||||||
this->fy_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_555_FY]);
|
this->fy_->publish_state(normalized_readings[5]);
|
||||||
}
|
}
|
||||||
if (this->f5_ != nullptr) {
|
if (this->f5_ != nullptr) {
|
||||||
this->f5_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_550_F5]);
|
this->f5_->publish_state(normalized_readings[6]);
|
||||||
}
|
}
|
||||||
if (this->fxl_ != nullptr) {
|
if (this->fxl_ != nullptr) {
|
||||||
this->fxl_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_600_FXL]);
|
this->fxl_->publish_state(normalized_readings[7]);
|
||||||
}
|
}
|
||||||
if (this->f6_ != nullptr) {
|
if (this->f6_ != nullptr) {
|
||||||
this->f6_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_640_F6]);
|
this->f6_->publish_state(normalized_readings[8]);
|
||||||
}
|
}
|
||||||
if (this->f7_ != nullptr) {
|
if (this->f7_ != nullptr) {
|
||||||
this->f7_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_690_F7]);
|
this->f7_->publish_state(normalized_readings[9]);
|
||||||
}
|
}
|
||||||
if (this->f8_ != nullptr) {
|
if (this->f8_ != nullptr) {
|
||||||
this->f8_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_745_F8]);
|
this->f8_->publish_state(normalized_readings[10]);
|
||||||
}
|
}
|
||||||
if (this->nir_ != nullptr) {
|
if (this->nir_ != nullptr) {
|
||||||
this->nir_->publish_state(this->channel_basic_readings_[AS7343_CHANNEL_855_NIR]);
|
this->nir_->publish_state(normalized_readings[11]);
|
||||||
}
|
|
||||||
if (this->clear_ != nullptr) {
|
|
||||||
float clear = (this->channel_readings_[AS7343_CHANNEL_CLEAR] + this->channel_readings_[AS7343_CHANNEL_CLEAR_0] +
|
|
||||||
this->channel_readings_[AS7343_CHANNEL_CLEAR_1]) /
|
|
||||||
3;
|
|
||||||
this->clear_->publish_state(clear);
|
|
||||||
}
|
}
|
||||||
|
// if (this->clear_ != nullptr) {
|
||||||
|
// float clear = (this->channel_readings_[AS7343_CHANNEL_CLEAR] + this->channel_readings_[AS7343_CHANNEL_CLEAR_0] +
|
||||||
|
// this->channel_readings_[AS7343_CHANNEL_CLEAR_1]) /
|
||||||
|
// 3;
|
||||||
|
// this->clear_->publish_state(clear);
|
||||||
|
// }
|
||||||
if (this->saturated_ != nullptr) {
|
if (this->saturated_ != nullptr) {
|
||||||
this->saturated_->publish_state(this->readings_saturated_);
|
this->saturated_->publish_state(this->readings_saturated_);
|
||||||
}
|
}
|
||||||
|
@ -242,31 +260,34 @@ float AS7343Component::get_gain_multiplier(AS7343Gain gain) {
|
||||||
float gainx = ((uint16_t) 1 << (uint8_t) gain);
|
float gainx = ((uint16_t) 1 << (uint8_t) gain);
|
||||||
return gainx / 2;
|
return gainx / 2;
|
||||||
}
|
}
|
||||||
void AS7343Component::set_gain(esphome::optional<unsigned int> g) {
|
|
||||||
if (g.has_value()) {
|
bool AS7343Component::setup_gain(AS7343Gain gain) {
|
||||||
this->set_gain(g.value());
|
ESP_LOGD(TAG, "Setup gain %u", (uint8_t) gain);
|
||||||
}
|
return this->write_byte((uint8_t) AS7343Registers::CFG1, gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AS7343Component::setup_gain(AS7343Gain gain) { return this->write_byte((uint8_t) AS7343Registers::CFG1, gain); }
|
bool AS7343Component::setup_atime(uint8_t atime) {
|
||||||
|
ESP_LOGD(TAG, "Setup atime %u", atime);
|
||||||
bool AS7343Component::setup_atime(uint8_t atime) { return this->write_byte((uint8_t) AS7343Registers::ATIME, atime); }
|
return this->write_byte((uint8_t) AS7343Registers::ATIME, atime);
|
||||||
|
}
|
||||||
|
|
||||||
bool AS7343Component::setup_astep(uint16_t astep) {
|
bool AS7343Component::setup_astep(uint16_t astep) {
|
||||||
|
ESP_LOGD(TAG, "Setup astep %u", astep);
|
||||||
return this->write_byte_16((uint8_t) AS7343Registers::ASTEP_LSB, swap_bytes(astep));
|
return this->write_byte_16((uint8_t) AS7343Registers::ASTEP_LSB, swap_bytes(astep));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AS7343Component::change_gain(AS7343Gain gain) {
|
bool AS7343Component::change_gain(AS7343Gain gain) {
|
||||||
|
this->gain_ = gain;
|
||||||
this->enable_spectral_measurement(false);
|
this->enable_spectral_measurement(false);
|
||||||
return this->write_byte((uint8_t) AS7343Registers::CFG1, gain);
|
return this->write_byte((uint8_t) AS7343Registers::CFG1, gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
float AS7343Component::calculate_ppfd(float tint_ms, float gain_x, AS7343Gain gain) {
|
float AS7343Component::calculate_ppfd(float tint_ms, float gain_x, AS7343Gain gain) {
|
||||||
float par = 0;
|
float pfd = 0;
|
||||||
float bc[NUM_USEFUL_CHANNELS] = {0};
|
float bc[NUM_USEFUL_CHANNELS] = {0};
|
||||||
float bcc[NUM_USEFUL_CHANNELS] = {0};
|
float bcc[NUM_USEFUL_CHANNELS] = {0};
|
||||||
|
|
||||||
for (uint8_t i = 0; i < NUM_USEFUL_CHANNELS; i++) {
|
for (uint8_t i = 0; i < NUM_USEFUL_CHANNELS - 1; i++) {
|
||||||
float basic_count = this->channel_readings_[CHANNEL_IDX[i]] / (gain_x * tint_ms);
|
float basic_count = this->channel_readings_[CHANNEL_IDX[i]] / (gain_x * tint_ms);
|
||||||
bc[i] = basic_count * AS7343_GAIN_CORRECTION[(uint8_t) gain][i];
|
bc[i] = basic_count * AS7343_GAIN_CORRECTION[(uint8_t) gain][i];
|
||||||
bcc[i] = basic_count / CHANNEL_SENS[i];
|
bcc[i] = basic_count / CHANNEL_SENS[i];
|
||||||
|
@ -275,35 +296,56 @@ float AS7343Component::calculate_ppfd(float tint_ms, float gain_x, AS7343Gain ga
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float watts = (basic_count - OFFSETS[i]) * CHANNEL_IRRAD_MW_PER_BASIC_COUNT[i] / 1000;
|
// float irradiance_in_w_per_m2 = basic_count * CHANNEL_IRRAD_MW_PER_BASIC_COUNT[i] /1000 ;
|
||||||
|
|
||||||
// https://www.berthold.com/en/bioanalytic/knowledge/faq/irradiance-to-photon-flux/
|
float irradiance_in_w_per_m2 = basic_count * CHANNEL_IRRAD_MW_PER_BASIC_COUNT[i] / 10000;
|
||||||
float photon_flux = watts * CHANNEL_NM[i] * 0.836e-2;
|
// probably is it not mW/m2 but uW/cm2!!!! so try divide by 10k not 1000
|
||||||
photon_flux *= CHANNEL_CONTRIBUTION[i];
|
// 1 W/m2 = 100 uW/cm2
|
||||||
par += photon_flux;
|
|
||||||
|
// // https://www.berthold.com/en/bioanalytic/knowledge/faq/irradiance-to-photon-flux/
|
||||||
|
// float photon_flux = watts * CHANNEL_NM[i] * 0.836e-2;
|
||||||
|
// photon_flux *= CHANNEL_ENERGY_CONTRIBUTION[i];
|
||||||
|
|
||||||
|
irradiance_in_w_per_m2 *= CHANNEL_ENERGY_CONTRIBUTION[i];
|
||||||
|
|
||||||
|
float photon_count = irradiance_in_w_per_m2 / PHOTON_ENERGIES[i];
|
||||||
|
float pfd_in_micromols = 1e6f * photon_count / 6.02214179e23f;
|
||||||
|
|
||||||
|
pfd += pfd_in_micromols;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, ",basic_counts, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", bc[0], bc[1], bc[2], bc[3], bc[4],
|
ESP_LOGD(TAG, ",basic_counts, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", bc[0], bc[1], bc[2], bc[3], bc[4],
|
||||||
bc[5], bc[6], bc[7], bc[8], bc[9], bc[10], bc[11]);
|
bc[5], bc[6], bc[7], bc[8], bc[9], bc[10], bc[11]);
|
||||||
ESP_LOGD(TAG, ",basic_counts_sens_corrected, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", bcc[0], bcc[1], bcc[2],
|
ESP_LOGD(TAG, ",basic_counts_sens_corrected, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", bcc[0], bcc[1], bcc[2],
|
||||||
bcc[3], bcc[4], bcc[5], bcc[6], bcc[7], bcc[8], bcc[9], bcc[10], bcc[11]);
|
bcc[3], bcc[4], bcc[5], bcc[6], bcc[7], bcc[8], bcc[9], bcc[10], bcc[11]);
|
||||||
return par;
|
return pfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AS7343Component::calculate_irradiance(float tint_ms, float gain_x, float &irradiance, float &lux,
|
void AS7343Component::calculate_irradiance(float tint_ms, float gain_x, float &irradiance_in_w_per_m2, float &lux,
|
||||||
AS7343Gain gain) {
|
AS7343Gain gain) {
|
||||||
float irr_band;
|
float irr_band;
|
||||||
for (uint8_t i = 0; i < NUM_USEFUL_CHANNELS; i++) {
|
irradiance_in_w_per_m2 = 0;
|
||||||
float basic_count = this->channel_readings_[CHANNEL_IDX[i]] / (gain_x * tint_ms);
|
for (uint8_t i = 0; i < NUM_USEFUL_CHANNELS - 1; i++) {
|
||||||
|
uint16_t reading = this->channel_readings_[CHANNEL_IDX[i]];
|
||||||
|
if (reading == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
float basic_count = reading / (gain_x * tint_ms);
|
||||||
|
ESP_LOGD(TAG, "[%2d] Basic count %f", i, basic_count);
|
||||||
basic_count *= AS7343_GAIN_CORRECTION[(uint8_t) gain][i];
|
basic_count *= AS7343_GAIN_CORRECTION[(uint8_t) gain][i];
|
||||||
irr_band = (basic_count - OFFSETS[i]) * CHANNEL_IRRAD_MW_PER_BASIC_COUNT[i] / 1000;
|
ESP_LOGD(TAG, "[%2d] gain corrected %f", i, basic_count);
|
||||||
irradiance += irr_band * CHANNEL_CONTRIBUTION[i];
|
irr_band = basic_count * CHANNEL_IRRAD_MW_PER_BASIC_COUNT[i] / 10000; // 1000 - if mW/m2, 100 if its uW/cm2
|
||||||
|
ESP_LOGD(TAG, "[%2d] irradiance %f", i, irr_band);
|
||||||
|
irradiance_in_w_per_m2 += irr_band * CHANNEL_ENERGY_CONTRIBUTION[i];
|
||||||
|
ESP_LOGD(TAG, "[%2d] band irradiance %f", i, irr_band * CHANNEL_ENERGY_CONTRIBUTION[i]);
|
||||||
}
|
}
|
||||||
lux = irradiance / 0.0079;
|
// sunlight equivalent
|
||||||
|
// 1 W/m2 = 116 ± 3 lx solar
|
||||||
|
// https://www.extrica.com/article/21667/pdf
|
||||||
|
lux = irradiance_in_w_per_m2 * 116;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AS7343Component::read_channels(uint16_t *data) {
|
bool AS7343Component::read_18_channels(uint16_t *data) {
|
||||||
this->enable_spectral_measurement(true);
|
|
||||||
this->wait_for_data();
|
this->wait_for_data();
|
||||||
|
|
||||||
AS7343RegStatus status{0};
|
AS7343RegStatus status{0};
|
||||||
|
@ -322,7 +364,7 @@ bool AS7343Component::read_channels(uint16_t *data) {
|
||||||
}
|
}
|
||||||
this->readings_saturated_ = astatus.asat_status;
|
this->readings_saturated_ = astatus.asat_status;
|
||||||
|
|
||||||
return this->read_bytes_16((uint8_t) AS7343Registers::DATA_O, this->channel_readings_, AS7343_NUM_CHANNELS);
|
return this->read_bytes_16((uint8_t) AS7343Registers::DATA_O, data, AS7343_NUM_CHANNELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AS7343Component::wait_for_data(uint16_t timeout) {
|
bool AS7343Component::wait_for_data(uint16_t timeout) {
|
||||||
|
@ -396,5 +438,300 @@ bool AS7343Component::clear_register_bit(uint8_t address, uint8_t bit_position)
|
||||||
|
|
||||||
uint16_t AS7343Component::swap_bytes(uint16_t data) { return (data >> 8) | (data << 8); }
|
uint16_t AS7343Component::swap_bytes(uint16_t data) { return (data >> 8) | (data << 8); }
|
||||||
|
|
||||||
|
void AS7343Component::setup_tint_(float TINT) {
|
||||||
|
ESP_LOGD(TAG, "Setup tint %.2f", TINT);
|
||||||
|
uint8_t ATIME = 0x00;
|
||||||
|
uint16_t ASTEP = 0x0000;
|
||||||
|
while (true) {
|
||||||
|
ASTEP = ((TINT / (double) (ATIME + 1)) * 720.0 / 2.0);
|
||||||
|
|
||||||
|
if (abs(((ATIME + 1) * (ASTEP + 1) * 2 / 720) - (uint16_t) TINT) <= 1) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ATIME += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setup_atime(ATIME);
|
||||||
|
this->setup_astep(ASTEP);
|
||||||
|
|
||||||
|
// this->write_byte((uint8_t)AS7343_ATIME, ATIME);
|
||||||
|
// this->write_byte((uint8_t)AS7343_ASTEP_LSB, (uint8_t) (ASTEP & 0xFF));
|
||||||
|
// this->write_byte((uint8_t)AS7343_ASTEP_MSB, (uint8_t) (ASTEP >> 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
float AS7343Component::get_tint_() {
|
||||||
|
uint16_t ASTEP = this->get_astep();
|
||||||
|
uint8_t ATIME = this->get_atime();
|
||||||
|
|
||||||
|
double TINT = (ASTEP + 1) * (ATIME + 1) * (2.0 / 720.0);
|
||||||
|
|
||||||
|
return TINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AS7343Component::optimizer_(float max_TINT) {
|
||||||
|
uint8_t currentGain = 12;
|
||||||
|
|
||||||
|
uint16_t FSR = 65535;
|
||||||
|
float TINT = 182.0;
|
||||||
|
// AS7343_set_TINT(handle, TINT);
|
||||||
|
this->setup_tint_(TINT);
|
||||||
|
|
||||||
|
uint16_t max_count;
|
||||||
|
uint16_t min_count;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
max_count = 0;
|
||||||
|
min_count = 0xffff;
|
||||||
|
this->setup_gain((AS7343Gain) currentGain);
|
||||||
|
|
||||||
|
uint16_t data[18];
|
||||||
|
this->enable_spectral_measurement(true);
|
||||||
|
this->read_18_channels(data);
|
||||||
|
this->enable_spectral_measurement(false);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 18; i++) {
|
||||||
|
if (i == 5 || i == 11 || i == 17) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (data[i] > max_count) {
|
||||||
|
max_count = data[i];
|
||||||
|
}
|
||||||
|
if (data[i] < min_count) {
|
||||||
|
min_count = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_count > 0xE665) {
|
||||||
|
if (currentGain == 0) {
|
||||||
|
// TODO: send optimizer failed due to saturation message
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentGain -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (min_count == 0) {
|
||||||
|
if (currentGain == 12) {
|
||||||
|
// TODO: send optimizer failed due to saturation message
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentGain += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float counts_expected = (float) max_count;
|
||||||
|
float multiplier = 0.90;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// set to loop once only, might change the algorithm in the future
|
||||||
|
max_count = 0;
|
||||||
|
float exp = (multiplier * (float) FSR - counts_expected);
|
||||||
|
if (exp < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
float temp_TINT = TINT + pow(2, log((multiplier * (float) FSR - counts_expected)) / log(2)) * (2.0 / 720.0);
|
||||||
|
|
||||||
|
if (temp_TINT > max_TINT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setup_tint_(temp_TINT);
|
||||||
|
|
||||||
|
uint16_t data[18];
|
||||||
|
this->enable_spectral_measurement(true);
|
||||||
|
this->read_18_channels(data);
|
||||||
|
this->enable_spectral_measurement(false);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 18; i++) {
|
||||||
|
if (i == 5 || i == 11 || i == 17) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (data[i] > max_count) {
|
||||||
|
max_count = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_count >= multiplier * 0xFFEE) {
|
||||||
|
multiplier = multiplier - 0.05;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
TINT = temp_TINT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// this->set_gain(currentGain);
|
||||||
|
this->setup_gain((AS7343Gain) currentGain);
|
||||||
|
this->setup_tint_(TINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AS7343Component::direct_config_3_chain_() {
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::CFG6, 0x0);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::FD_CFG0, 0xa1);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::CFG10, 0xf2);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::CFG0, 0x10);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::CFG1, 0x0c);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::CFG8, 0xc8);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::CFG20, 0x62);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::AGC_GAIN_MAX, 0x99);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::FD_TIME_1, 0x64);
|
||||||
|
this->write_byte((uint8_t) AS7343Registers::FD_TIME_2, 0x21);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x04);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x65);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x02);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x05);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x01);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x30);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x46);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x60);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x20);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x04);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x50);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x03);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x01);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x05);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x56);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x05);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x60);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x30);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x40);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x10);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x20);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
this->write_byte((uint8_t) 0xe7, 0x00);
|
||||||
|
this->write_byte((uint8_t) 0xe4, 0x66);
|
||||||
|
|
||||||
|
// this->write_byte((uint8_t)0x80, 0x11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MIN_ASTEP 1
|
||||||
|
#define MAX_ASTEP 65534
|
||||||
|
#define MIN_ITIME_US 6
|
||||||
|
#define MAX_ITIME_US 46602667
|
||||||
|
#define CONVERSION_FACTOR_MS_TO_US 1000
|
||||||
|
|
||||||
|
#define INTEGRATION_TIME_STEP_US_FACTOR 2000
|
||||||
|
#define INTEGRATION_TIME_STEP_US_DIVIDER 720
|
||||||
|
|
||||||
|
/*! Use this macro for signed 64 Bit divisions */
|
||||||
|
#define DIV64_S64(s64dividend, s64divisor) (s64dividend / s64divisor)
|
||||||
|
/*! Use this macro for unsigned 64 Bit divisions */
|
||||||
|
#define DIV64_U64(u64dividend, u64divisor) (u64dividend / u64divisor)
|
||||||
|
|
||||||
|
bool AS7343Component::as7352_set_integration_time_us(uint32_t time_us) {
|
||||||
|
bool result;
|
||||||
|
int64_t time;
|
||||||
|
uint8_t atime = 0;
|
||||||
|
uint16_t astep = 0xFFFF / 2;
|
||||||
|
int64_t astep_i64;
|
||||||
|
|
||||||
|
if (MIN_ITIME_US > time_us || MAX_ITIME_US < time_us) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
time = DIV64_S64((int64_t) time_us * INTEGRATION_TIME_STEP_US_DIVIDER, INTEGRATION_TIME_STEP_US_FACTOR);
|
||||||
|
time = DIV64_S64(time, ((int64_t) astep + 1));
|
||||||
|
time -= 1;
|
||||||
|
|
||||||
|
if (0 > time) {
|
||||||
|
atime = 0;
|
||||||
|
} else if (255 < time) {
|
||||||
|
atime = 255;
|
||||||
|
} else {
|
||||||
|
atime = (uint8_t) time;
|
||||||
|
}
|
||||||
|
|
||||||
|
astep_i64 = DIV64_S64((int64_t) time_us * INTEGRATION_TIME_STEP_US_DIVIDER * 10, INTEGRATION_TIME_STEP_US_FACTOR);
|
||||||
|
astep_i64 = DIV64_S64(astep_i64, ((int64_t) atime + 1)) + 5;
|
||||||
|
astep_i64 = DIV64_S64(astep_i64, 10);
|
||||||
|
astep_i64 -= 1;
|
||||||
|
|
||||||
|
if (MIN_ASTEP > astep_i64 || MAX_ASTEP < astep_i64) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
astep = (uint16_t) astep_i64;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "for itime %u : atime %u, astep %u", time_us, atime, astep);
|
||||||
|
|
||||||
|
this->set_astep(astep);
|
||||||
|
|
||||||
|
// if (result)
|
||||||
|
this->set_atime(atime);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace as7343
|
} // namespace as7343
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -35,7 +35,6 @@ class AS7343Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
void set_saturation_sensor(sensor::Sensor *sensor) { this->saturated_ = sensor; }
|
void set_saturation_sensor(sensor::Sensor *sensor) { this->saturated_ = sensor; }
|
||||||
|
|
||||||
void set_gain(AS7343Gain gain) { gain_ = gain; }
|
void set_gain(AS7343Gain gain) { gain_ = gain; }
|
||||||
void set_gain(esphome::optional<unsigned int> g);
|
|
||||||
void set_atime(uint8_t atime) { atime_ = atime; }
|
void set_atime(uint8_t atime) { atime_ = atime; }
|
||||||
void set_astep(uint16_t astep) { astep_ = astep; }
|
void set_astep(uint16_t astep) { astep_ = astep; }
|
||||||
|
|
||||||
|
@ -51,7 +50,7 @@ class AS7343Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
|
|
||||||
float get_gain_multiplier(AS7343Gain gain);
|
float get_gain_multiplier(AS7343Gain gain);
|
||||||
|
|
||||||
bool read_channels(uint16_t *data);
|
bool read_18_channels(uint16_t *data);
|
||||||
float calculate_ppfd(float tint_ms, float gain_x, AS7343Gain gain);
|
float calculate_ppfd(float tint_ms, float gain_x, AS7343Gain gain);
|
||||||
void calculate_irradiance(float tint_ms, float gain_x, float &irradiance, float &lux, AS7343Gain gain);
|
void calculate_irradiance(float tint_ms, float gain_x, float &irradiance, float &lux, AS7343Gain gain);
|
||||||
float calculate_spectre_();
|
float calculate_spectre_();
|
||||||
|
@ -109,6 +108,14 @@ class AS7343Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
uint8_t atime_;
|
uint8_t atime_;
|
||||||
uint16_t channel_readings_[AS7343_NUM_CHANNELS];
|
uint16_t channel_readings_[AS7343_NUM_CHANNELS];
|
||||||
float channel_basic_readings_[AS7343_NUM_CHANNELS];
|
float channel_basic_readings_[AS7343_NUM_CHANNELS];
|
||||||
|
|
||||||
|
float get_tint_();
|
||||||
|
void optimizer_(float max_TINT);
|
||||||
|
void direct_config_3_chain_();
|
||||||
|
void setup_tint_(float tint);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool as7352_set_integration_time_us(uint32_t time_us);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace as7343
|
} // namespace as7343
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -135,10 +135,9 @@ union AS7343RegAStatus {
|
||||||
AS7343Gain again_status : 4;
|
AS7343Gain again_status : 4;
|
||||||
uint8_t reserved_4_6 : 3;
|
uint8_t reserved_4_6 : 3;
|
||||||
uint8_t asat_status : 1;
|
uint8_t asat_status : 1;
|
||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace as7343
|
} // namespace as7343
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
Loading…
Reference in a new issue