[scd4x] Optimize logging + minor code clean-up (#9347)

This commit is contained in:
Keith Burzinski 2025-07-06 08:37:50 -05:00 committed by GitHub
parent 4673a5b48c
commit e061b6dc55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 58 deletions

View File

@ -7,6 +7,8 @@ namespace scd4x {
static const char *const TAG = "scd4x";
static const uint16_t SCD41_ID = 0x1408;
static const uint16_t SCD40_ID = 0x440;
static const uint16_t SCD4X_CMD_GET_SERIAL_NUMBER = 0x3682;
static const uint16_t SCD4X_CMD_TEMPERATURE_OFFSET = 0x241d;
static const uint16_t SCD4X_CMD_ALTITUDE_COMPENSATION = 0x2427;
@ -23,8 +25,6 @@ static const uint16_t SCD4X_CMD_STOP_MEASUREMENTS = 0x3f86;
static const uint16_t SCD4X_CMD_FACTORY_RESET = 0x3632;
static const uint16_t SCD4X_CMD_GET_FEATURESET = 0x202f;
static const float SCD4X_TEMPERATURE_OFFSET_MULTIPLIER = (1 << 16) / 175.0f;
static const uint16_t SCD41_ID = 0x1408;
static const uint16_t SCD40_ID = 0x440;
void SCD4XComponent::setup() {
ESP_LOGCONFIG(TAG, "Running setup");
@ -51,47 +51,66 @@ void SCD4XComponent::setup() {
if (!this->write_command(SCD4X_CMD_TEMPERATURE_OFFSET,
(uint16_t) (temperature_offset_ * SCD4X_TEMPERATURE_OFFSET_MULTIPLIER))) {
ESP_LOGE(TAG, "Error setting temperature offset.");
ESP_LOGE(TAG, "Error setting temperature offset");
this->error_code_ = MEASUREMENT_INIT_FAILED;
this->mark_failed();
return;
}
// If pressure compensation available use it
// else use altitude
if (ambient_pressure_compensation_) {
if (!this->update_ambient_pressure_compensation_(ambient_pressure_)) {
ESP_LOGE(TAG, "Error setting ambient pressure compensation.");
// If pressure compensation available use it, else use altitude
if (this->ambient_pressure_compensation_) {
if (!this->update_ambient_pressure_compensation_(this->ambient_pressure_)) {
ESP_LOGE(TAG, "Error setting ambient pressure compensation");
this->error_code_ = MEASUREMENT_INIT_FAILED;
this->mark_failed();
return;
}
} else {
if (!this->write_command(SCD4X_CMD_ALTITUDE_COMPENSATION, altitude_compensation_)) {
ESP_LOGE(TAG, "Error setting altitude compensation.");
if (!this->write_command(SCD4X_CMD_ALTITUDE_COMPENSATION, this->altitude_compensation_)) {
ESP_LOGE(TAG, "Error setting altitude compensation");
this->error_code_ = MEASUREMENT_INIT_FAILED;
this->mark_failed();
return;
}
}
if (!this->write_command(SCD4X_CMD_AUTOMATIC_SELF_CALIBRATION, enable_asc_ ? 1 : 0)) {
ESP_LOGE(TAG, "Error setting automatic self calibration.");
if (!this->write_command(SCD4X_CMD_AUTOMATIC_SELF_CALIBRATION, this->enable_asc_ ? 1 : 0)) {
ESP_LOGE(TAG, "Error setting automatic self calibration");
this->error_code_ = MEASUREMENT_INIT_FAILED;
this->mark_failed();
return;
}
initialized_ = true;
this->initialized_ = true;
// Finally start sensor measurements
this->start_measurement_();
ESP_LOGD(TAG, "Sensor initialized");
});
});
}
void SCD4XComponent::dump_config() {
ESP_LOGCONFIG(TAG, "scd4x:");
static const char *const MM_PERIODIC_STR = "Periodic (5s)";
static const char *const MM_LOW_POWER_PERIODIC_STR = "Low power periodic (30s)";
static const char *const MM_SINGLE_SHOT_STR = "Single shot";
static const char *const MM_SINGLE_SHOT_RHT_ONLY_STR = "Single shot rht only";
const char *measurement_mode_str = MM_PERIODIC_STR;
switch (this->measurement_mode_) {
case PERIODIC:
// measurement_mode_str = MM_PERIODIC_STR;
break;
case LOW_POWER_PERIODIC:
measurement_mode_str = MM_LOW_POWER_PERIODIC_STR;
break;
case SINGLE_SHOT:
measurement_mode_str = MM_SINGLE_SHOT_STR;
break;
case SINGLE_SHOT_RHT_ONLY:
measurement_mode_str = MM_SINGLE_SHOT_RHT_ONLY_STR;
break;
}
ESP_LOGCONFIG(TAG, "SCD4X:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
switch (this->error_code_) {
@ -102,16 +121,20 @@ void SCD4XComponent::dump_config() {
ESP_LOGW(TAG, "Measurement Initialization failed");
break;
case SERIAL_NUMBER_IDENTIFICATION_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");
break;
}
}
ESP_LOGCONFIG(TAG, " Automatic self calibration: %s", ONOFF(this->enable_asc_));
ESP_LOGCONFIG(TAG,
" Automatic self calibration: %s\n"
" Measurement mode: %s\n"
" Temperature offset: %.2f °C",
ONOFF(this->enable_asc_), measurement_mode_str, this->temperature_offset_);
if (this->ambient_pressure_source_ != nullptr) {
ESP_LOGCONFIG(TAG, " Dynamic ambient pressure compensation using sensor '%s'",
ESP_LOGCONFIG(TAG, " Dynamic ambient pressure compensation using '%s'",
this->ambient_pressure_source_->get_name().c_str());
} else {
if (this->ambient_pressure_compensation_) {
@ -126,21 +149,6 @@ void SCD4XComponent::dump_config() {
this->altitude_compensation_);
}
}
switch (this->measurement_mode_) {
case PERIODIC:
ESP_LOGCONFIG(TAG, " Measurement mode: periodic (5s)");
break;
case LOW_POWER_PERIODIC:
ESP_LOGCONFIG(TAG, " Measurement mode: low power periodic (30s)");
break;
case SINGLE_SHOT:
ESP_LOGCONFIG(TAG, " Measurement mode: single shot");
break;
case SINGLE_SHOT_RHT_ONLY:
ESP_LOGCONFIG(TAG, " Measurement mode: single shot rht only");
break;
}
ESP_LOGCONFIG(TAG, " Temperature offset: %.2f °C", this->temperature_offset_);
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "CO2", this->co2_sensor_);
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
@ -148,20 +156,20 @@ void SCD4XComponent::dump_config() {
}
void SCD4XComponent::update() {
if (!initialized_) {
if (!this->initialized_) {
return;
}
if (this->ambient_pressure_source_ != nullptr) {
float pressure = this->ambient_pressure_source_->state;
if (!std::isnan(pressure)) {
set_ambient_pressure_compensation(pressure);
this->set_ambient_pressure_compensation(pressure);
}
}
uint32_t wait_time = 0;
if (this->measurement_mode_ == SINGLE_SHOT || this->measurement_mode_ == SINGLE_SHOT_RHT_ONLY) {
start_measurement_();
this->start_measurement_();
wait_time =
this->measurement_mode_ == SINGLE_SHOT ? 5000 : 50; // Single shot measurement takes 5 secs rht mode 50 ms
}
@ -176,12 +184,12 @@ void SCD4XComponent::update() {
if (!this->read_data(raw_read_status) || raw_read_status == 0x00) {
this->status_set_warning();
ESP_LOGW(TAG, "Data not ready yet!");
ESP_LOGW(TAG, "Data not ready");
return;
}
if (!this->write_command(SCD4X_CMD_READ_MEASUREMENT)) {
ESP_LOGW(TAG, "Error reading measurement!");
ESP_LOGW(TAG, "Error reading measurement");
this->status_set_warning();
return; // NO RETRY
}
@ -218,7 +226,7 @@ bool SCD4XComponent::perform_forced_calibration(uint16_t current_co2_concentrati
}
this->set_timeout(500, [this, current_co2_concentration]() {
if (this->write_command(SCD4X_CMD_PERFORM_FORCED_CALIBRATION, current_co2_concentration)) {
ESP_LOGD(TAG, "setting forced calibration Co2 level %d ppm", current_co2_concentration);
ESP_LOGD(TAG, "Setting forced calibration Co2 level %d ppm", current_co2_concentration);
// frc takes 400 ms
// because this method will be used very rarly
// the simple approach with delay is ok
@ -226,11 +234,11 @@ bool SCD4XComponent::perform_forced_calibration(uint16_t current_co2_concentrati
if (!this->start_measurement_()) {
return false;
} else {
ESP_LOGD(TAG, "forced calibration complete");
ESP_LOGD(TAG, "Forced calibration complete");
}
return true;
} else {
ESP_LOGE(TAG, "force calibration failed");
ESP_LOGE(TAG, "Force calibration failed");
this->error_code_ = FRC_FAILED;
this->status_set_warning();
return false;
@ -261,25 +269,25 @@ bool SCD4XComponent::factory_reset() {
void SCD4XComponent::set_ambient_pressure_compensation(float pressure_in_hpa) {
ambient_pressure_compensation_ = true;
uint16_t new_ambient_pressure = (uint16_t) pressure_in_hpa;
if (!initialized_) {
ambient_pressure_ = new_ambient_pressure;
if (!this->initialized_) {
this->ambient_pressure_ = new_ambient_pressure;
return;
}
// Only send pressure value if it has changed since last update
if (new_ambient_pressure != ambient_pressure_) {
update_ambient_pressure_compensation_(new_ambient_pressure);
ambient_pressure_ = new_ambient_pressure;
if (new_ambient_pressure != this->ambient_pressure_) {
this->update_ambient_pressure_compensation_(new_ambient_pressure);
this->ambient_pressure_ = new_ambient_pressure;
} else {
ESP_LOGD(TAG, "ambient pressure compensation skipped - no change required");
ESP_LOGD(TAG, "Ambient pressure compensation skipped; no change required");
}
}
bool SCD4XComponent::update_ambient_pressure_compensation_(uint16_t pressure_in_hpa) {
if (this->write_command(SCD4X_CMD_AMBIENT_PRESSURE_COMPENSATION, pressure_in_hpa)) {
ESP_LOGD(TAG, "setting ambient pressure compensation to %d hPa", pressure_in_hpa);
ESP_LOGD(TAG, "Setting ambient pressure compensation to %d hPa", pressure_in_hpa);
return true;
} else {
ESP_LOGE(TAG, "Error setting ambient pressure compensation.");
ESP_LOGE(TAG, "Error setting ambient pressure compensation");
return false;
}
}
@ -304,7 +312,7 @@ bool SCD4XComponent::start_measurement_() {
static uint8_t remaining_retries = 3;
while (remaining_retries) {
if (!this->write_command(measurement_command)) {
ESP_LOGE(TAG, "Error starting measurements.");
ESP_LOGE(TAG, "Error starting measurements");
this->error_code_ = MEASUREMENT_INIT_FAILED;
this->status_set_warning();
if (--remaining_retries == 0)

View File

@ -8,14 +8,20 @@
namespace esphome {
namespace scd4x {
enum ERRORCODE {
enum ErrorCode : uint8_t {
COMMUNICATION_FAILED,
SERIAL_NUMBER_IDENTIFICATION_FAILED,
MEASUREMENT_INIT_FAILED,
FRC_FAILED,
UNKNOWN
UNKNOWN,
};
enum MeasurementMode : uint8_t {
PERIODIC,
LOW_POWER_PERIODIC,
SINGLE_SHOT,
SINGLE_SHOT_RHT_ONLY,
};
enum MeasurementMode { PERIODIC, LOW_POWER_PERIODIC, SINGLE_SHOT, SINGLE_SHOT_RHT_ONLY };
class SCD4XComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice {
public:
@ -39,15 +45,14 @@ class SCD4XComponent : public PollingComponent, public sensirion_common::Sensiri
protected:
bool update_ambient_pressure_compensation_(uint16_t pressure_in_hpa);
bool start_measurement_();
ERRORCODE error_code_;
bool initialized_{false};
float temperature_offset_;
uint16_t altitude_compensation_;
bool ambient_pressure_compensation_;
uint16_t ambient_pressure_;
bool initialized_{false};
bool ambient_pressure_compensation_;
bool enable_asc_;
float temperature_offset_;
ErrorCode error_code_;
MeasurementMode measurement_mode_{PERIODIC};
sensor::Sensor *co2_sensor_{nullptr};
sensor::Sensor *temperature_sensor_{nullptr};