Skip to content

Commit

Permalink
Sgp40 fix (#2462)
Browse files Browse the repository at this point in the history
* Sample from SGP40 sensor at the appropriate interval

The spg40 sensor must be sampled at 1Hz for the VOC index algorithm
to work correctly. This commit introduces a on device timer to
sample correctly seperately from updating the public state of the
component.

* Add missing configuration values for SGP40

The SGP40 component was not printing all of it's configuration in
dump_config, add in the missing store_baseline value.

* Address review comments

* Format according to clang-tidy

* Attempt 2 at clang tidy
  • Loading branch information
natelust committed Oct 10, 2021
1 parent c092d92 commit 92b85f9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
35 changes: 28 additions & 7 deletions esphome/components/sgp40/sgp40.cpp
Expand Up @@ -77,6 +77,20 @@ void SGP40Component::setup() {
}

this->self_test_();

/* The official spec for this sensor at https://docs.rs-online.com/1956/A700000007055193.pdf
indicates this sensor should be driven at 1Hz. Comments from the developers at:
https://github.com/Sensirion/embedded-sgp/issues/136 indicate the algorithm should be a bit
resilient to slight timing variations so the software timer should be accurate enough for
this.
This block starts sampling from the sensor at 1Hz, and is done seperately from the call
to the update method. This seperation is to support getting accurate measurements but
limit the amount of communication done over wifi for power consumption or to keep the
number of records reported from being overwhelming.
*/
ESP_LOGD(TAG, "Component requires sampling of 1Hz, setting up background sampler");
this->set_interval(1000, [this]() { this->update_voc_index(); });
}

void SGP40Component::self_test_() {
Expand Down Expand Up @@ -224,21 +238,26 @@ uint8_t SGP40Component::generate_crc_(const uint8_t *data, uint8_t datalen) {
return crc;
}

void SGP40Component::update() {
this->seconds_since_last_store_ += this->update_interval_ / 1000;

uint32_t voc_index = this->measure_voc_index_();
void SGP40Component::update_voc_index() {
this->seconds_since_last_store_ += 1;

this->voc_index_ = this->measure_voc_index_();
if (this->samples_read_ < this->samples_to_stabalize_) {
this->samples_read_++;
ESP_LOGD(TAG, "Sensor has not collected enough samples yet. (%d/%d) VOC index is: %u", this->samples_read_,
this->samples_to_stabalize_, voc_index);
this->samples_to_stabalize_, this->voc_index_);
return;
}
}

void SGP40Component::update() {
if (this->samples_read_ < this->samples_to_stabalize_) {
return;
}

if (voc_index != UINT16_MAX) {
if (this->voc_index_ != UINT16_MAX) {
this->status_clear_warning();
this->publish_state(voc_index);
this->publish_state(this->voc_index_);
} else {
this->status_set_warning();
}
Expand All @@ -247,6 +266,8 @@ void SGP40Component::update() {
void SGP40Component::dump_config() {
ESP_LOGCONFIG(TAG, "SGP40:");
LOG_I2C_DEVICE(this);
ESP_LOGCONFIG(TAG, " store_baseline: %d", this->store_baseline_);

if (this->is_failed()) {
switch (this->error_code_) {
case COMMUNICATION_FAILED:
Expand Down
2 changes: 2 additions & 0 deletions esphome/components/sgp40/sgp40.h
Expand Up @@ -46,6 +46,7 @@ class SGP40Component : public PollingComponent, public sensor::Sensor, public i2

void setup() override;
void update() override;
void update_voc_index();
void dump_config() override;
float get_setup_priority() const override { return setup_priority::DATA; }
void set_store_baseline(bool store_baseline) { store_baseline_ = store_baseline; }
Expand All @@ -72,6 +73,7 @@ class SGP40Component : public PollingComponent, public sensor::Sensor, public i2
bool store_baseline_;
int32_t state0_;
int32_t state1_;
int32_t voc_index_ = 0;
uint8_t samples_read_ = 0;
uint8_t samples_to_stabalize_ = static_cast<int8_t>(VOC_ALGORITHM_INITIAL_BLACKOUT) * 2;

Expand Down

0 comments on commit 92b85f9

Please sign in to comment.