Files
SpotMicroESP32-Leika/esp32/include/peripherals/drivers/hmc5883l.h
T
2026-01-30 12:57:51 +01:00

82 lines
2.3 KiB
C++

#pragma once
#include <peripherals/i2c_bus.h>
#include <cmath>
class HMC5883LDriver {
public:
static constexpr uint8_t DEFAULT_ADDR = 0x1E;
HMC5883LDriver(uint8_t addr = DEFAULT_ADDR) : _addr(addr) {}
bool begin() {
if (!I2CBus::instance().probe(_addr)) return false;
uint8_t idA = readReg(REG_ID_A);
uint8_t idB = readReg(REG_ID_B);
uint8_t idC = readReg(REG_ID_C);
if (idA != 'H' || idB != '4' || idC != '3') return false;
writeReg(REG_CONFIG_A, 0x70);
writeReg(REG_CONFIG_B, 0x20);
writeReg(REG_MODE, 0x00);
_initialized = true;
return true;
}
bool update() {
if (!_initialized) return false;
uint8_t buf[6];
if (I2CBus::instance().readReg(_addr, REG_DATA_X_MSB, buf, 6) != ESP_OK) return false;
int16_t x = (buf[0] << 8) | buf[1];
int16_t z = (buf[2] << 8) | buf[3];
int16_t y = (buf[4] << 8) | buf[5];
_mag[0] = x * _scale;
_mag[1] = y * _scale;
_mag[2] = z * _scale;
_heading = atan2f(_mag[1], _mag[0]);
_heading += _declination;
if (_heading < 0) _heading += 2 * M_PI;
if (_heading > 2 * M_PI) _heading -= 2 * M_PI;
_heading *= 180.0f / M_PI;
return true;
}
void setDeclination(float dec) { _declination = dec; }
float getMagX() const { return _mag[0]; }
float getMagY() const { return _mag[1]; }
float getMagZ() const { return _mag[2]; }
float getHeading() const { return _heading; }
bool isInitialized() const { return _initialized; }
private:
static constexpr uint8_t REG_CONFIG_A = 0x00;
static constexpr uint8_t REG_CONFIG_B = 0x01;
static constexpr uint8_t REG_MODE = 0x02;
static constexpr uint8_t REG_DATA_X_MSB = 0x03;
static constexpr uint8_t REG_ID_A = 0x0A;
static constexpr uint8_t REG_ID_B = 0x0B;
static constexpr uint8_t REG_ID_C = 0x0C;
static constexpr float _scale = 0.92f;
void writeReg(uint8_t reg, uint8_t val) { I2CBus::instance().writeReg(_addr, reg, &val, 1); }
uint8_t readReg(uint8_t reg) {
uint8_t val = 0;
I2CBus::instance().readReg(_addr, reg, &val, 1);
return val;
}
uint8_t _addr;
bool _initialized = false;
float _mag[3] = {0};
float _heading = 0;
float _declination = 0.22f;
};