ESPHome 2025.5.0
Loading...
Searching...
No Matches
mhz19.cpp
Go to the documentation of this file.
1#include "mhz19.h"
2#include "esphome/core/log.h"
3
4#include <cinttypes>
5
6namespace esphome {
7namespace mhz19 {
8
9static const char *const TAG = "mhz19";
10static const uint8_t MHZ19_REQUEST_LENGTH = 8;
11static const uint8_t MHZ19_RESPONSE_LENGTH = 9;
12static const uint8_t MHZ19_COMMAND_GET_PPM[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00};
13static const uint8_t MHZ19_COMMAND_ABC_ENABLE[] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00};
14static const uint8_t MHZ19_COMMAND_ABC_DISABLE[] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00};
15static const uint8_t MHZ19_COMMAND_CALIBRATE_ZERO[] = {0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00};
16
17uint8_t mhz19_checksum(const uint8_t *command) {
18 uint8_t sum = 0;
19 for (uint8_t i = 1; i < MHZ19_REQUEST_LENGTH; i++) {
20 sum += command[i];
21 }
22 return 0xFF - sum + 0x01;
23}
24
27 this->abc_enable();
28 } else if (this->abc_boot_logic_ == MHZ19_ABC_DISABLED) {
29 this->abc_disable();
30 }
31}
32
34 uint32_t now_ms = millis();
35 uint32_t warmup_ms = this->warmup_seconds_ * 1000;
36 if (now_ms < warmup_ms) {
37 ESP_LOGW(TAG, "MHZ19 warming up, %" PRIu32 " s left", (warmup_ms - now_ms) / 1000);
38 this->status_set_warning();
39 return;
40 }
41
42 uint8_t response[MHZ19_RESPONSE_LENGTH];
43 if (!this->mhz19_write_command_(MHZ19_COMMAND_GET_PPM, response)) {
44 ESP_LOGW(TAG, "Reading data from MHZ19 failed!");
45 this->status_set_warning();
46 return;
47 }
48
49 if (response[0] != 0xFF || response[1] != 0x86) {
50 ESP_LOGW(TAG, "Invalid preamble from MHZ19!");
51 this->status_set_warning();
52 return;
53 }
54
55 uint8_t checksum = mhz19_checksum(response);
56 if (response[8] != checksum) {
57 ESP_LOGW(TAG, "MHZ19 Checksum doesn't match: 0x%02X!=0x%02X", response[8], checksum);
58 this->status_set_warning();
59 return;
60 }
61
63 const uint16_t ppm = (uint16_t(response[2]) << 8) | response[3];
64 const int temp = int(response[4]) - 40;
65 const uint8_t status = response[5];
66
67 ESP_LOGD(TAG, "MHZ19 Received CO₂=%uppm Temperature=%d°C Status=0x%02X", ppm, temp, status);
68 if (this->co2_sensor_ != nullptr)
69 this->co2_sensor_->publish_state(ppm);
70 if (this->temperature_sensor_ != nullptr)
72}
73
75 ESP_LOGD(TAG, "MHZ19 Calibrating zero point");
76 this->mhz19_write_command_(MHZ19_COMMAND_CALIBRATE_ZERO, nullptr);
77}
78
80 ESP_LOGD(TAG, "MHZ19 Enabling automatic baseline calibration");
81 this->mhz19_write_command_(MHZ19_COMMAND_ABC_ENABLE, nullptr);
82}
83
85 ESP_LOGD(TAG, "MHZ19 Disabling automatic baseline calibration");
86 this->mhz19_write_command_(MHZ19_COMMAND_ABC_DISABLE, nullptr);
87}
88
89bool MHZ19Component::mhz19_write_command_(const uint8_t *command, uint8_t *response) {
90 // Empty RX Buffer
91 while (this->available())
92 this->read();
93 this->write_array(command, MHZ19_REQUEST_LENGTH);
94 this->write_byte(mhz19_checksum(command));
95 this->flush();
96
97 if (response == nullptr)
98 return true;
99
100 return this->read_array(response, MHZ19_RESPONSE_LENGTH);
101}
104 ESP_LOGCONFIG(TAG, "MH-Z19:");
105 LOG_SENSOR(" ", "CO2", this->co2_sensor_);
106 LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
107 this->check_uart_settings(9600);
108
109 if (this->abc_boot_logic_ == MHZ19_ABC_ENABLED) {
110 ESP_LOGCONFIG(TAG, " Automatic baseline calibration enabled on boot");
111 } else if (this->abc_boot_logic_ == MHZ19_ABC_DISABLED) {
112 ESP_LOGCONFIG(TAG, " Automatic baseline calibration disabled on boot");
113 }
114
115 ESP_LOGCONFIG(TAG, " Warmup time: %" PRIu32 " s", this->warmup_seconds_);
116}
117
118} // namespace mhz19
119} // namespace esphome
uint8_t checksum
Definition bl0906.h:3
uint8_t status
Definition bl0942.h:8
void status_set_warning(const char *message="unspecified")
void status_clear_warning()
void dump_config() override
Definition mhz19.cpp:103
float get_setup_priority() const override
Definition mhz19.cpp:102
sensor::Sensor * temperature_sensor_
Definition mhz19.h:33
sensor::Sensor * co2_sensor_
Definition mhz19.h:34
bool mhz19_write_command_(const uint8_t *command, uint8_t *response)
Definition mhz19.cpp:89
MHZ19ABCLogic abc_boot_logic_
Definition mhz19.h:35
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:39
optional< std::array< uint8_t, N > > read_array()
Definition uart.h:33
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
Definition uart.cpp:13
void write_byte(uint8_t data)
Definition uart.h:19
void write_array(const uint8_t *data, size_t len)
Definition uart.h:21
@ MHZ19_ABC_DISABLED
Definition mhz19.h:11
@ MHZ19_ABC_ENABLED
Definition mhz19.h:11
uint8_t mhz19_checksum(const uint8_t *command)
Definition mhz19.cpp:17
const float DATA
For components that import data from directly connected sensors like DHT.
Definition component.cpp:19
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27