ESPHome 2026.10.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(
27 TAG, " Mains Filter: %s",
28 (filter_ == FILTER_60HZ ? LOG_STR_LITERAL("60 Hz")
29 : (filter_ == FILTER_50HZ ? LOG_STR_LITERAL("50 Hz") : LOG_STR_LITERAL("Unknown!"))));
31 ESP_LOGCONFIG(TAG, " Thermocouple Type: Unknown");
32 } else {
33 ESP_LOGCONFIG(TAG, " Thermocouple Type: %c", "BEJKNRST"[this->thermocouple_type_]);
34 }
35
36 LOG_UPDATE_INTERVAL(this);
37}
38
40 ESP_LOGVV(TAG, "update");
41
43
44 // Datasheet max conversion time for 1 shot is 155ms for 60Hz / 185ms for 50Hz
45 this->set_timeout("MAX31856Sensor::read_thermocouple_temperature_", filter_ == FILTER_60HZ ? 155 : 185,
46 [this]() { this->read_thermocouple_temperature_(); });
47}
48
50 if (this->has_fault_()) {
51 // Faults have been logged, clear it for next loop
52 this->clear_fault_();
53 } else {
54 int32_t temp24 = this->read_register24_(MAX31856_LTCBH_REG);
55 if (temp24 & 0x800000) {
56 temp24 |= 0xFF000000; // fix sign
57 }
58
59 temp24 >>= 5; // bottom 5 bits are unused
60
61 float temp_c = temp24;
62 temp_c *= 0.0078125;
63
64 ESP_LOGD(TAG, "Got thermocouple temperature: %.2f°C", temp_c);
65 this->publish_state(temp_c);
66 }
67}
68
70 ESP_LOGVV(TAG, "one_shot_temperature_");
72
73 uint8_t t = this->read_register_(MAX31856_CR0_REG);
74
75 t &= ~MAX31856_CR0_AUTOCONVERT; // turn off autoconversion mode
76 t |= MAX31856_CR0_1SHOT; // turn on one shot mode
77
79}
80
82 ESP_LOGVV(TAG, "read_fault_");
83 uint8_t faults = this->read_register_(MAX31856_SR_REG);
84
85 if (faults == 0) {
86 ESP_LOGV(TAG, "status_set_warning");
88 return false;
89 }
90
91 ESP_LOGV(TAG, "status_set_warning");
92 this->status_set_warning();
93
95 ESP_LOGW(TAG, "Cold Junction Out-of-Range: '%s'", this->name_.c_str());
96 }
98 ESP_LOGW(TAG, "Thermocouple Out-of-Range: '%s'", this->name_.c_str());
99 }
101 ESP_LOGW(TAG, "Cold-Junction High Fault: '%s'", this->name_.c_str());
102 }
103 if ((faults & MAX31856_FAULT_CJLOW) == MAX31856_FAULT_CJLOW) {
104 ESP_LOGW(TAG, "Cold-Junction Low Fault: '%s'", this->name_.c_str());
105 }
107 ESP_LOGW(TAG, "Thermocouple Temperature High Fault: '%s'", this->name_.c_str());
108 }
109 if ((faults & MAX31856_FAULT_TCLOW) == MAX31856_FAULT_TCLOW) {
110 ESP_LOGW(TAG, "Thermocouple Temperature Low Fault: '%s'", this->name_.c_str());
111 }
112 if ((faults & MAX31856_FAULT_OVUV) == MAX31856_FAULT_OVUV) {
113 ESP_LOGW(TAG, "Overvoltage or Undervoltage Input Fault: '%s'", this->name_.c_str());
114 }
115 if ((faults & MAX31856_FAULT_OPEN) == MAX31856_FAULT_OPEN) {
116 ESP_LOGW(TAG, "Thermocouple Open-Circuit Fault (possibly not connected): '%s'", this->name_.c_str());
117 }
118
119 return true;
120}
121
123 ESP_LOGV(TAG, "clear_fault_");
124 uint8_t t = this->read_register_(MAX31856_CR0_REG);
125
126 t |= MAX31856_CR0_FAULT; // turn on fault interrupt mode
127 t |= MAX31856_CR0_FAULTCLR; // enable the fault status clear bit
128
130}
131
135 type = MAX31856_TCTYPE_K;
136 } else {
137 type = this->thermocouple_type_;
138 }
139 ESP_LOGCONFIG(TAG, "set_thermocouple_type_: 0x%02X", type);
140 uint8_t t = this->read_register_(MAX31856_CR1_REG);
141 t &= 0xF0; // mask off bottom 4 bits
142 t |= (uint8_t) type & 0x0F;
144}
145
147 ESP_LOGCONFIG(TAG, "set_noise_filter_: 0x%02X", filter_);
148 uint8_t t = this->read_register_(MAX31856_CR0_REG);
149 if (filter_ == FILTER_50HZ) {
150 t |= 0x01;
151 ESP_LOGCONFIG(TAG, "set_noise_filter_: 50 Hz, t==0x%02X", t);
152 } else {
153 t &= 0xfe;
154 ESP_LOGCONFIG(TAG, "set_noise_filter_: 60 Hz, t==0x%02X", t);
155 }
157}
158
159void MAX31856Sensor::write_register_(uint8_t reg, uint8_t value) {
160 ESP_LOGVV(TAG, "write_register_ raw reg=0x%02X value=0x%02X", reg, value);
161 reg |= SPI_WRITE_M;
162 ESP_LOGVV(TAG, "write_register_ masked reg=0x%02X value=0x%02X", reg, value);
163 this->enable();
164 ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
165 this->write_byte(reg);
166 ESP_LOGVV(TAG, "write_byte value=0x%02X", value);
167 this->write_byte(value);
168 this->disable();
169 ESP_LOGV(TAG, "write_register_ 0x%02X: 0x%02X", reg, value);
170}
171
172uint8_t MAX31856Sensor::read_register_(uint8_t reg) {
173 ESP_LOGVV(TAG, "read_register_ 0x%02X", reg);
174 this->enable();
175 ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
176 this->write_byte(reg);
177 const uint8_t value(this->read_byte());
178 ESP_LOGVV(TAG, "read_byte value=0x%02X", value);
179 this->disable();
180 ESP_LOGV(TAG, "read_register_ reg=0x%02X: value=0x%02X", reg, value);
181 return value;
182}
183
185 ESP_LOGVV(TAG, "read_register_24_ 0x%02X", reg);
186 this->enable();
187 ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
188 this->write_byte(reg);
189 const uint8_t msb(this->read_byte());
190 ESP_LOGVV(TAG, "read_byte msb=0x%02X", msb);
191 const uint8_t mid(this->read_byte());
192 ESP_LOGVV(TAG, "read_byte mid=0x%02X", mid);
193 const uint8_t lsb(this->read_byte());
194 ESP_LOGVV(TAG, "read_byte lsb=0x%02X", lsb);
195 this->disable();
196 const uint32_t value((msb << 16) | (mid << 8) | lsb);
197 ESP_LOGV(TAG, "read_register_24_ reg=0x%02X: value=0x%06" PRIX32, reg, value);
198 return value;
199}
200
201} // namespace esphome::max31856
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:289
constexpr const char * c_str() const
Definition string_ref.h:73
void write_register_(uint8_t reg, uint8_t value)
Definition max31856.cpp:159
MAX31856ConfigFilter filter_
Definition max31856.h:85
MAX31856ThermocoupleType thermocouple_type_
Definition max31856.h:86
uint32_t read_register24_(uint8_t reg)
Definition max31856.cpp:184
uint8_t read_register_(uint8_t reg)
Definition max31856.cpp:172
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