ESPHome  2024.4.1
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  LOG_UPDATE_INTERVAL(this);
36 }
37 
39  ESP_LOGVV(TAG, "update");
40 
41  this->one_shot_temperature_();
42 
43  // Datasheet max conversion time for 1 shot is 155ms for 60Hz / 185ms for 50Hz
44  auto f = std::bind(&MAX31856Sensor::read_thermocouple_temperature_, this);
45  this->set_timeout("MAX31856Sensor::read_thermocouple_temperature_", filter_ == FILTER_60HZ ? 155 : 185, f);
46 }
47 
49  if (this->has_fault_()) {
50  // Faults have been logged, clear it for next loop
51  this->clear_fault_();
52  } else {
53  int32_t temp24 = this->read_register24_(MAX31856_LTCBH_REG);
54  if (temp24 & 0x800000) {
55  temp24 |= 0xFF000000; // fix sign
56  }
57 
58  temp24 >>= 5; // bottom 5 bits are unused
59 
60  float temp_c = temp24;
61  temp_c *= 0.0078125;
62 
63  ESP_LOGD(TAG, "Got thermocouple temperature: %.2f°C", temp_c);
64  this->publish_state(temp_c);
65  }
66 }
67 
69  ESP_LOGVV(TAG, "one_shot_temperature_");
71 
72  uint8_t t = this->read_register_(MAX31856_CR0_REG);
73 
74  t &= ~MAX31856_CR0_AUTOCONVERT; // turn off autoconversion mode
75  t |= MAX31856_CR0_1SHOT; // turn on one shot mode
76 
78 }
79 
81  ESP_LOGVV(TAG, "read_fault_");
82  uint8_t faults = this->read_register_(MAX31856_SR_REG);
83 
84  if (faults == 0) {
85  ESP_LOGV(TAG, "status_set_warning");
86  this->status_clear_warning();
87  return false;
88  }
89 
90  ESP_LOGV(TAG, "status_set_warning");
91  this->status_set_warning();
92 
93  if ((faults & MAX31856_FAULT_CJRANGE) == MAX31856_FAULT_CJRANGE) {
94  ESP_LOGW(TAG, "Cold Junction Out-of-Range: '%s'...", this->name_.c_str());
95  }
97  ESP_LOGW(TAG, "Thermocouple Out-of-Range: '%s'...", this->name_.c_str());
98  }
99  if ((faults & MAX31856_FAULT_CJHIGH) == MAX31856_FAULT_CJHIGH) {
100  ESP_LOGW(TAG, "Cold-Junction High Fault: '%s'...", this->name_.c_str());
101  }
102  if ((faults & MAX31856_FAULT_CJLOW) == MAX31856_FAULT_CJLOW) {
103  ESP_LOGW(TAG, "Cold-Junction Low Fault: '%s'...", this->name_.c_str());
104  }
105  if ((faults & MAX31856_FAULT_TCHIGH) == MAX31856_FAULT_TCHIGH) {
106  ESP_LOGW(TAG, "Thermocouple Temperature High Fault: '%s'...", this->name_.c_str());
107  }
108  if ((faults & MAX31856_FAULT_TCLOW) == MAX31856_FAULT_TCLOW) {
109  ESP_LOGW(TAG, "Thermocouple Temperature Low Fault: '%s'...", this->name_.c_str());
110  }
111  if ((faults & MAX31856_FAULT_OVUV) == MAX31856_FAULT_OVUV) {
112  ESP_LOGW(TAG, "Overvoltage or Undervoltage Input Fault: '%s'...", this->name_.c_str());
113  }
114  if ((faults & MAX31856_FAULT_OPEN) == MAX31856_FAULT_OPEN) {
115  ESP_LOGW(TAG, "Thermocouple Open-Circuit Fault (possibly not connected): '%s'...", this->name_.c_str());
116  }
117 
118  return true;
119 }
120 
122  ESP_LOGV(TAG, "clear_fault_");
123  uint8_t t = this->read_register_(MAX31856_CR0_REG);
124 
125  t |= MAX31856_CR0_FAULT; // turn on fault interrupt mode
126  t |= MAX31856_CR0_FAULTCLR; // enable the fault status clear bit
127 
129 }
130 
133  ESP_LOGCONFIG(TAG, "set_thermocouple_type_: 0x%02X", type);
134  uint8_t t = this->read_register_(MAX31856_CR1_REG);
135  t &= 0xF0; // mask off bottom 4 bits
136  t |= (uint8_t) type & 0x0F;
138 }
139 
141  ESP_LOGCONFIG(TAG, "set_noise_filter_: 0x%02X", filter_);
142  uint8_t t = this->read_register_(MAX31856_CR0_REG);
143  if (filter_ == FILTER_50HZ) {
144  t |= 0x01;
145  ESP_LOGCONFIG(TAG, "set_noise_filter_: 50 Hz, t==0x%02X", t);
146  } else {
147  t &= 0xfe;
148  ESP_LOGCONFIG(TAG, "set_noise_filter_: 60 Hz, t==0x%02X", t);
149  }
151 }
152 
153 void MAX31856Sensor::write_register_(uint8_t reg, uint8_t value) {
154  ESP_LOGVV(TAG, "write_register_ raw reg=0x%02X value=0x%02X", reg, value);
155  reg |= SPI_WRITE_M;
156  ESP_LOGVV(TAG, "write_register_ masked reg=0x%02X value=0x%02X", reg, value);
157  this->enable();
158  ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
159  this->write_byte(reg);
160  ESP_LOGVV(TAG, "write_byte value=0x%02X", value);
161  this->write_byte(value);
162  this->disable();
163  ESP_LOGV(TAG, "write_register_ 0x%02X: 0x%02X", reg, value);
164 }
165 
166 uint8_t MAX31856Sensor::read_register_(uint8_t reg) {
167  ESP_LOGVV(TAG, "read_register_ 0x%02X", reg);
168  this->enable();
169  ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
170  this->write_byte(reg);
171  const uint8_t value(this->read_byte());
172  ESP_LOGVV(TAG, "read_byte value=0x%02X", value);
173  this->disable();
174  ESP_LOGV(TAG, "read_register_ reg=0x%02X: value=0x%02X", reg, value);
175  return value;
176 }
177 
178 uint32_t MAX31856Sensor::read_register24_(uint8_t reg) {
179  ESP_LOGVV(TAG, "read_register_24_ 0x%02X", reg);
180  this->enable();
181  ESP_LOGVV(TAG, "write_byte reg=0x%02X", reg);
182  this->write_byte(reg);
183  const uint8_t msb(this->read_byte());
184  ESP_LOGVV(TAG, "read_byte msb=0x%02X", msb);
185  const uint8_t mid(this->read_byte());
186  ESP_LOGVV(TAG, "read_byte mid=0x%02X", mid);
187  const uint8_t lsb(this->read_byte());
188  ESP_LOGVV(TAG, "read_byte lsb=0x%02X", lsb);
189  this->disable();
190  const uint32_t value((msb << 16) | (mid << 8) | lsb);
191  ESP_LOGV(TAG, "read_register_24_ reg=0x%02X: value=0x%06" PRIX32, reg, value);
192  return value;
193 }
194 
196 
197 } // namespace max31856
198 } // 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:85
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:178
GPIOPin * cs_
Definition: spi.h:395
Fault status Thermocouple Temperature Low Fault flag.
Definition: max31856.h:46
void write_register_(uint8_t reg, uint8_t value)
Definition: max31856.cpp:153
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:55
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:166
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
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
Config 0 fault clear flag.
Definition: max31856.h:23
float get_setup_priority() const override
Definition: max31856.cpp:195
Fault status Thermocouple Out-of-Range flag.
Definition: max31856.h:42
Cold-Junction Temperature Offset Register.
Definition: max31856.h:33