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