9 static const char *
const TAG =
"sgp4x";
12 ESP_LOGCONFIG(TAG,
"Setting up SGP4x...");
15 uint16_t raw_serial_number[3];
16 if (!this->
get_register(SGP4X_CMD_GET_SERIAL_ID, raw_serial_number, 3, 1)) {
17 ESP_LOGE(TAG,
"Failed to read serial number");
18 this->error_code_ = SERIAL_NUMBER_IDENTIFICATION_FAILED;
22 this->
serial_number_ = (uint64_t(raw_serial_number[0]) << 24) | (uint64_t(raw_serial_number[1]) << 16) |
23 (uint64_t(raw_serial_number[2]));
27 uint16_t raw_featureset;
28 if (!this->
get_register(SGP4X_CMD_GET_FEATURESET, raw_featureset, 1)) {
29 ESP_LOGD(TAG,
"raw_featureset write_command_ failed");
34 if ((this->
featureset_ & 0x1FF) == SGP40_FEATURESET) {
39 ESP_LOGE(TAG,
"Measuring NOx requires a SGP41 sensor but a SGP40 sensor is detected");
49 if ((this->
featureset_ & 0x1FF) == SGP41_FEATURESET) {
54 ESP_LOGD(TAG,
"Product feature set failed 0x%0X , expecting 0x%0X", uint16_t(this->
featureset_ & 0x1FF),
61 ESP_LOGD(TAG,
"Product version: 0x%0X", uint16_t(this->
featureset_ & 0x1FF));
70 if (this->pref_.load(&this->voc_baselines_storage_)) {
73 ESP_LOGI(TAG,
"Loaded VOC baseline state0: 0x%04" PRIX32
", state1: 0x%04" PRIX32,
81 ESP_LOGI(TAG,
"Setting VOC baseline from save state0: 0x%04" PRIX32
", state1: 0x%04" PRIX32,
113 ESP_LOGD(TAG,
"Component requires sampling of 1Hz, setting up background sampler");
118 ESP_LOGD(TAG,
"Self-test started");
120 this->error_code_ = COMMUNICATION_FAILED;
121 ESP_LOGD(TAG,
"Self-test communication failed");
128 this->error_code_ = SELF_TEST_FAILED;
129 ESP_LOGD(TAG,
"Self-test read_data_ failed");
134 if (reply == 0xD400) {
136 ESP_LOGD(TAG,
"Self-test completed");
139 this->error_code_ = SELF_TEST_FAILED;
140 ESP_LOGD(TAG,
"Self-test failed 0x%X", reply);
144 ESP_LOGD(TAG,
"Self-test failed 0x%X", reply);
169 ESP_LOGV(TAG,
"VOC = %" PRId32
", NOx = %" PRId32, voc, nox);
180 if (this->
pref_.
save(&this->voc_baselines_storage_)) {
181 ESP_LOGI(TAG,
"Stored VOC baseline state0: 0x%04" PRIX32
" ,state1: 0x%04" PRIX32,
184 ESP_LOGW(TAG,
"Could not store VOC baselines");
199 float humidity = NAN;
200 static uint32_t nox_conditioning_start =
millis();
203 ESP_LOGD(TAG,
"Self-test not yet complete");
209 if (std::isnan(humidity) || humidity < 0.0f || humidity > 100.0f) {
217 if (std::isnan(temperature) || temperature < -40.0f || temperature > 85.0f) {
223 size_t response_words;
226 command = SGP40_CMD_MEASURE_RAW;
230 if (
millis() - nox_conditioning_start < 10000) {
231 command = SGP41_CMD_NOX_CONDITIONING;
234 command = SGP41_CMD_MEASURE_RAW;
238 uint16_t rhticks = llround((uint16_t) ((humidity * 65535) / 100));
239 uint16_t tempticks = (uint16_t) (((temperature + 45) * 65535) / 175);
247 ESP_LOGD(TAG,
"write error (%d)", this->
last_error_);
251 uint16_t raw_data[2];
253 if (!this->
read_data(raw_data, response_words)) {
255 ESP_LOGD(TAG,
"read error (%d)", this->
last_error_);
258 voc_raw = raw_data[0];
259 nox_raw = raw_data[1];
271 ESP_LOGE(TAG,
"measure gas indices failed");
276 ESP_LOGD(TAG,
"Sensor has not collected enough samples yet. (%d/%d) VOC index is: %" PRIu32, this->
samples_read_,
277 this->samples_to_stabilize_, this->
voc_index_);
305 ESP_LOGCONFIG(TAG,
"SGP4x:");
306 LOG_I2C_DEVICE(
this);
310 switch (this->error_code_) {
311 case COMMUNICATION_FAILED:
312 ESP_LOGW(TAG,
"Communication failed! Is the sensor connected?");
314 case SERIAL_NUMBER_IDENTIFICATION_FAILED:
315 ESP_LOGW(TAG,
"Get Serial number failed.");
317 case SELF_TEST_FAILED:
318 ESP_LOGW(TAG,
"Self test failed.");
322 ESP_LOGW(TAG,
"Unknown setup error!");
326 ESP_LOGCONFIG(TAG,
" Type: %s",
sgp_type_ ==
SGP41 ?
"SGP41" :
"SPG40");
327 ESP_LOGCONFIG(TAG,
" Serial number: %" PRIu64, this->
serial_number_);
328 ESP_LOGCONFIG(TAG,
" Minimum Samples: %f", GasIndexAlgorithm_INITIAL_BLACKOUT);
330 LOG_UPDATE_INTERVAL(
this);
333 ESP_LOGCONFIG(TAG,
" Compensation:");
337 ESP_LOGCONFIG(TAG,
" Compensation: No source configured");
void set_disabled_by_default(bool disabled_by_default)
sensor::Sensor * voc_sensor_
void set_interval(const std::string &name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
void set_internal(bool internal)
const char * to_string(SHTCXType type)
const float MAXIMUM_STORAGE_DIFF
void status_set_warning(const char *message="unspecified")
bool write_command(T i2c_register)
Write a command to the i2c device.
void dump_config() override
const uint32_t SHORTEST_BASELINE_STORE_INTERVAL
VOCGasIndexAlgorithm voc_algorithm_
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
optional< GasTuning > nox_tuning_params_
ESPPreferenceObject pref_
bool read_data(uint16_t *data, uint8_t len)
Read data words from i2c device.
sensor::Sensor * nox_sensor_
sensor::Sensor * humidity_sensor_
Input sensor for humidity and temperature compensation.
uint32_t IRAM_ATTR HOT millis()
optional< GasTuning > voc_tuning_params_
float state
This member variable stores the last state that has passed through all filters.
bool measure_gas_indices_(int32_t &voc, int32_t &nox)
Combined the measured gasses, temperature, and humidity to calculate the VOC Index.
void update_gas_indices()
ESPPreferences * global_preferences
void status_clear_warning()
uint32_t seconds_since_last_store_
void publish_state(float state)
Publish a new state to the front-end.
SGP4xBaselines voc_baselines_storage_
Application App
Global storage of Application pointer - only one Application can exist.
bool measure_raw_(uint16_t &voc_raw, uint16_t &nox_raw)
Return the raw gas measurement.
uint8_t samples_to_stabilize_
NOxGasIndexAlgorithm nox_algorithm_
bool get_register(uint16_t command, uint16_t *data, uint8_t len, uint8_t delay=0)
get data words from i2c register.
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
uint32_t fnv1_hash(const std::string &str)
Calculate a FNV-1 hash of str.
virtual void mark_failed()
Mark this component as failed.
i2c::ErrorCode last_error_
last error code from i2c operation
sensor::Sensor * temperature_sensor_
Implementation of SPI Controller mode.
std::string get_compilation_time() const
void IRAM_ATTR HOT delay(uint32_t ms)