1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-14 14:48:18 +00:00

mhz19: disable autocalibration for MH-Z19B by default

MH-Z19B allows to enable/disable 'automatic baseline calibration',
which is enabled by default (MH-Z19B v1.2 datasheet).
It operates on too short 24hr interval. So if the place
where sensor is located is not ventilated well "every" day, ABC will
make sensor under-report CO2 value, since baseline (400ppm) is moved
to lowest observed value in 24hr.

With such short recalibrartion window, sensor often doesn't show
correct CO2 levels when ABS is left enabled. Disable it on boot
defaut and add 'automatic_baseline_calibration' option to allow
override from config.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
This commit is contained in:
Igor Mammedov 2019-05-05 16:00:44 +02:00
parent 886f84af29
commit 9781915611
3 changed files with 25 additions and 1 deletions

View File

@ -7,6 +7,8 @@ namespace mhz19 {
static const char *TAG = "mhz19";
static const uint8_t MHZ19_PDU_LENGTH = 9;
static const uint8_t MHZ19_COMMAND_GET_PPM[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
static const uint8_t MHZ19_COMMAND_ABC_ENABLE[] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6};
static const uint8_t MHZ19_COMMAND_ABC_DISABLE[] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86};
uint8_t mhz19_checksum(const uint8_t *command) {
uint8_t sum = 0;
@ -40,6 +42,21 @@ void MHZ19Component::setup() {
this->model_b_ = true;
}
if (this->model_b_) {
/*
* MH-Z19B allows to enable/disable 'automatic baseline calibration' (datasheet MH-Z19B v1.2),
* disable it to prevent sensor baseline drift in not well ventilated areas
*/
if (this->abc_enabled_ == false) {
ESP_LOGI(TAG, "Disabling ABC on boot");
/* per spec response isn't expected but sensor replies anyway.
* Read reply out and discard it so it won't get in the way of following commands */
this->mhz19_write_command_(MHZ19_COMMAND_ABC_DISABLE, response);
} else {
ESP_LOGI(TAG, "Enabling ABC on boot");
this->mhz19_write_command_(MHZ19_COMMAND_ABC_ENABLE, response);
}
}
setup_done = true;
}
@ -123,6 +140,7 @@ bool MHZ19Component::mhz19_write_command_(const uint8_t *command, uint8_t *respo
float MHZ19Component::get_setup_priority() const { return setup_priority::DATA; }
void MHZ19Component::dump_config() {
ESP_LOGCONFIG(TAG, "MH-Z19%s:", this->model_b_ ? "B" : "");
ESP_LOGCONFIG(TAG, " Automatic calibration: %s", this->abc_enabled_ ? " enabled" : "disabled");
LOG_SENSOR(" ", "CO2", this->co2_sensor_);
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
}

View File

@ -17,6 +17,7 @@ class MHZ19Component : public PollingComponent, public uart::UARTDevice {
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(bool enable_abc) { abc_enabled_ = enable_abc; }
protected:
bool mhz19_write_command_(const uint8_t *command, uint8_t *response);
@ -24,6 +25,7 @@ class MHZ19Component : public PollingComponent, public uart::UARTDevice {
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *co2_sensor_{nullptr};
bool model_b_;
bool abc_enabled_;
};
} // namespace mhz19

View File

@ -2,10 +2,11 @@ import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, uart
from esphome.const import CONF_CO2, CONF_ID, CONF_TEMPERATURE, ICON_PERIODIC_TABLE_CO2, \
UNIT_PARTS_PER_MILLION, UNIT_CELSIUS, ICON_THERMOMETER
UNIT_PARTS_PER_MILLION, UNIT_CELSIUS, ICON_THERMOMETER, UNIT_EMPTY, ICON_EMPTY
DEPENDENCIES = ['uart']
CONF_ABC = "automatic_baseline_calibration"
mhz19_ns = cg.esphome_ns.namespace('mhz19')
MHZ19Component = mhz19_ns.class_('MHZ19Component', cg.PollingComponent, uart.UARTDevice)
@ -13,6 +14,7 @@ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_id(MHZ19Component),
cv.Required(CONF_CO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, ICON_PERIODIC_TABLE_CO2, 0),
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 0),
cv.Optional(CONF_ABC, default=False): cv.boolean,
}).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA)
@ -28,3 +30,5 @@ def to_code(config):
if CONF_TEMPERATURE in config:
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
cg.add(var.set_temperature_sensor(sens))
cg.add(var.set_abc(config[CONF_ABC]))