diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index f3222221a2..3298a5b8db 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -29,6 +29,19 @@ static const int8_t SEN5X_INDEX_SCALE_FACTOR = 10; // static const int8_t SEN5X_MIN_INDEX_VALUE = 1 * SEN5X_INDEX_SCALE_FACTOR; // must be adjusted by the scale factor static const int16_t SEN5X_MAX_INDEX_VALUE = 500 * SEN5X_INDEX_SCALE_FACTOR; // must be adjusted by the scale factor +static const LogString *rht_accel_mode_to_string(RhtAccelerationMode mode) { + switch (mode) { + case LOW_ACCELERATION: + return LOG_STR("LOW"); + case MEDIUM_ACCELERATION: + return LOG_STR("MEDIUM"); + case HIGH_ACCELERATION: + return LOG_STR("HIGH"); + default: + return LOG_STR("UNKNOWN"); + } +} + void SEN5XComponent::setup() { // the sensor needs 1000 ms to enter the idle state this->set_timeout(1000, [this]() { @@ -50,7 +63,7 @@ void SEN5XComponent::setup() { uint32_t stop_measurement_delay = 0; // In order to query the device periodic measurement must be ceased if (raw_read_status) { - ESP_LOGD(TAG, "Sensor has data available, stopping periodic measurement"); + ESP_LOGD(TAG, "Data is available; stopping periodic measurement"); if (!this->write_command(SEN5X_CMD_STOP_MEASUREMENTS)) { ESP_LOGE(TAG, "Failed to stop measurements"); this->mark_failed(); @@ -71,7 +84,8 @@ void SEN5XComponent::setup() { this->serial_number_[0] = static_cast(uint16_t(raw_serial_number[0]) & 0xFF); this->serial_number_[1] = static_cast(raw_serial_number[0] & 0xFF); this->serial_number_[2] = static_cast(raw_serial_number[1] >> 8); - ESP_LOGD(TAG, "Serial number %02d.%02d.%02d", serial_number_[0], serial_number_[1], serial_number_[2]); + ESP_LOGV(TAG, "Serial number %02d.%02d.%02d", this->serial_number_[0], this->serial_number_[1], + this->serial_number_[2]); uint16_t raw_product_name[16]; if (!this->get_register(SEN5X_CMD_GET_PRODUCT_NAME, raw_product_name, 16, 20)) { @@ -88,45 +102,43 @@ void SEN5XComponent::setup() { // first char current_char = *current_int >> 8; if (current_char) { - product_name_.push_back(current_char); + this->product_name_.push_back(current_char); // second char current_char = *current_int & 0xFF; if (current_char) { - product_name_.push_back(current_char); + this->product_name_.push_back(current_char); } } current_int++; } while (current_char && --max); Sen5xType sen5x_type = UNKNOWN; - if (product_name_ == "SEN50") { + if (this->product_name_ == "SEN50") { sen5x_type = SEN50; } else { - if (product_name_ == "SEN54") { + if (this->product_name_ == "SEN54") { sen5x_type = SEN54; } else { - if (product_name_ == "SEN55") { + if (this->product_name_ == "SEN55") { sen5x_type = SEN55; } } - ESP_LOGD(TAG, "Productname %s", product_name_.c_str()); + ESP_LOGD(TAG, "Product name: %s", this->product_name_.c_str()); } if (this->humidity_sensor_ && sen5x_type == SEN50) { - ESP_LOGE(TAG, "For Relative humidity a SEN54 OR SEN55 is required. You are using a <%s> sensor", - this->product_name_.c_str()); + ESP_LOGE(TAG, "Relative humidity requires a SEN54 or SEN55"); this->humidity_sensor_ = nullptr; // mark as not used } if (this->temperature_sensor_ && sen5x_type == SEN50) { - ESP_LOGE(TAG, "For Temperature a SEN54 OR SEN55 is required. You are using a <%s> sensor", - this->product_name_.c_str()); + ESP_LOGE(TAG, "Temperature requires a SEN54 or SEN55"); this->temperature_sensor_ = nullptr; // mark as not used } if (this->voc_sensor_ && sen5x_type == SEN50) { - ESP_LOGE(TAG, "For VOC a SEN54 OR SEN55 is required. You are using a <%s> sensor", this->product_name_.c_str()); + ESP_LOGE(TAG, "VOC requires a SEN54 or SEN55"); this->voc_sensor_ = nullptr; // mark as not used } if (this->nox_sensor_ && sen5x_type != SEN55) { - ESP_LOGE(TAG, "For NOx a SEN55 is required. You are using a <%s> sensor", this->product_name_.c_str()); + ESP_LOGE(TAG, "NOx requires a SEN55"); this->nox_sensor_ = nullptr; // mark as not used } @@ -137,7 +149,7 @@ void SEN5XComponent::setup() { return; } this->firmware_version_ >>= 8; - ESP_LOGD(TAG, "Firmware version %d", this->firmware_version_); + ESP_LOGV(TAG, "Firmware version %d", this->firmware_version_); if (this->voc_sensor_ && this->store_baseline_) { uint32_t combined_serial = @@ -150,7 +162,7 @@ void SEN5XComponent::setup() { if (this->pref_.load(&this->voc_baselines_storage_)) { ESP_LOGI(TAG, "Loaded VOC baseline state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, voc_baselines_storage_.state1); + this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); } // Initialize storage timestamp @@ -158,13 +170,13 @@ void SEN5XComponent::setup() { if (this->voc_baselines_storage_.state0 > 0 && this->voc_baselines_storage_.state1 > 0) { ESP_LOGI(TAG, "Setting VOC baseline from save state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, voc_baselines_storage_.state1); + this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); uint16_t states[4]; - states[0] = voc_baselines_storage_.state0 >> 16; - states[1] = voc_baselines_storage_.state0 & 0xFFFF; - states[2] = voc_baselines_storage_.state1 >> 16; - states[3] = voc_baselines_storage_.state1 & 0xFFFF; + states[0] = this->voc_baselines_storage_.state0 >> 16; + states[1] = this->voc_baselines_storage_.state0 & 0xFFFF; + states[2] = this->voc_baselines_storage_.state1 >> 16; + states[3] = this->voc_baselines_storage_.state1 & 0xFFFF; if (!this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE, states, 4)) { ESP_LOGE(TAG, "Failed to set VOC baseline from saved state"); @@ -182,11 +194,11 @@ void SEN5XComponent::setup() { delay(20); uint16_t secs[2]; if (this->read_data(secs, 2)) { - auto_cleaning_interval_ = secs[0] << 16 | secs[1]; + this->auto_cleaning_interval_ = secs[0] << 16 | secs[1]; } } - if (acceleration_mode_.has_value()) { - result = this->write_command(SEN5X_CMD_RHT_ACCELERATION_MODE, acceleration_mode_.value()); + if (this->acceleration_mode_.has_value()) { + result = this->write_command(SEN5X_CMD_RHT_ACCELERATION_MODE, this->acceleration_mode_.value()); } else { result = this->write_command(SEN5X_CMD_RHT_ACCELERATION_MODE); } @@ -197,7 +209,7 @@ void SEN5XComponent::setup() { return; } delay(20); - if (!acceleration_mode_.has_value()) { + if (!this->acceleration_mode_.has_value()) { uint16_t mode; if (this->read_data(mode)) { this->acceleration_mode_ = RhtAccelerationMode(mode); @@ -227,19 +239,18 @@ void SEN5XComponent::setup() { } if (!this->write_command(cmd)) { - ESP_LOGE(TAG, "Error starting continuous measurements."); + ESP_LOGE(TAG, "Error starting continuous measurements"); this->error_code_ = MEASUREMENT_INIT_FAILED; this->mark_failed(); return; } - initialized_ = true; - ESP_LOGD(TAG, "Sensor initialized"); + this->initialized_ = true; }); }); } void SEN5XComponent::dump_config() { - ESP_LOGCONFIG(TAG, "sen5x:"); + ESP_LOGCONFIG(TAG, "SEN5X:"); LOG_I2C_DEVICE(this); if (this->is_failed()) { switch (this->error_code_) { @@ -247,16 +258,16 @@ void SEN5XComponent::dump_config() { ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL); break; case MEASUREMENT_INIT_FAILED: - ESP_LOGW(TAG, "Measurement Initialization failed"); + ESP_LOGW(TAG, "Measurement initialization failed"); break; case SERIAL_NUMBER_IDENTIFICATION_FAILED: - ESP_LOGW(TAG, "Unable to read sensor serial id"); + ESP_LOGW(TAG, "Unable to read serial ID"); break; case PRODUCT_NAME_FAILED: ESP_LOGW(TAG, "Unable to read product name"); break; case FIRMWARE_FAILED: - ESP_LOGW(TAG, "Unable to read sensor firmware version"); + ESP_LOGW(TAG, "Unable to read firmware version"); break; default: ESP_LOGW(TAG, "Unknown setup error"); @@ -264,26 +275,17 @@ void SEN5XComponent::dump_config() { } } ESP_LOGCONFIG(TAG, - " Productname: %s\n" + " Product name: %s\n" " Firmware version: %d\n" " Serial number %02d.%02d.%02d", - this->product_name_.c_str(), this->firmware_version_, serial_number_[0], serial_number_[1], - serial_number_[2]); + this->product_name_.c_str(), this->firmware_version_, this->serial_number_[0], this->serial_number_[1], + this->serial_number_[2]); if (this->auto_cleaning_interval_.has_value()) { - ESP_LOGCONFIG(TAG, " Auto cleaning interval %" PRId32 " seconds", auto_cleaning_interval_.value()); + ESP_LOGCONFIG(TAG, " Auto cleaning interval: %" PRId32 "s", this->auto_cleaning_interval_.value()); } if (this->acceleration_mode_.has_value()) { - switch (this->acceleration_mode_.value()) { - case LOW_ACCELERATION: - ESP_LOGCONFIG(TAG, " Low RH/T acceleration mode"); - break; - case MEDIUM_ACCELERATION: - ESP_LOGCONFIG(TAG, " Medium RH/T acceleration mode"); - break; - case HIGH_ACCELERATION: - ESP_LOGCONFIG(TAG, " High RH/T acceleration mode"); - break; - } + ESP_LOGCONFIG(TAG, " RH/T acceleration mode: %s", + LOG_STR_ARG(rht_accel_mode_to_string(this->acceleration_mode_.value()))); } LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "PM 1.0", this->pm_1_0_sensor_); @@ -297,7 +299,7 @@ void SEN5XComponent::dump_config() { } void SEN5XComponent::update() { - if (!initialized_) { + if (!this->initialized_) { return; } @@ -320,8 +322,8 @@ void SEN5XComponent::update() { this->voc_baselines_storage_.state1 = state1; if (this->pref_.save(&this->voc_baselines_storage_)) { - ESP_LOGI(TAG, "Stored VOC baseline state0: 0x%04" PRIX32 " ,state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, voc_baselines_storage_.state1); + ESP_LOGI(TAG, "Stored VOC baseline state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, + this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); } else { ESP_LOGW(TAG, "Could not store VOC baselines"); } @@ -333,7 +335,7 @@ void SEN5XComponent::update() { if (!this->write_command(SEN5X_CMD_READ_MEASUREMENT)) { this->status_set_warning(); - ESP_LOGD(TAG, "write error read measurement (%d)", this->last_error_); + ESP_LOGD(TAG, "Write error: read measurement (%d)", this->last_error_); return; } this->set_timeout(20, [this]() { @@ -341,7 +343,7 @@ void SEN5XComponent::update() { if (!this->read_data(measurements, 8)) { this->status_set_warning(); - ESP_LOGD(TAG, "read data error (%d)", this->last_error_); + ESP_LOGD(TAG, "Read data error (%d)", this->last_error_); return; } @@ -413,7 +415,7 @@ bool SEN5XComponent::write_tuning_parameters_(uint16_t i2c_command, const GasTun params[5] = tuning.gain_factor; auto result = write_command(i2c_command, params, 6); if (!result) { - ESP_LOGE(TAG, "set tuning parameters failed. i2c command=%0xX, err=%d", i2c_command, this->last_error_); + ESP_LOGE(TAG, "Set tuning parameters failed (command=%0xX, err=%d)", i2c_command, this->last_error_); } return result; } @@ -424,7 +426,7 @@ bool SEN5XComponent::write_temperature_compensation_(const TemperatureCompensati params[1] = compensation.normalized_offset_slope; params[2] = compensation.time_constant; if (!write_command(SEN5X_CMD_TEMPERATURE_COMPENSATION, params, 3)) { - ESP_LOGE(TAG, "set temperature_compensation failed. Err=%d", this->last_error_); + ESP_LOGE(TAG, "Set temperature_compensation failed (%d)", this->last_error_); return false; } return true; @@ -433,7 +435,7 @@ bool SEN5XComponent::write_temperature_compensation_(const TemperatureCompensati bool SEN5XComponent::start_fan_cleaning() { if (!write_command(SEN5X_CMD_START_CLEANING_FAN)) { this->status_set_warning(); - ESP_LOGE(TAG, "write error start fan (%d)", this->last_error_); + ESP_LOGE(TAG, "Start fan cleaning failed (%d)", this->last_error_); return false; } else { ESP_LOGD(TAG, "Fan auto clean started"); diff --git a/esphome/components/sen5x/sen5x.h b/esphome/components/sen5x/sen5x.h index 0fa31605e6..9e5b6bf231 100644 --- a/esphome/components/sen5x/sen5x.h +++ b/esphome/components/sen5x/sen5x.h @@ -9,7 +9,7 @@ namespace esphome { namespace sen5x { -enum ERRORCODE { +enum ERRORCODE : uint8_t { COMMUNICATION_FAILED, SERIAL_NUMBER_IDENTIFICATION_FAILED, MEASUREMENT_INIT_FAILED, @@ -18,19 +18,17 @@ enum ERRORCODE { UNKNOWN }; -// Shortest time interval of 3H for storing baseline values. -// Prevents wear of the flash because of too many write operations -const uint32_t SHORTEST_BASELINE_STORE_INTERVAL = 10800; -// Store anyway if the baseline difference exceeds the max storage diff value -const uint32_t MAXIMUM_STORAGE_DIFF = 50; +enum RhtAccelerationMode : uint16_t { + LOW_ACCELERATION = 0, + MEDIUM_ACCELERATION = 1, + HIGH_ACCELERATION = 2, +}; struct Sen5xBaselines { int32_t state0; int32_t state1; } PACKED; // NOLINT -enum RhtAccelerationMode : uint16_t { LOW_ACCELERATION = 0, MEDIUM_ACCELERATION = 1, HIGH_ACCELERATION = 2 }; - struct GasTuning { uint16_t index_offset; uint16_t learning_time_offset_hours; @@ -46,6 +44,12 @@ struct TemperatureCompensation { uint16_t time_constant; }; +// Shortest time interval of 3H for storing baseline values. +// Prevents wear of the flash because of too many write operations +static const uint32_t SHORTEST_BASELINE_STORE_INTERVAL = 10800; +// Store anyway if the baseline difference exceeds the max storage diff value +static const uint32_t MAXIMUM_STORAGE_DIFF = 50; + class SEN5XComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice { public: void setup() override; @@ -102,8 +106,14 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri protected: bool write_tuning_parameters_(uint16_t i2c_command, const GasTuning &tuning); bool write_temperature_compensation_(const TemperatureCompensation &compensation); + + uint32_t seconds_since_last_store_; + uint16_t firmware_version_; ERRORCODE error_code_; + uint8_t serial_number_[4]; bool initialized_{false}; + bool store_baseline_; + sensor::Sensor *pm_1_0_sensor_{nullptr}; sensor::Sensor *pm_2_5_sensor_{nullptr}; sensor::Sensor *pm_4_0_sensor_{nullptr}; @@ -115,18 +125,14 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri // SEN55 only sensor::Sensor *nox_sensor_{nullptr}; - std::string product_name_; - uint8_t serial_number_[4]; - uint16_t firmware_version_; - Sen5xBaselines voc_baselines_storage_; - bool store_baseline_; - uint32_t seconds_since_last_store_; - ESPPreferenceObject pref_; optional acceleration_mode_; optional auto_cleaning_interval_; optional voc_tuning_params_; optional nox_tuning_params_; optional temperature_compensation_; + ESPPreferenceObject pref_; + std::string product_name_; + Sen5xBaselines voc_baselines_storage_; }; } // namespace sen5x diff --git a/esphome/components/sensirion_common/i2c_sensirion.cpp b/esphome/components/sensirion_common/i2c_sensirion.cpp index f71b3c14cb..22c4b0e53c 100644 --- a/esphome/components/sensirion_common/i2c_sensirion.cpp +++ b/esphome/components/sensirion_common/i2c_sensirion.cpp @@ -11,21 +11,22 @@ static const char *const TAG = "sensirion_i2c"; // To avoid memory allocations for small writes a stack buffer is used static const size_t BUFFER_STACK_SIZE = 16; -bool SensirionI2CDevice::read_data(uint16_t *data, uint8_t len) { +bool SensirionI2CDevice::read_data(uint16_t *data, const uint8_t len) { const uint8_t num_bytes = len * 3; - std::vector buf(num_bytes); + uint8_t buf[num_bytes]; - last_error_ = this->read(buf.data(), num_bytes); - if (last_error_ != i2c::ERROR_OK) { + this->last_error_ = this->read(buf, num_bytes); + if (this->last_error_ != i2c::ERROR_OK) { return false; } for (uint8_t i = 0; i < len; i++) { const uint8_t j = 3 * i; - uint8_t crc = sht_crc_(buf[j], buf[j + 1]); + // Use MSB first since Sensirion devices use CRC-8 with MSB first + uint8_t crc = crc8(&buf[j], 2, 0xFF, CRC_POLYNOMIAL, true); if (crc != buf[j + 2]) { - ESP_LOGE(TAG, "CRC8 Checksum invalid at pos %d! 0x%02X != 0x%02X", i, buf[j + 2], crc); - last_error_ = i2c::ERROR_CRC; + ESP_LOGE(TAG, "CRC invalid @ %d! 0x%02X != 0x%02X", i, buf[j + 2], crc); + this->last_error_ = i2c::ERROR_CRC; return false; } data[i] = encode_uint16(buf[j], buf[j + 1]); @@ -34,10 +35,10 @@ bool SensirionI2CDevice::read_data(uint16_t *data, uint8_t len) { } /*** * write command with parameters and insert crc - * use stack array for less than 4 parameters. Most sensirion i2c commands have less parameters + * use stack array for less than 4 parameters. Most Sensirion I2C commands have less parameters */ bool SensirionI2CDevice::write_command_(uint16_t command, CommandLen command_len, const uint16_t *data, - uint8_t data_len) { + const uint8_t data_len) { uint8_t temp_stack[BUFFER_STACK_SIZE]; std::unique_ptr temp_heap; uint8_t *temp; @@ -74,56 +75,26 @@ bool SensirionI2CDevice::write_command_(uint16_t command, CommandLen command_len temp[raw_idx++] = data[i] & 0xFF; temp[raw_idx++] = data[i] >> 8; #endif - temp[raw_idx++] = sht_crc_(data[i]); + // Use MSB first since Sensirion devices use CRC-8 with MSB first + temp[raw_idx++] = crc8(&temp[raw_idx - 2], 2, 0xFF, CRC_POLYNOMIAL, true); } - last_error_ = this->write(temp, raw_idx); - return last_error_ == i2c::ERROR_OK; + this->last_error_ = this->write(temp, raw_idx); + return this->last_error_ == i2c::ERROR_OK; } -bool SensirionI2CDevice::get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, uint8_t len, - uint8_t delay_ms) { +bool SensirionI2CDevice::get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, const uint8_t len, + const uint8_t delay_ms) { if (!this->write_command_(reg, command_len, nullptr, 0)) { - ESP_LOGE(TAG, "Failed to write i2c register=0x%X (%d) err=%d,", reg, command_len, this->last_error_); + ESP_LOGE(TAG, "Write failed: reg=0x%X (%d) err=%d,", reg, command_len, this->last_error_); return false; } delay(delay_ms); bool result = this->read_data(data, len); if (!result) { - ESP_LOGE(TAG, "Failed to read data from register=0x%X err=%d,", reg, this->last_error_); + ESP_LOGE(TAG, "Read failed: reg=0x%X err=%d,", reg, this->last_error_); } return result; } -// The 8-bit CRC checksum is transmitted after each data word -uint8_t SensirionI2CDevice::sht_crc_(uint16_t data) { - uint8_t bit; - uint8_t crc = 0xFF; -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - crc ^= data >> 8; -#else - crc ^= data & 0xFF; -#endif - for (bit = 8; bit > 0; --bit) { - if (crc & 0x80) { - crc = (crc << 1) ^ crc_polynomial_; - } else { - crc = (crc << 1); - } - } -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - crc ^= data & 0xFF; -#else - crc ^= data >> 8; -#endif - for (bit = 8; bit > 0; --bit) { - if (crc & 0x80) { - crc = (crc << 1) ^ crc_polynomial_; - } else { - crc = (crc << 1); - } - } - return crc; -} - } // namespace sensirion_common } // namespace esphome diff --git a/esphome/components/sensirion_common/i2c_sensirion.h b/esphome/components/sensirion_common/i2c_sensirion.h index e141591525..f3eb3761f6 100644 --- a/esphome/components/sensirion_common/i2c_sensirion.h +++ b/esphome/components/sensirion_common/i2c_sensirion.h @@ -8,10 +8,10 @@ namespace esphome { namespace sensirion_common { /** - * Implementation of a i2c functions for Sensirion sensors - * Sensirion data requires crc checking. + * Implementation of I2C functions for Sensirion sensors + * Sensirion data requires CRC checking. * Each 16 bit word is/must be followed 8 bit CRC code - * (Applies to read and write - note the i2c command code doesn't need a CRC) + * (Applies to read and write - note the I2C command code doesn't need a CRC) * Format: * | 16 Bit Command Code | 16 bit Data word 1 | CRC of DW 1 | 16 bit Data word 1 | CRC of DW 2 | .. */ @@ -21,79 +21,79 @@ class SensirionI2CDevice : public i2c::I2CDevice { public: enum CommandLen : uint8_t { ADDR_8_BIT = 1, ADDR_16_BIT = 2 }; - /** Read data words from i2c device. - * handles crc check used by Sensirion sensors + /** Read data words from I2C device. + * handles CRC check used by Sensirion sensors * @param data pointer to raw result * @param len number of words to read * @return true if reading succeeded */ bool read_data(uint16_t *data, uint8_t len); - /** Read 1 data word from i2c device. + /** Read 1 data word from I2C device. * @param data reference to raw result * @return true if reading succeeded */ bool read_data(uint16_t &data) { return this->read_data(&data, 1); } - /** get data words from i2c register. - * handles crc check used by Sensirion sensors - * @param i2c register + /** get data words from I2C register. + * handles CRC check used by Sensirion sensors + * @param I2C register * @param data pointer to raw result * @param len number of words to read - * @param delay milliseconds to to wait between sending the i2c command and reading the result + * @param delay milliseconds to to wait between sending the I2C command and reading the result * @return true if reading succeeded */ bool get_register(uint16_t command, uint16_t *data, uint8_t len, uint8_t delay = 0) { return get_register_(command, ADDR_16_BIT, data, len, delay); } - /** Read 1 data word from 16 bit i2c register. - * @param i2c register + /** Read 1 data word from 16 bit I2C register. + * @param I2C register * @param data reference to raw result - * @param delay milliseconds to to wait between sending the i2c command and reading the result + * @param delay milliseconds to to wait between sending the I2C command and reading the result * @return true if reading succeeded */ bool get_register(uint16_t i2c_register, uint16_t &data, uint8_t delay = 0) { return this->get_register_(i2c_register, ADDR_16_BIT, &data, 1, delay); } - /** get data words from i2c register. - * handles crc check used by Sensirion sensors - * @param i2c register + /** get data words from I2C register. + * handles CRC check used by Sensirion sensors + * @param I2C register * @param data pointer to raw result * @param len number of words to read - * @param delay milliseconds to to wait between sending the i2c command and reading the result + * @param delay milliseconds to to wait between sending the I2C command and reading the result * @return true if reading succeeded */ bool get_8bit_register(uint8_t i2c_register, uint16_t *data, uint8_t len, uint8_t delay = 0) { return get_register_(i2c_register, ADDR_8_BIT, data, len, delay); } - /** Read 1 data word from 8 bit i2c register. - * @param i2c register + /** Read 1 data word from 8 bit I2C register. + * @param I2C register * @param data reference to raw result - * @param delay milliseconds to to wait between sending the i2c command and reading the result + * @param delay milliseconds to to wait between sending the I2C command and reading the result * @return true if reading succeeded */ bool get_8bit_register(uint8_t i2c_register, uint16_t &data, uint8_t delay = 0) { return this->get_register_(i2c_register, ADDR_8_BIT, &data, 1, delay); } - /** Write a command to the i2c device. - * @param command i2c command to send + /** Write a command to the I2C device. + * @param command I2C command to send * @return true if reading succeeded */ template bool write_command(T i2c_register) { return write_command(i2c_register, nullptr, 0); } - /** Write a command and one data word to the i2c device . - * @param command i2c command to send - * @param data argument for the i2c command + /** Write a command and one data word to the I2C device . + * @param command I2C command to send + * @param data argument for the I2C command * @return true if reading succeeded */ template bool write_command(T i2c_register, uint16_t data) { return write_command(i2c_register, &data, 1); } /** Write a command with arguments as words - * @param i2c_register i2c command to send - an be uint8_t or uint16_t - * @param data vector arguments for the i2c command + * @param i2c_register I2C command to send - an be uint8_t or uint16_t + * @param data vector arguments for the I2C command * @return true if reading succeeded */ template bool write_command(T i2c_register, const std::vector &data) { @@ -101,57 +101,39 @@ class SensirionI2CDevice : public i2c::I2CDevice { } /** Write a command with arguments as words - * @param i2c_register i2c command to send - an be uint8_t or uint16_t - * @param data arguments for the i2c command + * @param i2c_register I2C command to send - an be uint8_t or uint16_t + * @param data arguments for the I2C command * @param len number of arguments (words) * @return true if reading succeeded */ template bool write_command(T i2c_register, const uint16_t *data, uint8_t len) { // limit to 8 or 16 bit only - static_assert(sizeof(i2c_register) == 1 || sizeof(i2c_register) == 2, - "only 8 or 16 bit command types are supported."); + static_assert(sizeof(i2c_register) == 1 || sizeof(i2c_register) == 2, "Only 8 or 16 bit command types supported"); return write_command_(i2c_register, CommandLen(sizeof(T)), data, len); } protected: - uint8_t crc_polynomial_{0x31u}; // default for sensirion /** Write a command with arguments as words - * @param command i2c command to send can be uint8_t or uint16_t + * @param command I2C command to send can be uint8_t or uint16_t * @param command_len either 1 for short 8 bit command or 2 for 16 bit command codes - * @param data arguments for the i2c command + * @param data arguments for the I2C command * @param data_len number of arguments (words) * @return true if reading succeeded */ bool write_command_(uint16_t command, CommandLen command_len, const uint16_t *data, uint8_t data_len); - /** get data words from i2c register. - * handles crc check used by Sensirion sensors - * @param i2c register + /** get data words from I2C register. + * handles CRC check used by Sensirion sensors + * @param I2C register * @param command_len either 1 for short 8 bit command or 2 for 16 bit command codes * @param data pointer to raw result * @param len number of words to read - * @param delay milliseconds to to wait between sending the i2c command and reading the result + * @param delay milliseconds to to wait between sending the I2C command and reading the result * @return true if reading succeeded */ bool get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, uint8_t len, uint8_t delay); - /** 8-bit CRC checksum that is transmitted after each data word for read and write operation - * @param command i2c command to send - * @param data data word for which the crc8 checksum is calculated - * @param len number of arguments (words) - * @return 8 Bit CRC - */ - uint8_t sht_crc_(uint16_t data); - - /** 8-bit CRC checksum that is transmitted after each data word for read and write operation - * @param command i2c command to send - * @param data1 high byte of data word - * @param data2 low byte of data word - * @return 8 Bit CRC - */ - uint8_t sht_crc_(uint8_t data1, uint8_t data2) { return sht_crc_(encode_uint16(data1, data2)); } - - /** last error code from i2c operation + /** last error code from I2C operation */ i2c::ErrorCode last_error_; };