ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
max31856.cpp
Go to the documentation of this file.
1#include "max31856.h"
2
3#include "esphome/core/log.h"
4#include <cmath>
5
7
8static const char *const TAG = "max31856";
9
10// Based on Adafruit's library: https://github.com/adafruit/Adafruit_MAX31856
11
13 this->spi_setup();
14
15 // assert on any fault
18
20 this->set_noise_filter_();
21}
22
24 LOG_SENSOR("", "MAX31856", this);
25 LOG_PIN(" CS Pin: ", this->cs_);
26 ESP_LOGCONFIG(TAG, " Mains Filter: %s",
27 (filter_ == FILTER_60HZ ? "60 Hz" : (filter_ == FILTER_50HZ ? "50 Hz" : "Unknown!")));
29 ESP_LOGCONFIG(TAG, " Thermocouple Type: Unknown");
30 } else {
31 ESP_LOGCONFIG(TAG, " Thermocouple Type: %c", "BEJKNRST"[this->thermocouple_type_]);
32 }
33
34 LOG_UPDATE_INTERVAL(this);
35}
36
38 ESP_LOGVV(TAG, "update");
39
41
42 // Datasheet max conversion time for 1 shot is 155ms for 60Hz / 185ms for 50Hz
43 this->set_timeout("MAX31856Sensor::read_thermocouple_temperature_", filter_ == FILTER_60HZ ? 155 : 185,
44 [this]() { this->read_thermocouple_temperature_(); });
45}
46
48 if (this->has_fault_()) {
49 // Faults have been logged, clear it for next loop
50 this->clear_fault_();
51 } else {
52 int32_t temp24 = this->read_register24_(MAX31856_LTCBH_REG);
53 if (temp24 & 0x800000) {
54 temp24 |= 0xFF000000; // fix sign
55 }
56
57 temp24 >>= 5; // bottom 5 bits are unused
58
59 float temp_c = temp24;
60 temp_c *= 0.0078125;
61
62 ESP_LOGD(TAG, "Got thermocouple temperature: %.2f°C", temp_c);
63 this->publish_state(temp_c);
64 }
65}
66
68 ESP_LOGVV(TAG, "one_shot_temperature_");
70
71 uint8_t t = this->read_register_(MAX31856_CR0_REG);
72
73 t &= ~MAX31856_CR0_AUTOCONVERT; // turn off autoconversion mode
74 t |= MAX31856_CR0_1SHOT; // turn on one shot mode
75
77}
78
80 ESP_LOGVV(TAG, "read_fault_");
81 uint8_t faults = this->read_register_(MAX31856_SR_REG);
82
83 if (faults == 0) {
84 ESP_LOGV(TAG, "status_set_warning");
86 return false;
87 }
88
89 ESP_LOGV(TAG, "status_set_warning");
90 this->status_set_warning();
91
93 ESP_LOGW(TAG, "Cold Junction Out-of-Range: '%s'", this->name_.c_str());
94 }
96 ESP_LOGW(TAG, "Thermocouple Out-of-Range: '%s'", this->name_.c_str());
97 }
99 ESP_LOGW(TAG, "Cold-Junction High Fault: '%s'", this->name_.c_str());
100 }
101 if ((faults & MAX31856_FAULT_CJLOW) == MAX31856_FAULT_CJLOW) {
102 ESP_LOGW(TAG, "Cold-Junction Low Fault: '%s'", this->name_.c_str());
103 }
105 ESP_LOGW(TAG, "Thermocouple Temperature High Fault: '%s'", this->name_.c_str());
106 }
107 if ((faults & MAX31856_FAULT_TCLOW) == MAX31856_FAULT_TCLOW) {
108 ESP_LOGW(TAG, "Thermocouple Temperature Low Fault: '%s'", this->name_.c_str());
109 }
110 if ((faults & MAX31856_FAULT_OVUV) == MAX31856_FAULT_OVUV) {
111 ESP_LOGW(TAG, "Overvoltage or Undervoltage Input Fault: '%s'", this->name_.c_str());
112 }
113 if ((faults & MAX31856_FAULT_OPEN) == MAX31856_FAULT_OPEN) {
114 ESP_LOGW(TAG, "Thermocouple Open-Circuit Fault (possibly not connected): '%s'", this->name_.c_str());
115 }
116
117 return true;
118}
119
121 ESP_LOGV(TAG, "clear_fault_");
122 uint8_t t = this->read_register_(MAX31856_CR0_REG);
123
124 t |= MAX31856_CR0_FAULT; // turn on fault interrupt mode
125 t |= MAX31856_CR0_FAULTCLR; // enable the fault status clear bit
126
128}
129
133 type = MAX31856_TCTYPE_K;
134 } else {
135 type = this->thermocouple_type_;
136 }
137 ESP_LOGCONFIG(TAG, "set_thermocouple_type_: 0x%02X", type);
138 uint8_t t = this->read_register_(MAX31856_CR1_REG);
139 t &= 0xF0; // mask off bottom 4 bits
140 t |= (uint8_t) type & 0x0F;
142}
143
145 ESP_LOGCONFIG(TAG, "set_noise_filter_: 0x%02X", filter_);
146 uint8_t t = this->read_register_(MAX31856_CR0_REG);
147 if (filter_ == FILTER_50HZ) {
148 t |= 0x01;
149 ESP_LOGCONFIG(TAG, "set_noise_filter_: 50 Hz, t==0x%02X", t);
150 } else {
151 t &= 0xfe;
152 ESP_LOGCONFIG(TAG, "set_noise_filter_: 60 Hz, t==0x%02X", t);
153 }
155}
156
157void MAX31856Sensor::write_register_(uint8_t reg, uint8_t value) {
158 ESP_LOGVV(TAG, "write_register_ raw reg=0x%02X value=0x%02X", reg, value);
159 reg |= SPI_WRITE_M;
160 ESP_LOGVV(TAG, "write_register_ masked reg=0x%02X value=0x%02X", reg, value);
161 this->enable();
162 ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
163 this->write_byte(reg);
164 ESP_LOGVV(TAG, "write_byte value=0x%02X", value);
165 this->write_byte(value);
166 this->disable();
167 ESP_LOGV(TAG, "write_register_ 0x%02X: 0x%02X", reg, value);
168}
169
170uint8_t MAX31856Sensor::read_register_(uint8_t reg) {
171 ESP_LOGVV(TAG, "read_register_ 0x%02X", reg);
172 this->enable();
173 ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
174 this->write_byte(reg);
175 const uint8_t value(this->read_byte());
176 ESP_LOGVV(TAG, "read_byte value=0x%02X", value);
177 this->disable();
178 ESP_LOGV(TAG, "read_register_ reg=0x%02X: value=0x%02X", reg, value);
179 return value;
180}
181
183 ESP_LOGVV(TAG, "read_register_24_ 0x%02X", reg);
184 this->enable();
185 ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
186 this->write_byte(reg);
187 const uint8_t msb(this->read_byte());
188 ESP_LOGVV(TAG, "read_byte msb=0x%02X", msb);
189 const uint8_t mid(this->read_byte());
190 ESP_LOGVV(TAG, "read_byte mid=0x%02X", mid);
191 const uint8_t lsb(this->read_byte());
192 ESP_LOGVV(TAG, "read_byte lsb=0x%02X", lsb);
193 this->disable();
194 const uint32_t value((msb << 16) | (mid << 8) | lsb);
195 ESP_LOGV(TAG, "read_register_24_ reg=0x%02X: value=0x%06" PRIX32, reg, value);
196 return value;
197}
198
199} // namespace esphome::max31856
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:493
void status_clear_warning()
Definition component.h:289
constexpr const char * c_str() const
Definition string_ref.h:73
void write_register_(uint8_t reg, uint8_t value)
Definition max31856.cpp:157
MAX31856ConfigFilter filter_
Definition max31856.h:85
MAX31856ThermocoupleType thermocouple_type_
Definition max31856.h:86
uint32_t read_register24_(uint8_t reg)
Definition max31856.cpp:182
uint8_t read_register_(uint8_t reg)
Definition max31856.cpp:170
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
uint16_t type
MAX31856ThermocoupleType
Multiple types of thermocouples supported by the chip.
Definition max31856.h:53
@ MAX31856_CR0_1SHOT
Config 0 one shot convert flag.
Definition max31856.h:16
@ MAX31856_CR1_REG
Config 1 register.
Definition max31856.h:24
@ MAX31856_FAULT_TCLOW
Fault status Thermocouple Temperature Low Fault flag.
Definition max31856.h:45
@ MAX31856_CR0_FAULT
Config 0 fault mode flag.
Definition max31856.h:21
@ MAX31856_LTCBH_REG
Linearized TC Temperature, Byte 2.
Definition max31856.h:35
@ MAX31856_FAULT_TCRANGE
Fault status Thermocouple Out-of-Range flag.
Definition max31856.h:41
@ MAX31856_CR0_REG
Config 0 register.
Definition max31856.h:14
@ MAX31856_CJTO_REG
Cold-Junction Temperature Offset Register.
Definition max31856.h:32
@ MAX31856_FAULT_OPEN
Fault status Thermocouple Open-Circuit Fault flag.
Definition max31856.h:47
@ MAX31856_FAULT_CJHIGH
Fault status Cold-Junction High Fault flag.
Definition max31856.h:42
@ MAX31856_SR_REG
Fault Status Register.
Definition max31856.h:38
@ MAX31856_MASK_REG
Fault Mask register.
Definition max31856.h:25
@ MAX31856_FAULT_CJLOW
Fault status Cold-Junction Low Fault flag.
Definition max31856.h:43
@ MAX31856_FAULT_OVUV
Fault status Overvoltage or Undervoltage Input Fault flag.
Definition max31856.h:46
@ MAX31856_CR0_OCFAULT01
Config 0 open circuit fault 01 flag.
Definition max31856.h:18
@ MAX31856_FAULT_TCHIGH
Fault status Thermocouple Temperature High Fault flag.
Definition max31856.h:44
@ MAX31856_FAULT_CJRANGE
Fault status Cold Junction Out-of-Range flag.
Definition max31856.h:40
@ MAX31856_CR0_FAULTCLR
Config 0 fault clear flag.
Definition max31856.h:22
static void uint32_t