ESPHome  2024.4.1
mlx90614.cpp
Go to the documentation of this file.
1 #include "mlx90614.h"
2 
3 #include "esphome/core/hal.h"
4 #include "esphome/core/log.h"
5 
6 namespace esphome {
7 namespace mlx90614 {
8 
9 static const uint8_t MLX90614_RAW_IR_1 = 0x04;
10 static const uint8_t MLX90614_RAW_IR_2 = 0x05;
11 static const uint8_t MLX90614_TEMPERATURE_AMBIENT = 0x06;
12 static const uint8_t MLX90614_TEMPERATURE_OBJECT_1 = 0x07;
13 static const uint8_t MLX90614_TEMPERATURE_OBJECT_2 = 0x08;
14 
15 static const uint8_t MLX90614_TOMAX = 0x20;
16 static const uint8_t MLX90614_TOMIN = 0x21;
17 static const uint8_t MLX90614_PWMCTRL = 0x22;
18 static const uint8_t MLX90614_TARANGE = 0x23;
19 static const uint8_t MLX90614_EMISSIVITY = 0x24;
20 static const uint8_t MLX90614_CONFIG = 0x25;
21 static const uint8_t MLX90614_ADDR = 0x2E;
22 static const uint8_t MLX90614_ID1 = 0x3C;
23 static const uint8_t MLX90614_ID2 = 0x3D;
24 static const uint8_t MLX90614_ID3 = 0x3E;
25 static const uint8_t MLX90614_ID4 = 0x3F;
26 
27 static const char *const TAG = "mlx90614";
28 
30  ESP_LOGCONFIG(TAG, "Setting up MLX90614...");
31  if (!this->write_emissivity_()) {
32  ESP_LOGE(TAG, "Communication with MLX90614 failed!");
33  this->mark_failed();
34  return;
35  }
36 }
37 
39  if (std::isnan(this->emissivity_))
40  return true;
41  uint16_t value = (uint16_t) (this->emissivity_ * 65535);
42  if (!this->write_bytes_(MLX90614_EMISSIVITY, 0)) {
43  return false;
44  }
45  delay(10);
46  if (!this->write_bytes_(MLX90614_EMISSIVITY, value)) {
47  return false;
48  }
49  delay(10);
50  return true;
51 }
52 
53 uint8_t MLX90614Component::crc8_pec_(const uint8_t *data, uint8_t len) {
54  uint8_t crc = 0;
55  for (uint8_t i = 0; i < len; i++) {
56  uint8_t in = data[i];
57  for (uint8_t j = 0; j < 8; j++) {
58  bool carry = (crc ^ in) & 0x80;
59  crc <<= 1;
60  if (carry)
61  crc ^= 0x07;
62  in <<= 1;
63  }
64  }
65  return crc;
66 }
67 
68 bool MLX90614Component::write_bytes_(uint8_t reg, uint16_t data) {
69  uint8_t buf[5];
70  buf[0] = this->address_ << 1;
71  buf[1] = reg;
72  buf[2] = data & 0xFF;
73  buf[3] = data >> 8;
74  buf[4] = this->crc8_pec_(buf, 4);
75  return this->write_bytes(reg, buf + 2, 3);
76 }
77 
79  ESP_LOGCONFIG(TAG, "MLX90614:");
80  LOG_I2C_DEVICE(this);
81  if (this->is_failed()) {
82  ESP_LOGE(TAG, "Communication with MLX90614 failed!");
83  }
84  LOG_UPDATE_INTERVAL(this);
85  LOG_SENSOR(" ", "Ambient", this->ambient_sensor_);
86  LOG_SENSOR(" ", "Object", this->object_sensor_);
87 }
88 
90 
92  uint8_t emissivity[3];
93  if (this->read_register(MLX90614_EMISSIVITY, emissivity, 3, false) != i2c::ERROR_OK) {
94  this->status_set_warning();
95  return;
96  }
97  uint8_t raw_object[3];
98  if (this->read_register(MLX90614_TEMPERATURE_OBJECT_1, raw_object, 3, false) != i2c::ERROR_OK) {
99  this->status_set_warning();
100  return;
101  }
102 
103  uint8_t raw_ambient[3];
104  if (this->read_register(MLX90614_TEMPERATURE_AMBIENT, raw_ambient, 3, false) != i2c::ERROR_OK) {
105  this->status_set_warning();
106  return;
107  }
108 
109  float ambient = raw_ambient[1] & 0x80 ? NAN : encode_uint16(raw_ambient[1], raw_ambient[0]) * 0.02f - 273.15f;
110  float object = raw_object[1] & 0x80 ? NAN : encode_uint16(raw_object[1], raw_object[0]) * 0.02f - 273.15f;
111 
112  ESP_LOGD(TAG, "Got Temperature=%.1f°C Ambient=%.1f°C", object, ambient);
113 
114  if (this->ambient_sensor_ != nullptr && !std::isnan(ambient))
115  this->ambient_sensor_->publish_state(ambient);
116  if (this->object_sensor_ != nullptr && !std::isnan(object))
117  this->object_sensor_->publish_state(object);
118  this->status_clear_warning();
119 }
120 
121 } // namespace mlx90614
122 } // namespace esphome
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop=true)
reads an array of bytes from a specific register in the I²C device
Definition: i2c.cpp:10
sensor::Sensor * ambient_sensor_
Definition: mlx90614.h:28
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition: i2c.h:149
float get_setup_priority() const override
Definition: mlx90614.cpp:89
uint8_t crc8_pec_(const uint8_t *data, uint8_t len)
Definition: mlx90614.cpp:53
No error found during execution of method.
Definition: i2c_bus.h:13
void status_clear_warning()
Definition: component.cpp:166
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition: helpers.h:182
uint8_t address_
store the address of the device on the bus
Definition: i2c.h:269
bool write_bytes_(uint8_t reg, uint16_t data)
Definition: mlx90614.cpp:68
std::string size_t len
Definition: helpers.h:292
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len, bool stop=true)
Definition: i2c.h:248