ESPHome  2024.3.2
hmc5883l.cpp
Go to the documentation of this file.
1 #include "hmc5883l.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace hmc5883l {
6 
7 static const char *const TAG = "hmc5883l";
8 static const uint8_t HMC5883L_ADDRESS = 0x1E;
9 static const uint8_t HMC5883L_REGISTER_CONFIG_A = 0x00;
10 static const uint8_t HMC5883L_REGISTER_CONFIG_B = 0x01;
11 static const uint8_t HMC5883L_REGISTER_MODE = 0x02;
12 static const uint8_t HMC5883L_REGISTER_DATA_X_MSB = 0x03;
13 static const uint8_t HMC5883L_REGISTER_DATA_X_LSB = 0x04;
14 static const uint8_t HMC5883L_REGISTER_DATA_Z_MSB = 0x05;
15 static const uint8_t HMC5883L_REGISTER_DATA_Z_LSB = 0x06;
16 static const uint8_t HMC5883L_REGISTER_DATA_Y_MSB = 0x07;
17 static const uint8_t HMC5883L_REGISTER_DATA_Y_LSB = 0x08;
18 static const uint8_t HMC5883L_REGISTER_STATUS = 0x09;
19 static const uint8_t HMC5883L_REGISTER_IDENTIFICATION_A = 0x0A;
20 static const uint8_t HMC5883L_REGISTER_IDENTIFICATION_B = 0x0B;
21 static const uint8_t HMC5883L_REGISTER_IDENTIFICATION_C = 0x0C;
22 
24  ESP_LOGCONFIG(TAG, "Setting up HMC5583L...");
25  uint8_t id[3];
26  if (!this->read_byte(HMC5883L_REGISTER_IDENTIFICATION_A, &id[0]) ||
27  !this->read_byte(HMC5883L_REGISTER_IDENTIFICATION_B, &id[1]) ||
28  !this->read_byte(HMC5883L_REGISTER_IDENTIFICATION_C, &id[2])) {
30  this->mark_failed();
31  return;
32  }
33 
34  if (id[0] != 0x48 || id[1] != 0x34 || id[2] != 0x33) {
35  this->error_code_ = ID_REGISTERS;
36  this->mark_failed();
37  return;
38  }
39 
40  uint8_t config_a = 0;
41  config_a |= this->oversampling_ << 5;
42  config_a |= this->datarate_ << 2;
43  config_a |= 0b0 << 0; // Measurement Mode: Normal(high impedance on load)
44  if (!this->write_byte(HMC5883L_REGISTER_CONFIG_A, config_a)) {
46  this->mark_failed();
47  return;
48  }
49 
50  uint8_t config_b = 0;
51  config_b |= this->range_ << 5;
52  if (!this->write_byte(HMC5883L_REGISTER_CONFIG_B, config_b)) {
54  this->mark_failed();
55  return;
56  }
57 
58  uint8_t mode = 0;
59  // Continuous Measurement Mode
60  mode |= 0b00;
61  if (!this->write_byte(HMC5883L_REGISTER_MODE, mode)) {
63  this->mark_failed();
64  return;
65  }
66 }
68  ESP_LOGCONFIG(TAG, "HMC5883L:");
69  LOG_I2C_DEVICE(this);
70  if (this->error_code_ == COMMUNICATION_FAILED) {
71  ESP_LOGE(TAG, "Communication with HMC5883L failed!");
72  } else if (this->error_code_ == ID_REGISTERS) {
73  ESP_LOGE(TAG, "The ID registers don't match - Is this really an HMC5883L?");
74  }
75  LOG_UPDATE_INTERVAL(this);
76 
77  LOG_SENSOR(" ", "X Axis", this->x_sensor_);
78  LOG_SENSOR(" ", "Y Axis", this->y_sensor_);
79  LOG_SENSOR(" ", "Z Axis", this->z_sensor_);
80  LOG_SENSOR(" ", "Heading", this->heading_sensor_);
81 }
84  uint16_t raw_x, raw_y, raw_z;
85  if (!this->read_byte_16(HMC5883L_REGISTER_DATA_X_MSB, &raw_x) ||
86  !this->read_byte_16(HMC5883L_REGISTER_DATA_Y_MSB, &raw_y) ||
87  !this->read_byte_16(HMC5883L_REGISTER_DATA_Z_MSB, &raw_z)) {
88  this->status_set_warning();
89  return;
90  }
91 
92  float mg_per_bit;
93  switch (this->range_) {
95  mg_per_bit = 0.073f;
96  break;
98  mg_per_bit = 0.92f;
99  break;
101  mg_per_bit = 1.22f;
102  break;
104  mg_per_bit = 1.52f;
105  break;
107  mg_per_bit = 2.27f;
108  break;
110  mg_per_bit = 2.56f;
111  break;
113  mg_per_bit = 3.03f;
114  break;
116  mg_per_bit = 4.35f;
117  break;
118  default:
119  mg_per_bit = NAN;
120  }
121 
122  // in µT
123  const float x = int16_t(raw_x) * mg_per_bit * 0.1f;
124  const float y = int16_t(raw_y) * mg_per_bit * 0.1f;
125  const float z = int16_t(raw_z) * mg_per_bit * 0.1f;
126 
127  float heading = atan2f(0.0f - x, y) * 180.0f / M_PI;
128  ESP_LOGD(TAG, "Got x=%0.02fµT y=%0.02fµT z=%0.02fµT heading=%0.01f°", x, y, z, heading);
129 
130  if (this->x_sensor_ != nullptr)
131  this->x_sensor_->publish_state(x);
132  if (this->y_sensor_ != nullptr)
133  this->y_sensor_->publish_state(y);
134  if (this->z_sensor_ != nullptr)
135  this->z_sensor_->publish_state(z);
136  if (this->heading_sensor_ != nullptr)
137  this->heading_sensor_->publish_state(heading);
138 }
139 
140 } // namespace hmc5883l
141 } // namespace esphome
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
Definition: i2c.h:235
bool read_byte_16(uint8_t a_register, uint16_t *data)
Definition: i2c.h:246
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
sensor::Sensor * heading_sensor_
Definition: hmc5883l.h:60
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:146
uint16_t x
Definition: tt21100.cpp:17
uint16_t y
Definition: tt21100.cpp:18
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:151
HMC5883LOversampling oversampling_
Definition: hmc5883l.h:54
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
enum esphome::hmc5883l::HMC5883LComponent::ErrorCode error_code_
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
Definition: i2c.h:262
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:113
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
float get_setup_priority() const override
Definition: hmc5883l.cpp:82