SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
sensor/magnetometer/qmc/SensorQMC5883L.hpp
Go to the documentation of this file.
1
30#pragma once
31
32#include "../../../SensorBuildOpt.h"
33#if !SENSORLIB_EXCLUDE_QMC5883L
36
37static constexpr uint8_t QMC5883L_SLAVE_ADDRESS = 0x0D;
38
40{
41public:
42
49 SensorQMC5883L() = default;
50
57 ~SensorQMC5883L() = default;
58
67 bool readData(MagnetometerData &data) override
68 {
69 uint8_t buffer[6] = {0};
70 int16_t x = 0, y = 0, z = 0;
71
72 int status = readReg(REG_0x06_STATUS);
73 if (status < 0) {
74 SENSORLIB_LOG_E("Failed to read status register");
75 return false;
76 }
77
78 // OVL (Overflow)
79 if (sensorlib::_isBitSet(status, 1)) {
80 data.overflow = true;
81 SENSORLIB_LOG_E("Data overflow detected");
82 } else {
83 data.overflow = false;
84 }
85
86 // DOR (Data Skip)
87 if (sensorlib::_isBitSet(status, 2)) {
88 SENSORLIB_LOG_E("Data skip detected");
89 data.skip_data = true;
90 } else {
91 data.skip_data = false;
92 }
93
94 // DRDY (Data Ready)
95 if (!sensorlib::_isBitSet(status, 0)) {
96 // SENSORLIB_LOG_W("Data not ready");
97 return false;
98 }
99
100 if (readRegBuff(REG_0x00_LSB_DX, buffer, 6) < 0) {
101 SENSORLIB_LOG_E("Failed to read magnetic field data");
102 return false;
103 }
104
105 x = (int16_t)(buffer[1] << 8) | (buffer[0]); // Combine X LSB and MSB
106 y = (int16_t)(buffer[3] << 8) | (buffer[2]); // Combine Y LSB and MSB
107 z = (int16_t)(buffer[5] << 8) | (buffer[4]); // Combine Z LSB and MSB
108
109 data.raw.x = x - _x_offset;
110 data.raw.y = y - _y_offset;
111 data.raw.z = z - _z_offset;
112
113 // Convert raw values to Gauss using sensitivity (depends on selected magnetic range)
114 data.magnetic_field.x = (float)(data.raw.x) * _sensitivity;
115 data.magnetic_field.y = (float)(data.raw.y) * _sensitivity;
116 data.magnetic_field.z = (float)(data.raw.z) * _sensitivity;
117
118 // Calculate heading
120
121 // Convert heading to degrees
122 data.heading_degrees = data.heading * (180.0 / M_PI);
123
124 return true;
125 }
126
133 bool isDataReady() override
134 {
135 return getRegBit(REG_0x06_STATUS, 0);
136 }
137
145 {
146 return getRegBit(REG_0x06_STATUS, 1);
147 }
148
156 {
157 return getRegBit(REG_0x06_STATUS, 2);
158 }
159
166 bool reset() override
167 {
168 writeReg(REG_0x0A_CMD2, 0x80);
169 hal->delay(10);
170 writeReg(REG_0x0A_CMD2, 0x00);
171 return true;
172 }
173
179 bool selfTest() override
180 {
181 SENSORLIB_LOG_E("QMC5883L not self-test function");
182 return true;
183 }
184
194 {
195 float full_scale = 0;
196 float sensitivity = 0.0f;
197 uint8_t range_value = 0;
198 switch (range) {
200 sensitivity = 0.00033333f; // 3000 LSB/Gauss
201 range_value = 0x01 << 4;
202 full_scale = 8.0f;
203 break;
205 sensitivity = 0.00008333f; // 12000 LSB/Gauss
206 range_value = 0x00 << 4;
207 full_scale = 2.0f;
208 break;
209 default:
210 SENSORLIB_LOG_E("Invalid magnetometer range");
211 return false;
212 }
213 if (updateBits(REG_0x09_CMD1, 0x30, range_value) > 0) {
214 SENSORLIB_LOG_E("Failed to set full scale range");
215 return false;
216 }
217 _config.range = full_scale;
218 _sensitivity = sensitivity;
219 return true;
220 }
221
229 bool setOutputDataRate(float data_rate_hz) override
230 {
231 int rangeInt = static_cast<int>(data_rate_hz * 100 + 0.5);
232 SENSORLIB_LOG_D("Input: %.2f, Integer: %d\n", data_rate_hz, rangeInt);
233 uint8_t regValue = 0;
234 switch (rangeInt) {
235 case 1000: // 10.0
236 regValue = 0x00 << 2;
237 break;
238 case 5000: // 50.0
239 regValue = 0x01 << 2;
240 break;
241 case 10000: // 100.0
242 regValue = 0x02 << 2;
243 break;
244 case 20000: // 200.0
245 regValue = 0x03 << 2;
246 break;
247 default:
248 SENSORLIB_LOG_E("Invalid output data rate");
249 return false;
250 }
251 if (updateBits(REG_0x09_CMD1, 0x0C, regValue) < 0) {
252 SENSORLIB_LOG_E("Failed to set bandwidth");
253 return false;
254 }
255 _config.sample_rate = data_rate_hz;
256 return true;
257 }
258
266 bool setOperationMode(OperationMode mode) override
267 {
268 uint8_t mode_val = 0;
269 switch (mode) {
271 mode_val = 0x00;
272 break;
275 mode_val = 0x01;
276 break;
277 default:
278 SENSORLIB_LOG_E("Invalid operation mode");
279 return false;
280 }
281 if (updateBits(REG_0x09_CMD1, 0x03, mode_val) < 0) {
282 SENSORLIB_LOG_E("Failed to set operation mode");
283 return false;
284 }
285 _config.mode = mode;
286 return true;
287 }
288
297 {
298 uint8_t osr_val = 0;
299 switch (osr) {
300 // 512
302 osr_val = 0x00 << 6;
303 _oversampling_rate = 512;
304 break;
305 // 256
307 osr_val = 0x01 << 6;
308 _oversampling_rate = 256;
309 break;
310 // 128
312 osr_val = 0x02 << 6;
313 _oversampling_rate = 128;
314 break;
315 // 64
317 osr_val = 0x03 << 6;
319 break;
320 default:
321 SENSORLIB_LOG_E("Invalid oversampling rate");
322 return false;
323 }
324 return updateBits(REG_0x09_CMD1, 0xC0, osr_val) == 0;
325 }
326
333 {
334 SENSORLIB_LOG_E("QSTMagnetic does not support downsampling");
335 return false;
336 }
337
346 bool getTemperature(float &temperature, int16_t &raw_temp)
347 {
348 uint8_t buffer[2] = {0};
349
350 if (readRegBuff(REG_0x07_TOUT_LOW, buffer, 2) < 0) {
351 SENSORLIB_LOG_E("Failed to read temperature registers");
352 return false;
353 }
354 raw_temp = (int16_t)((buffer[1] << 8) | buffer[0]);
355 // 100 LSB/°C
356 temperature = (float)raw_temp / 100.0f;
357 //TODO: The actual test result was 0, which may be due to a chip problem.
358 return true;
359 }
360
366 uint8_t getChipID() const
367 {
368 return _info.uid;
369 }
370
382 bool configMagnetometer(OperationMode mode, MagFullScaleRange range, float data_rate_hz,
384 {
385 if (!setOperationMode(mode)) {
386 SENSORLIB_LOG_E("Failed to set operation mode");
387 return false;
388 }
389 if (!setFullScaleRange(range)) {
390 SENSORLIB_LOG_E("Failed to set full scale range");
391 return false;
392 }
393 if (!setOutputDataRate(data_rate_hz)) {
394 SENSORLIB_LOG_E("Failed to set bandwidth");
395 return false;
396 }
397 if (!setOversamplingRate(osr)) {
398 SENSORLIB_LOG_E("Failed to set oversampling rate");
399 return false;
400 }
401 return true;
402 }
403
404private:
405
406 static constexpr uint8_t REG_0x00_LSB_DX = 0x00;
407 static constexpr uint8_t REG_0x01_MSB_DX = 0x01;
408 static constexpr uint8_t REG_0x02_LSB_DY = 0x02;
409 static constexpr uint8_t REG_0x03_MSB_DY = 0x03;
410 static constexpr uint8_t REG_0x04_LSB_DZ = 0x04;
411 static constexpr uint8_t REG_0x05_MSB_DZ = 0x05;
412 static constexpr uint8_t REG_0x06_STATUS = 0x06;
413 static constexpr uint8_t REG_0x07_TOUT_LOW = 0x07;
414 static constexpr uint8_t REG_0x08_TOUT_HIGH = 0x08;
415 static constexpr uint8_t REG_0x09_CMD1 = 0x09;
416 static constexpr uint8_t REG_0x0A_CMD2 = 0x0A;
417 static constexpr uint8_t REG_0x0B_CMD3 = 0x0B;
418 static constexpr uint8_t REG_0x0D_CHIP_ID = 0x0D;
419 static constexpr uint8_t QMC5883L_CHIP_ID = 0xFF;
420
421 bool initImpl(uint8_t param) override
422 {
423 reset();
424
425 hal->delay(20);
426
427 // SET/RESET Period is controlled by FBR [7:0].
428 // It is recommended that the register 0BH is written by 0x01.
429 uint8_t set_reset_period = 0x01;
430 if (writeReg(REG_0x0B_CMD3, set_reset_period) < 0) {
431 SENSORLIB_LOG_E("Failed to set SET/RESET period");
432 return false;
433 }
434 _info.uid = readReg(REG_0x0D_CHIP_ID);
435 _info.manufacturer = "QSTMagnetic";
436 _info.model = "QMC5883L";
439 _info.version = 1; // Set a default version
440
441
442 // Set default configuration
445 50.0f,
447
449 _config.range = 2.0f;
450 _config.sample_rate = 50.0f;
451 _config.latency = 0;
453
454 return _info.uid == QMC5883L_CHIP_ID;
455 }
456
457};
458
459#endif
@license MIT License
@license MIT License
@ MAGNETOMETER
Magnetometer sensor.
OperationMode
Enumeration of sensor operation modes.
MagFullScaleRange
Enumeration defining full-scale range settings for the sensor.
MagDownSampleRatio
Enumeration defining down-sample ratios for the sensor.
@ DSR_1
1x down-sample ratio
#define M_PI
MagOverSampleRatio
Enumeration defining over-sample ratios for the sensor.
@ OSR_8
8x over-sample ratio
@ OSR_4
4x over-sample ratio
@ OSR_2
2x over-sample ratio
@ OSR_1
1x over-sample ratio
#define SENSORLIB_LOG_E(...)
#define SENSORLIB_LOG_D(...)
SensorTemperature temperature(bhy)
std::unique_ptr< SensorHal > hal
SensorConfig _config
Current configuration.
SensorInfo _info
Sensor information.
bool getRegBit(uint8_t reg, uint8_t bit)
int readReg(uint8_t reg) const
int writeReg(uint8_t reg, uint8_t val)
int readRegBuff(uint8_t reg, uint8_t *buf, size_t len) const
int updateBits(uint8_t reg, uint8_t mask, uint8_t value_shifted)
bool getTemperature(float &temperature, int16_t &raw_temp)
Gets the temperature reading from the sensor.
~SensorQMC5883L()=default
Destructor.
uint8_t getChipID() const
Gets the chip ID of the magnetometer.
bool setDownsamplingRate(MagDownSampleRatio dsr) override
QM5883L does not support downsampling.
bool selfTest() override
QMC5883L does not support self-test checks.
bool setOutputDataRate(float data_rate_hz) override
Sets the bandwidth of the magnetometer.
SensorQMC5883L()=default
Default constructor.
bool isDataSkipped()
Checks if data has been skipped.
bool isDataReady() override
Checks if new data is available from the sensor.
bool isDataOverflow()
Checks if data overflow has occurred.
bool configMagnetometer(OperationMode mode, MagFullScaleRange range, float data_rate_hz, MagOverSampleRatio osr, MagDownSampleRatio dsr=MagDownSampleRatio::DSR_1) override
Configures the magnetometer with multiple parameters.
bool reset() override
Resets the sensor to its default state.
bool setFullScaleRange(MagFullScaleRange range) override
Sets the full-scale range of the magnetometer.
bool setOversamplingRate(MagOverSampleRatio osr) override
Sets the oversampling rate of the magnetometer.
bool readData(MagnetometerData &data) override
Reads the magnetic field data from the sensor.
bool setOperationMode(OperationMode mode) override
Sets the operation mode of the magnetometer.
float calculateHeading(const MagnetometerData &data, float declination=0.0f)
Calculate heading (yaw) angle from magnetometer data in radians.
constexpr bool _isBitSet(T value, uint8_t bit)
Definition SensorLib.h:112
Structure representing magnetometer data.
RawVector raw
raw data
float heading_degrees
heading angle (degrees)
float heading
heading angle (radians)
bool skip_data
skip data flag
SensorVector magnetic_field
magnetic field strength (Gauss)
bool overflow
data overflow flag
int16_t x
X-axis raw value.
int16_t y
Y-axis raw value.
int16_t z
Z-axis raw value.
uint32_t latency
Reporting latency in milliseconds.
float sample_rate
Sample rate in Hz.
float range
Measurement range.
SensorType type
Type of the sensor.
OperationMode mode
Operation mode.
uint8_t version
Hardware/firmware version.
uint8_t i2c_address
Default I2C address.
uint32_t uid
Unique identifier.
SensorType type
Sensor type.
const char * manufacturer
Manufacturer name.
const char * model
Model name/identifier.
float x
X-axis component.
float y
Y-axis component.
float z
Z-axis component.
int16_t x[5]
int16_t y[5]