mirror of
https://github.com/esphome/esphome.git
synced 2026-02-08 00:31:58 +00:00
[mhz19] Make detection range configurable (#12677)
Co-authored-by: Fabio Pugliese Ornellas <fabio.ornellas@gmail.com>
This commit is contained in:
committed by
GitHub
parent
c34665f650
commit
5cfcf8d104
@@ -13,6 +13,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;
|
||||
@@ -28,6 +31,8 @@ void MHZ19Component::setup() {
|
||||
} else if (this->abc_boot_logic_ == MHZ19_ABC_DISABLED) {
|
||||
this->abc_disable();
|
||||
}
|
||||
|
||||
this->range_set(this->detection_range_);
|
||||
}
|
||||
|
||||
void MHZ19Component::update() {
|
||||
@@ -86,6 +91,26 @@ void MHZ19Component::abc_disable() {
|
||||
this->mhz19_write_command_(MHZ19_COMMAND_ABC_DISABLE, nullptr);
|
||||
}
|
||||
|
||||
void MHZ19Component::range_set(MHZ19DetectionRange detection_ppm) {
|
||||
switch (detection_ppm) {
|
||||
case MHZ19_DETECTION_RANGE_DEFAULT:
|
||||
ESP_LOGV(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;
|
||||
}
|
||||
}
|
||||
|
||||
bool MHZ19Component::mhz19_write_command_(const uint8_t *command, uint8_t *response) {
|
||||
// Empty RX Buffer
|
||||
while (this->available())
|
||||
@@ -99,7 +124,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_);
|
||||
@@ -113,6 +140,23 @@ void MHZ19Component::dump_config() {
|
||||
}
|
||||
|
||||
ESP_LOGCONFIG(TAG, " Warmup time: %" PRIu32 " s", 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
|
||||
|
||||
@@ -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:
|
||||
@@ -21,11 +32,13 @@ class MHZ19Component : public PollingComponent, public uart::UARTDevice {
|
||||
void calibrate_zero();
|
||||
void abc_enable();
|
||||
void abc_disable();
|
||||
void range_set(MHZ19DetectionRange detection_ppm);
|
||||
|
||||
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
|
||||
void set_co2_sensor(sensor::Sensor *co2_sensor) { co2_sensor_ = co2_sensor; }
|
||||
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);
|
||||
@@ -33,7 +46,10 @@ class MHZ19Component : public PollingComponent, public uart::UARTDevice {
|
||||
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<typename... Ts> class MHZ19CalibrateZeroAction : public Action<Ts...> {
|
||||
@@ -66,5 +82,16 @@ template<typename... Ts> class MHZ19ABCDisableAction : public Action<Ts...> {
|
||||
MHZ19Component *mhz19_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class MHZ19DetectionRangeSetAction : public Action<Ts...> {
|
||||
public:
|
||||
MHZ19DetectionRangeSetAction(MHZ19Component *mhz19) : mhz19_(mhz19) {}
|
||||
TEMPLATABLE_VALUE(MHZ19DetectionRange, detection_range)
|
||||
|
||||
void play(const Ts &...x) override { this->mhz19_->range_set(this->detection_range_.value(x...)); }
|
||||
|
||||
protected:
|
||||
MHZ19Component *mhz19_;
|
||||
};
|
||||
|
||||
} // namespace mhz19
|
||||
} // namespace esphome
|
||||
|
||||
@@ -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)
|
||||
@@ -27,6 +28,18 @@ MHZ19CalibrateZeroAction = mhz19_ns.class_(
|
||||
)
|
||||
MHZ19ABCEnableAction = mhz19_ns.class_("MHZ19ABCEnableAction", automation.Action)
|
||||
MHZ19ABCDisableAction = mhz19_ns.class_("MHZ19ABCDisableAction", automation.Action)
|
||||
MHZ19DetectionRangeSetAction = mhz19_ns.class_(
|
||||
"MHZ19DetectionRangeSetAction", automation.Action
|
||||
)
|
||||
|
||||
mhz19_detection_range = mhz19_ns.enum("MHZ19DetectionRange")
|
||||
MHZ19_DETECTION_RANGE_ENUM = {
|
||||
2000: mhz19_detection_range.MHZ19_DETECTION_RANGE_0_2000PPM,
|
||||
5000: mhz19_detection_range.MHZ19_DETECTION_RANGE_0_5000PPM,
|
||||
10000: mhz19_detection_range.MHZ19_DETECTION_RANGE_0_10000PPM,
|
||||
}
|
||||
|
||||
_validate_ppm = cv.float_with_unit("parts per million", "ppm")
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
@@ -49,6 +62,9 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(
|
||||
CONF_WARMUP_TIME, default="75s"
|
||||
): cv.positive_time_period_seconds,
|
||||
cv.Optional(CONF_DETECTION_RANGE): cv.All(
|
||||
_validate_ppm, cv.enum(MHZ19_DETECTION_RANGE_ENUM)
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
@@ -78,6 +94,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(
|
||||
{
|
||||
@@ -98,3 +117,25 @@ CALIBRATION_ACTION_SCHEMA = maybe_simple_id(
|
||||
async def mhz19_calibration_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
RANGE_ACTION_SCHEMA = maybe_simple_id(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(MHZ19Component),
|
||||
cv.Required(CONF_DETECTION_RANGE): cv.All(
|
||||
_validate_ppm, cv.enum(MHZ19_DETECTION_RANGE_ENUM)
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"mhz19.detection_range_set", MHZ19DetectionRangeSetAction, RANGE_ACTION_SCHEMA
|
||||
)
|
||||
async def mhz19_detection_range_set_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
detection_range = config.get(CONF_DETECTION_RANGE)
|
||||
template_ = await cg.templatable(detection_range, args, mhz19_detection_range)
|
||||
cg.add(var.set_detection_range(template_))
|
||||
return var
|
||||
|
||||
@@ -6,3 +6,4 @@ sensor:
|
||||
name: MH-Z19 Temperature
|
||||
automatic_baseline_calibration: false
|
||||
update_interval: 15s
|
||||
detection_range: 5000ppm
|
||||
|
||||
Reference in New Issue
Block a user