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