From b53adcb4d60cd16a695550c30c5d416dc7306453 Mon Sep 17 00:00:00 2001 From: Fabio Pugliese Ornellas Date: Sun, 25 Feb 2024 13:06:06 +0000 Subject: [PATCH] add detection range --- esphome/components/mhz19/mhz19.cpp | 40 ++++++++++++++++++++++++++++++ esphome/components/mhz19/mhz19.h | 18 +++++++++++++- esphome/components/mhz19/sensor.py | 8 ++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index 019f6cee5..12bb9f5b6 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -11,6 +11,9 @@ static const uint8_t MHZ19_COMMAND_GET_PPM[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x static const uint8_t MHZ19_COMMAND_ABC_ENABLE[] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00}; static const uint8_t MHZ19_COMMAND_ABC_DISABLE[] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00}; static const uint8_t MHZ19_COMMAND_CALIBRATE_ZERO[] = {0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_2000PPM[] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x07, 0xD0}; +static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_5000PPM[] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88}; +static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_10000PPM[] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x27, 0x10}; uint8_t mhz19_checksum(const uint8_t *command) { uint8_t sum = 0; @@ -26,6 +29,24 @@ void MHZ19Component::setup() { } else if (this->abc_boot_logic_ == MHZ19_ABC_DISABLED) { this->abc_disable(); } + + switch (this->detection_range_) { + case MHZ19_DETECTION_RANGE_DEFAULT: + ESP_LOGD(TAG, "Using previously set detection range (no change)"); + break; + case MHZ19_DETECTION_RANGE_0_2000PPM: + ESP_LOGD(TAG, "Setting detection range to 0 to 2000ppm"); + this->mhz19_write_command_(MHZ19_COMMAND_DETECTION_RANGE_0_2000PPM, nullptr); + break; + case MHZ19_DETECTION_RANGE_0_5000PPM: + ESP_LOGD(TAG, "Setting detection range to 0 to 5000ppm"); + this->mhz19_write_command_(MHZ19_COMMAND_DETECTION_RANGE_0_5000PPM, nullptr); + break; + case MHZ19_DETECTION_RANGE_0_10000PPM: + ESP_LOGD(TAG, "Setting detection range to 0 to 10000ppm"); + this->mhz19_write_command_(MHZ19_COMMAND_DETECTION_RANGE_0_10000PPM, nullptr); + break; + } } void MHZ19Component::update() { @@ -97,7 +118,9 @@ bool MHZ19Component::mhz19_write_command_(const uint8_t *command, uint8_t *respo return this->read_array(response, MHZ19_RESPONSE_LENGTH); } + float MHZ19Component::get_setup_priority() const { return setup_priority::DATA; } + void MHZ19Component::dump_config() { ESP_LOGCONFIG(TAG, "MH-Z19:"); LOG_SENSOR(" ", "CO2", this->co2_sensor_); @@ -111,6 +134,23 @@ void MHZ19Component::dump_config() { } ESP_LOGCONFIG(TAG, " Warmup seconds: %ds", this->warmup_seconds_); + + const char *range_str; + switch (this->detection_range_) { + case MHZ19_DETECTION_RANGE_DEFAULT: + range_str = "default"; + break; + case MHZ19_DETECTION_RANGE_0_2000PPM: + range_str = "0 to 2000ppm"; + break; + case MHZ19_DETECTION_RANGE_0_5000PPM: + range_str = "0 to 5000ppm"; + break; + case MHZ19_DETECTION_RANGE_0_10000PPM: + range_str = "0 to 10000ppm"; + break; + } + ESP_LOGCONFIG(TAG, " Detection range: %s", range_str); } } // namespace mhz19 diff --git a/esphome/components/mhz19/mhz19.h b/esphome/components/mhz19/mhz19.h index ec38f2cd2..6c4562fc8 100644 --- a/esphome/components/mhz19/mhz19.h +++ b/esphome/components/mhz19/mhz19.h @@ -8,7 +8,18 @@ namespace esphome { namespace mhz19 { -enum MHZ19ABCLogic { MHZ19_ABC_NONE = 0, MHZ19_ABC_ENABLED, MHZ19_ABC_DISABLED }; +enum MHZ19ABCLogic { + MHZ19_ABC_NONE = 0, + MHZ19_ABC_ENABLED, + MHZ19_ABC_DISABLED, +}; + +enum MHZ19DetectionRange { + MHZ19_DETECTION_RANGE_DEFAULT = 0, + MHZ19_DETECTION_RANGE_0_2000PPM, + MHZ19_DETECTION_RANGE_0_5000PPM, + MHZ19_DETECTION_RANGE_0_10000PPM, +}; class MHZ19Component : public PollingComponent, public uart::UARTDevice { public: @@ -27,13 +38,18 @@ class MHZ19Component : public PollingComponent, public uart::UARTDevice { void set_abc_enabled(bool abc_enabled) { abc_boot_logic_ = abc_enabled ? MHZ19_ABC_ENABLED : MHZ19_ABC_DISABLED; } void set_warmup_seconds(uint32_t seconds) { warmup_seconds_ = seconds; } + void set_detection_range(MHZ19DetectionRange detection_range) { detection_range_ = detection_range; } + protected: bool mhz19_write_command_(const uint8_t *command, uint8_t *response); sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *co2_sensor_{nullptr}; MHZ19ABCLogic abc_boot_logic_{MHZ19_ABC_NONE}; + uint32_t warmup_seconds_; + + MHZ19DetectionRange detection_range_{MHZ19_DETECTION_RANGE_DEFAULT}; }; template class MHZ19CalibrateZeroAction : public Action { diff --git a/esphome/components/mhz19/sensor.py b/esphome/components/mhz19/sensor.py index 395672798..07ce9e05c 100644 --- a/esphome/components/mhz19/sensor.py +++ b/esphome/components/mhz19/sensor.py @@ -19,6 +19,7 @@ DEPENDENCIES = ["uart"] CONF_AUTOMATIC_BASELINE_CALIBRATION = "automatic_baseline_calibration" CONF_WARMUP_TIME = "warmup_time" +CONF_DETECTION_RANGE = "detection_range" mhz19_ns = cg.esphome_ns.namespace("mhz19") MHZ19Component = mhz19_ns.class_("MHZ19Component", cg.PollingComponent, uart.UARTDevice) @@ -49,6 +50,10 @@ CONFIG_SCHEMA = ( cv.Optional( CONF_WARMUP_TIME, default="75s" ): cv.positive_time_period_seconds, + cv.Optional(CONF_DETECTION_RANGE): cv.All( + cv.float_with_unit("parts per million", "(ppm)"), + cv.one_of(2000, 5000, 10000, int=True), + ), } ) .extend(cv.polling_component_schema("60s")) @@ -74,6 +79,9 @@ async def to_code(config): cg.add(var.set_warmup_seconds(config[CONF_WARMUP_TIME])) + if CONF_DETECTION_RANGE in config: + cg.add(var.set_detection_range(config[CONF_DETECTION_RANGE])) + CALIBRATION_ACTION_SCHEMA = maybe_simple_id( {