ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
hdc302x.cpp
Go to the documentation of this file.
1#include "hdc302x.h"
2
3#include "esphome/core/hal.h"
5#include "esphome/core/log.h"
6
7namespace esphome::hdc302x {
8
9ESPHOME_LOG_TAG(TAG, "hdc302x.sensor");
10
11static constexpr uint32_t HEATER_OFF_TIMEOUT_ID = 0;
12
13// Commands (per datasheet Table 7-4)
14static const uint8_t HDC302X_CMD_SOFT_RESET[2] = {0x30, 0xa2};
15static const uint8_t HDC302X_CMD_CLEAR_STATUS_REGISTER[2] = {0x30, 0x41};
16
17static const uint8_t HDC302X_CMD_TRIGGER_MSB = 0x24;
18
19static const uint8_t HDC302X_CMD_HEATER_ENABLE[2] = {0x30, 0x6d};
20static const uint8_t HDC302X_CMD_HEATER_DISABLE[2] = {0x30, 0x66};
21static const uint8_t HDC302X_CMD_HEATER_CONFIGURE[2] = {0x30, 0x6e};
22
24 // Soft reset the device
25 if (this->write(HDC302X_CMD_SOFT_RESET, 2) != i2c::ERROR_OK) {
26 this->mark_failed(LOG_STR("Soft reset failed"));
27 return;
28 }
29 // Delay SensorRR (reset ready), per datasheet, 6.5.
30 delay(3);
31
32 // Clear status register
33 if (this->write(HDC302X_CMD_CLEAR_STATUS_REGISTER, 2) != i2c::ERROR_OK) {
34 this->mark_failed(LOG_STR("Clear status failed"));
35 return;
36 }
37}
38
40 ESP_LOGCONFIG(TAG,
41 "HDC302x:\n"
42 " Heater: %s",
43 this->heater_active_ ? LOG_STR_LITERAL("active") : LOG_STR_LITERAL("inactive"));
44 LOG_I2C_DEVICE(this);
45 LOG_UPDATE_INTERVAL(this);
46 LOG_SENSOR(" ", "Temperature", this->temp_sensor_);
47 LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
48}
49
51 uint8_t cmd[] = {
52 HDC302X_CMD_TRIGGER_MSB,
53 this->power_mode_,
54 };
55 if (this->write(cmd, 2) != i2c::ERROR_OK) {
56 this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
57 return;
58 }
59
60 // Read data after ADC conversion has completed
61 this->set_timeout(this->conversion_delay_ms_(), [this]() { this->read_data_(); });
62}
63
64void HDC302XComponent::start_heater(uint16_t power, uint32_t duration_ms) {
65 if (!this->disable_heater_()) {
66 ESP_LOGD(TAG, "Heater disable before start failed");
67 }
68 if (!this->configure_heater_(power) || !this->enable_heater_()) {
69 ESP_LOGW(TAG, "Heater start failed");
70 return;
71 }
72 this->heater_active_ = true;
73 this->cancel_timeout(HEATER_OFF_TIMEOUT_ID);
74 if (duration_ms > 0) {
75 this->set_timeout(HEATER_OFF_TIMEOUT_ID, duration_ms, [this]() { this->stop_heater(); });
76 }
77}
78
80 this->cancel_timeout(HEATER_OFF_TIMEOUT_ID);
81 if (!this->disable_heater_()) {
82 ESP_LOGW(TAG, "Heater stop failed");
83 }
84 this->heater_active_ = false;
85}
86
88 if (this->write(HDC302X_CMD_HEATER_ENABLE, 2) != i2c::ERROR_OK) {
89 ESP_LOGE(TAG, "Enable heater failed");
90 return false;
91 }
92 return true;
93}
94
95bool HDC302XComponent::configure_heater_(uint16_t power_level) {
96 if (power_level > 0x3fff) {
97 ESP_LOGW(TAG, "Heater power 0x%04x exceeds max 0x3fff", power_level);
98 return false;
99 }
100
101 // Heater current level config.
102 uint8_t config[] = {
103 static_cast<uint8_t>((power_level >> 8) & 0xff), // MSB
104 static_cast<uint8_t>(power_level & 0xff) // LSB
105 };
106
107 // Configure level of heater current (per datasheet 7.5.7.8).
108 uint8_t cmd[] = {
109 HDC302X_CMD_HEATER_CONFIGURE[0], HDC302X_CMD_HEATER_CONFIGURE[1], config[0], config[1],
110 crc8(config, 2, 0xff, 0x31, true),
111 };
112 if (this->write(cmd, sizeof(cmd)) != i2c::ERROR_OK) {
113 ESP_LOGE(TAG, "Configure heater failed");
114 return false;
115 }
116
117 return true;
118}
119
121 if (this->write(HDC302X_CMD_HEATER_DISABLE, 2) != i2c::ERROR_OK) {
122 ESP_LOGE(TAG, "Disable heater failed");
123 return false;
124 }
125 return true;
126}
127
129 uint8_t buf[6];
130 if (this->read(buf, 6) != i2c::ERROR_OK) {
131 this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
132 return;
133 }
134
135 // Check checksums
136 const bool crc_ok = crc8(buf, 2, 0xff, 0x31, true) == buf[2] && crc8(buf + 3, 2, 0xff, 0x31, true) == buf[5];
137 if (!this->status_comm_result(crc_ok, LOG_STR("Read data: invalid CRC")))
138 return;
139
140 if (this->temp_sensor_ != nullptr) {
141 uint16_t raw_t = encode_uint16(buf[0], buf[1]);
142 // Calculate temperature in Celsius per datasheet section 7.3.3.
143 float temp = -45 + 175 * (float(raw_t) / 65535.0f);
144 this->temp_sensor_->publish_state(temp);
145 }
146
147 if (this->humidity_sensor_ != nullptr) {
148 uint16_t raw_rh = encode_uint16(buf[3], buf[4]);
149 // Calculate RH% per datasheet section 7.3.3.
150 float humidity = 100 * (float(raw_rh) / 65535.0f);
151 this->humidity_sensor_->publish_state(humidity);
152 }
153}
154
156 // ADC conversion delay per datasheet, Table 7-5. - Trigger on Demand
157 switch (this->power_mode_) {
159 return 8;
161 return 5;
163 return 4;
165 default:
166 return 13;
167 }
168}
169
170} // namespace esphome::hdc302x
void mark_failed()
Mark this component as failed.
bool status_comm_result(bool ok)
Clears the warning when ok, else sets it with message (default "Communication failed"); returns ok.
bool cancel_timeout(const char *name)
Cancel a timeout function.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
Definition component.cpp:96
sensor::Sensor * humidity_sensor_
Definition hdc302x.h:38
void start_heater(uint16_t power, uint32_t duration_ms)
Definition hdc302x.cpp:64
sensor::Sensor * temp_sensor_
Definition hdc302x.h:37
bool configure_heater_(uint16_t power_level)
Definition hdc302x.cpp:95
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
Definition i2c.h:195
ErrorCode read(uint8_t *data, size_t len) const
reads an array of bytes from the device using an I2CBus
Definition i2c.h:175
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
ESPHOME_LOG_TAG(TAG, "hdc302x.sensor")
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:15
uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc, uint8_t poly, bool msb_first)
Calculate a CRC-8 checksum of data with size len.
Definition helpers.cpp:68
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:998
void HOT delay(uint32_t ms)
Definition hal.cpp:85
static void uint32_t