From ccfa1e23f0211f5421bef22b328ec3fb5b4204ee Mon Sep 17 00:00:00 2001 From: Martin <25747549+martgras@users.noreply.github.com> Date: Wed, 24 Nov 2021 23:28:19 +0100 Subject: [PATCH] Add support for sdp8xx (#2779) --- esphome/components/sdp3x/sdp3x.cpp | 106 ++++++++++++++++++----------- esphome/components/sdp3x/sdp3x.h | 6 +- esphome/components/sdp3x/sensor.py | 12 ++++ 3 files changed, 83 insertions(+), 41 deletions(-) diff --git a/esphome/components/sdp3x/sdp3x.cpp b/esphome/components/sdp3x/sdp3x.cpp index b0d8bcc6c4..107ed2902f 100644 --- a/esphome/components/sdp3x/sdp3x.cpp +++ b/esphome/components/sdp3x/sdp3x.cpp @@ -11,6 +11,7 @@ static const uint8_t SDP3X_SOFT_RESET[2] = {0x00, 0x06}; static const uint8_t SDP3X_READ_ID1[2] = {0x36, 0x7C}; static const uint8_t SDP3X_READ_ID2[2] = {0xE1, 0x02}; static const uint8_t SDP3X_START_DP_AVG[2] = {0x36, 0x15}; +static const uint8_t SDP3X_START_MASS_FLOW_AVG[2] = {0x36, 0x03}; static const uint8_t SDP3X_STOP_MEAS[2] = {0x3F, 0xF9}; void SDP3XComponent::update() { this->read_pressure_(); } @@ -26,46 +27,69 @@ void SDP3XComponent::setup() { ESP_LOGW(TAG, "Soft Reset SDP3X failed!"); // This sometimes fails for no good reason } - delayMicroseconds(20000); + this->set_timeout(20, [this] { + if (this->write(SDP3X_READ_ID1, 2) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Read ID1 SDP3X failed!"); + this->mark_failed(); + return; + } + if (this->write(SDP3X_READ_ID2, 2) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Read ID2 SDP3X failed!"); + this->mark_failed(); + return; + } - if (this->write(SDP3X_READ_ID1, 2) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Read ID1 SDP3X failed!"); - this->mark_failed(); - return; - } - if (this->write(SDP3X_READ_ID2, 2) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Read ID2 SDP3X failed!"); - this->mark_failed(); - return; - } + uint8_t data[18]; + if (this->read(data, 18) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Read ID SDP3X failed!"); + this->mark_failed(); + return; + } + if (!(check_crc_(&data[0], 2, data[2]) && check_crc_(&data[3], 2, data[5]))) { + ESP_LOGE(TAG, "CRC ID SDP3X failed!"); + this->mark_failed(); + return; + } - uint8_t data[18]; - if (this->read(data, 18) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Read ID SDP3X failed!"); - this->mark_failed(); - return; - } + // SDP8xx + // ref: + // https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/8_Differential_Pressure/Datasheets/Sensirion_Differential_Pressure_Datasheet_SDP8xx_Digital.pdf + if (data[2] == 0x02) { + switch (data[3]) { + case 0x01: // SDP800-500Pa + ESP_LOGCONFIG(TAG, "Sensor is SDP800-500Pa"); + break; + case 0x0A: // SDP810-500Pa + ESP_LOGCONFIG(TAG, "Sensor is SDP810-500Pa"); + break; + case 0x04: // SDP801-500Pa + ESP_LOGCONFIG(TAG, "Sensor is SDP801-500Pa"); + break; + case 0x0D: // SDP811-500Pa + ESP_LOGCONFIG(TAG, "Sensor is SDP811-500Pa"); + break; + case 0x02: // SDP800-125Pa + ESP_LOGCONFIG(TAG, "Sensor is SDP800-125Pa"); + break; + case 0x0B: // SDP810-125Pa + ESP_LOGCONFIG(TAG, "Sensor is SDP810-125Pa"); + break; + } + } else if (data[2] == 0x01) { + if (data[3] == 0x01) { + ESP_LOGCONFIG(TAG, "Sensor is SDP31-500Pa"); + } else if (data[3] == 0x02) { + ESP_LOGCONFIG(TAG, "Sensor is SDP32-125Pa"); + } + } - if (!(check_crc_(&data[0], 2, data[2]) && check_crc_(&data[3], 2, data[5]))) { - ESP_LOGE(TAG, "CRC ID SDP3X failed!"); - this->mark_failed(); - return; - } - - if (data[3] == 0x01) { - ESP_LOGCONFIG(TAG, "SDP3X is SDP31"); - pressure_scale_factor_ = 60.0f * 100.0f; // Scale factors converted to hPa per count - } else if (data[3] == 0x02) { - ESP_LOGCONFIG(TAG, "SDP3X is SDP32"); - pressure_scale_factor_ = 240.0f * 100.0f; - } - - if (this->write(SDP3X_START_DP_AVG, 2) != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Start Measurements SDP3X failed!"); - this->mark_failed(); - return; - } - ESP_LOGCONFIG(TAG, "SDP3X started!"); + if (this->write(measurement_mode_ == DP_AVG ? SDP3X_START_DP_AVG : SDP3X_START_MASS_FLOW_AVG, 2) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Start Measurements SDP3X failed!"); + this->mark_failed(); + return; + } + ESP_LOGCONFIG(TAG, "SDP3X started!"); + }); } void SDP3XComponent::dump_config() { LOG_SENSOR(" ", "SDP3X", this); @@ -91,8 +115,12 @@ void SDP3XComponent::read_pressure_() { } int16_t pressure_raw = encode_uint16(data[0], data[1]); - float pressure = pressure_raw / pressure_scale_factor_; - ESP_LOGV(TAG, "Got raw pressure=%d, scale factor =%.3f ", pressure_raw, pressure_scale_factor_); + int16_t temperature_raw = encode_uint16(data[3], data[4]); + int16_t scale_factor_raw = encode_uint16(data[6], data[7]); + // scale factor is in Pa - convert to hPa + float pressure = pressure_raw / (scale_factor_raw * 100.0f); + ESP_LOGV(TAG, "Got raw pressure=%d, raw scale factor =%d, raw temperature=%d ", pressure_raw, scale_factor_raw, + temperature_raw); ESP_LOGD(TAG, "Got Pressure=%.3f hPa", pressure); this->publish_state(pressure); diff --git a/esphome/components/sdp3x/sdp3x.h b/esphome/components/sdp3x/sdp3x.h index 51c9973c61..0e74d0883d 100644 --- a/esphome/components/sdp3x/sdp3x.h +++ b/esphome/components/sdp3x/sdp3x.h @@ -7,6 +7,8 @@ namespace esphome { namespace sdp3x { +enum MeasurementMode { MASS_FLOW_AVG, DP_AVG }; + class SDP3XComponent : public PollingComponent, public i2c::I2CDevice, public sensor::Sensor { public: /// Schedule temperature+pressure readings. @@ -16,14 +18,14 @@ class SDP3XComponent : public PollingComponent, public i2c::I2CDevice, public se void dump_config() override; float get_setup_priority() const override; + void set_measurement_mode(MeasurementMode mode) { measurement_mode_ = mode; } protected: /// Internal method to read the pressure from the component after it has been scheduled. void read_pressure_(); bool check_crc_(const uint8_t data[], uint8_t size, uint8_t checksum); - - float pressure_scale_factor_ = 0.0f; // hPa per count + MeasurementMode measurement_mode_; }; } // namespace sdp3x diff --git a/esphome/components/sdp3x/sensor.py b/esphome/components/sdp3x/sensor.py index 08d7250f6e..45f5cc4d9a 100644 --- a/esphome/components/sdp3x/sensor.py +++ b/esphome/components/sdp3x/sensor.py @@ -14,6 +14,14 @@ CODEOWNERS = ["@Azimath"] sdp3x_ns = cg.esphome_ns.namespace("sdp3x") SDP3XComponent = sdp3x_ns.class_("SDP3XComponent", cg.PollingComponent, i2c.I2CDevice) + +MeasurementMode = sdp3x_ns.enum("MeasurementMode") +MEASUREMENT_MODE = { + "mass_flow": MeasurementMode.MASS_FLOW_AVG, + "differential_pressure": MeasurementMode.DP_AVG, +} +CONF_MEASUREMENT_MODE = "measurement_mode" + CONFIG_SCHEMA = ( sensor.sensor_schema( unit_of_measurement=UNIT_HECTOPASCAL, @@ -24,6 +32,9 @@ CONFIG_SCHEMA = ( .extend( { cv.GenerateID(): cv.declare_id(SDP3XComponent), + cv.Optional( + CONF_MEASUREMENT_MODE, default="differential_pressure" + ): cv.enum(MEASUREMENT_MODE), } ) .extend(cv.polling_component_schema("60s")) @@ -36,3 +47,4 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) await sensor.register_sensor(var, config) + cg.add(var.set_measurement_mode(config[CONF_MEASUREMENT_MODE]))