ESPHome 2026.1.0-dev
Loading...
Searching...
No Matches
hc8.cpp
Go to the documentation of this file.
1#include "hc8.h"
4#include "esphome/core/log.h"
5
6#include <array>
7
8namespace esphome::hc8 {
9
10static const char *const TAG = "hc8";
11static const std::array<uint8_t, 5> HC8_COMMAND_GET_PPM{0x64, 0x69, 0x03, 0x5E, 0x4E};
12static const std::array<uint8_t, 3> HC8_COMMAND_CALIBRATE_PREAMBLE{0x11, 0x03, 0x03};
13
15 // send an initial query to the device, this will
16 // get it out of "active output mode", where it
17 // generates data every second
18 this->write_array(HC8_COMMAND_GET_PPM);
19 this->flush();
20
21 // ensure the buffer is empty
22 while (this->available())
23 this->read();
24}
25
27 uint32_t now_ms = App.get_loop_component_start_time();
28 uint32_t warmup_ms = this->warmup_seconds_ * 1000;
29 if (now_ms < warmup_ms) {
30 ESP_LOGW(TAG, "HC8 warming up, %" PRIu32 " s left", (warmup_ms - now_ms) / 1000);
31 this->status_set_warning();
32 return;
33 }
34
35 while (this->available())
36 this->read();
37
38 this->write_array(HC8_COMMAND_GET_PPM);
39 this->flush();
40
41 // the sensor is a bit slow in responding, so trying to
42 // read immediately after sending a query will timeout
43 this->set_timeout(50, [this]() {
44 std::array<uint8_t, 14> response;
45 if (!this->read_array(response.data(), response.size())) {
46 ESP_LOGW(TAG, "Reading data from HC8 failed!");
47 this->status_set_warning();
48 return;
49 }
50
51 if (response[0] != 0x64 || response[1] != 0x69) {
52 ESP_LOGW(TAG, "Invalid preamble from HC8!");
53 this->status_set_warning();
54 return;
55 }
56
57 if (crc16(response.data(), 12) != encode_uint16(response[13], response[12])) {
58 ESP_LOGW(TAG, "HC8 Checksum mismatch");
59 this->status_set_warning();
60 return;
61 }
62
64
65 const uint16_t ppm = encode_uint16(response[5], response[4]);
66 ESP_LOGD(TAG, "HC8 Received CO₂=%uppm", ppm);
67 if (this->co2_sensor_ != nullptr)
68 this->co2_sensor_->publish_state(ppm);
69 });
70}
71
72void HC8Component::calibrate(uint16_t baseline) {
73 ESP_LOGD(TAG, "HC8 Calibrating baseline to %uppm", baseline);
74
75 std::array<uint8_t, 6> command{};
76 std::copy(begin(HC8_COMMAND_CALIBRATE_PREAMBLE), end(HC8_COMMAND_CALIBRATE_PREAMBLE), begin(command));
77 command[3] = baseline >> 8;
78 command[4] = baseline;
79 command[5] = 0;
80
81 // the last byte is a checksum over the data
82 for (uint8_t i = 0; i < 5; ++i)
83 command[5] -= command[i];
84
85 this->write_array(command);
86 this->flush();
87}
88
90
92 ESP_LOGCONFIG(TAG, "HC8:");
93 LOG_SENSOR(" ", "CO2", this->co2_sensor_);
94 this->check_uart_settings(9600);
95
96 ESP_LOGCONFIG(TAG, " Warmup time: %" PRIu32 " s", this->warmup_seconds_);
97}
98
99} // namespace esphome::hc8
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void status_set_warning(const char *message=nullptr)
void status_clear_warning()
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
void calibrate(uint16_t baseline)
Definition hc8.cpp:72
uint32_t warmup_seconds_
Definition hc8.h:27
float get_setup_priority() const override
Definition hc8.cpp:89
void update() override
Definition hc8.cpp:26
sensor::Sensor * co2_sensor_
Definition hc8.h:26
void dump_config() override
Definition hc8.cpp:91
void setup() override
Definition hc8.cpp:14
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:77
optional< std::array< uint8_t, N > > read_array()
Definition uart.h:38
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:12
void write_array(const uint8_t *data, size_t len)
Definition uart.h:26
const float DATA
For components that import data from directly connected sensors like DHT.
Definition component.cpp:81
uint16_t crc16(const uint8_t *data, uint16_t len, uint16_t crc, uint16_t reverse_poly, bool refin, bool refout)
Calculate a CRC-16 checksum of data with size len.
Definition helpers.cpp:72
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:420
Application App
Global storage of Application pointer - only one Application can exist.
uint8_t end[39]
Definition sun_gtil2.cpp:17