ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
dallas_temp.cpp
Go to the documentation of this file.
1#include "dallas_temp.h"
3#include "esphome/core/log.h"
4
6
7ESPHOME_LOG_TAG(TAG, "dallas.temp.sensor");
8
9static constexpr uint32_t CONVERSION_TIMEOUT_ID = 0;
10
11static const uint8_t DALLAS_MODEL_DS18S20 = 0x10;
12static const uint8_t DALLAS_MODEL_DS18B20 = 0x28;
13static const uint8_t DALLAS_COMMAND_START_CONVERSION = 0x44;
14static const uint8_t DALLAS_COMMAND_READ_SCRATCH_PAD = 0xBE;
15static const uint8_t DALLAS_COMMAND_WRITE_SCRATCH_PAD = 0x4E;
16static const uint8_t DALLAS_COMMAND_COPY_SCRATCH_PAD = 0x48;
17
19 switch (this->resolution_) {
20 case 9:
21 return 94;
22 case 10:
23 return 188;
24 case 11:
25 return 375;
26 default:
27 return 750;
28 }
29}
30
32 ESP_LOGCONFIG(TAG, "Dallas Temperature Sensor:");
33 if (this->address_ == 0) {
34 ESP_LOGW(TAG, " Unable to select an address");
35 return;
36 }
37 LOG_ONE_WIRE_DEVICE(this);
38 ESP_LOGCONFIG(TAG, " Resolution: %u bits", this->resolution_);
39 LOG_UPDATE_INTERVAL(this);
40}
41
43 if (this->address_ == 0)
44 return;
45
47
48 this->send_command_(DALLAS_COMMAND_START_CONVERSION);
49
50 this->set_timeout(CONVERSION_TIMEOUT_ID, this->millis_to_wait_for_conversion_(), [this] {
51 if (!this->read_scratch_pad_() || !this->check_scratch_pad_()) {
52 this->publish_state(NAN);
53 return;
54 }
55
56 float tempc = this->get_temp_c_();
57 ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", LOG_STR_ARG(this->get_log_name()), tempc);
58 this->publish_state(tempc);
59 });
60}
61
63 bool success = this->send_command_(DALLAS_COMMAND_READ_SCRATCH_PAD);
64 if (success) {
65 for (uint8_t &i : this->scratch_pad_) {
66 i = this->bus_->read8();
67 }
68 } else {
69 ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", LOG_STR_ARG(this->get_log_name()));
70 this->status_set_warning(LOG_STR("bus reset failed"));
71 }
72 return success;
73}
74
76 if (!this->check_address_or_index_())
77 return;
78 if (!this->read_scratch_pad_())
79 return;
80 if (!this->check_scratch_pad_())
81 return;
82
83 if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) {
84 // DS18S20 doesn't support resolution.
85 ESP_LOGW(TAG, "DS18S20 doesn't support setting resolution");
86 return;
87 }
88
89 uint8_t res;
90 switch (this->resolution_) {
91 case 12:
92 res = 0x7F;
93 break;
94 case 11:
95 res = 0x5F;
96 break;
97 case 10:
98 res = 0x3F;
99 break;
100 case 9:
101 default:
102 res = 0x1F;
103 break;
104 }
105
106 if (this->scratch_pad_[4] == res)
107 return;
108 this->scratch_pad_[4] = res;
109
110 if (this->send_command_(DALLAS_COMMAND_WRITE_SCRATCH_PAD)) {
111 this->bus_->write8(this->scratch_pad_[2]); // high alarm temp
112 this->bus_->write8(this->scratch_pad_[3]); // low alarm temp
113 this->bus_->write8(this->scratch_pad_[4]); // resolution
114 }
115
116 // write value to EEPROM
117 this->send_command_(DALLAS_COMMAND_COPY_SCRATCH_PAD);
118}
119
121 bool chksum_validity = (crc8(this->scratch_pad_, 8) == this->scratch_pad_[8]);
122
123#ifdef ESPHOME_LOG_LEVEL_VERY_VERBOSE
124 ESP_LOGVV(TAG, "Scratch pad: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X (%02X)", this->scratch_pad_[0],
125 this->scratch_pad_[1], this->scratch_pad_[2], this->scratch_pad_[3], this->scratch_pad_[4],
126 this->scratch_pad_[5], this->scratch_pad_[6], this->scratch_pad_[7], this->scratch_pad_[8],
127 crc8(this->scratch_pad_, 8));
128#endif
129 if (!chksum_validity) {
130 this->status_set_warning(LOG_STR("scratch pad checksum invalid"));
131 ESP_LOGD(TAG, "Scratch pad: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X (%02X)", this->scratch_pad_[0],
132 this->scratch_pad_[1], this->scratch_pad_[2], this->scratch_pad_[3], this->scratch_pad_[4],
133 this->scratch_pad_[5], this->scratch_pad_[6], this->scratch_pad_[7], this->scratch_pad_[8],
134 crc8(this->scratch_pad_, 8));
135 }
136 return chksum_validity;
137}
138
140 int16_t temp = encode_value_le<int16_t>(this->scratch_pad_);
141 if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) {
142 if (this->scratch_pad_[7] == 0) {
143 return NAN;
144 }
145 return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25f;
146 }
147 switch (this->resolution_) {
148 case 9:
149 temp &= 0xfff8;
150 break;
151 case 10:
152 temp &= 0xfffc;
153 break;
154 case 11:
155 temp &= 0xfffe;
156 break;
157 case 12:
158 default:
159 break;
160 }
161 // undocumented test for powerup measurement of 85
162 // https://github.com/cpetrich/counterfeit_DS18B20#solution-to-the-85-c-problem
163 if ((this->address_ & 0xff) == DALLAS_MODEL_DS18B20) {
164 if ((temp == 85 * 16) && (this->scratch_pad_[6] == 0xc)) {
165 ESP_LOGD(TAG, "dropping reading caused by sensor reset");
166 return NAN;
167 }
168 }
169 return temp / 16.0f;
170}
171
172} // namespace esphome::dallas_temp
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
void status_clear_warning()
Definition component.h:296
const LogString * get_log_name() const
Get the name for a "%s" log argument (LOG_STR_ARG).
uint16_t millis_to_wait_for_conversion_() const
Get the number of milliseconds we have to wait for the conversion phase.
virtual void write8(uint8_t val)=0
Write a word to the bus. LSB first.
virtual uint8_t read8()=0
Read an 8 bit word from the bus.
OneWireBus * bus_
pointer to OneWireBus instance
Definition one_wire.h:33
bool send_command_(uint8_t cmd)
send command on the bus
Definition one_wire.cpp:7
bool check_address_or_index_()
find an address if necessary should be called from setup
Definition one_wire.cpp:14
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
ESPHOME_LOG_TAG(TAG, "dallas.temp.sensor")
constexpr T encode_value_le(const uint8_t *bytes)
Encode a value from its constituent bytes (from least to most significant) in an array with length si...
Definition helpers.h:1039
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
static void uint32_t