SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
SensorQSTMagnetic.hpp
Go to the documentation of this file.
1
30#pragma once
31
34
35static constexpr uint8_t QMC6310U_SLAVE_ADDRESS = 0x1C;
36static constexpr uint8_t QMC6310N_SLAVE_ADDRESS = 0x3C;
37static constexpr uint8_t QMC5883P_SLAVE_ADDRESS = 0x2C;
38
40{
41public:
51
59
66 ~SensorQSTMagnetic() = default;
67
76 bool readData(MagnetometerData &data) override
77 {
78 uint8_t buffer[6] = {0};
79 int16_t x = 0, y = 0, z = 0;
80
81 // QMC has no data skipping bit
82 data.skip_data = false;
83
84 int status = readReg(REG_0x09_STAT);
85 if (status < 0) {
86 SENSORLIB_LOG_E("Failed to read status register");
87 return false;
88 }
89
90 // OVL (Overflow)
91 if (sensorlib::_isBitSet(status, 1)) {
92 data.overflow = true;
93 SENSORLIB_LOG_W("Data overflow detected");
94 } else {
95 data.overflow = false;
96 }
97
98 // DRDY (Data Ready)
99 if (!sensorlib::_isBitSet(status, 0)) {
100 // SENSORLIB_LOG_E("Data not ready");
101 return false;
102 }
103
104 if (readRegBuff(REG_0x01_LSB_DX, buffer, 6) < 0) {
105 SENSORLIB_LOG_E("Failed to read magnetic field data");
106 return false;
107 }
108
109 x = (int16_t)(buffer[1] << 8) | (buffer[0]); // Combine X LSB and MSB
110 y = (int16_t)(buffer[3] << 8) | (buffer[2]); // Combine Y LSB and MSB
111 z = (int16_t)(buffer[5] << 8) | (buffer[4]); // Combine Z LSB and MSB
112
113 data.raw.x = x - _x_offset;
114 data.raw.y = y - _y_offset;
115 data.raw.z = z - _z_offset;
116
117 // Convert raw values to Gauss using sensitivity (depends on selected magnetic range)
118 data.magnetic_field.x = (float)(data.raw.x) * _sensitivity;
119 data.magnetic_field.y = (float)(data.raw.y) * _sensitivity;
120 data.magnetic_field.z = (float)(data.raw.z) * _sensitivity;
121
122 // Calculate heading
124
125 // Convert heading to degrees
126 data.heading_degrees = data.heading * (180.0 / M_PI);
127
128 return true;
129 }
130
137 bool isDataReady() override
138 {
139 return getRegBit(REG_0x09_STAT, 0);
140 }
141
149 {
150 return getRegBit(REG_0x09_STAT, 1);
151 }
152
159 bool reset() override
160 {
161 writeReg(REG_0x0B_CMD2, (uint8_t)0x80);
162 hal->delay(10);
163 writeReg(REG_0x0B_CMD2, (uint8_t)0x00);
164 return true;
165 }
166
173 bool selfTest() override
174 {
175 int16_t x_result = 0, y_result = 0, z_result = 0;
176 return selfTest(x_result, y_result, z_result);
177 }
178
189 bool selfTest(int16_t &x_result, int16_t &y_result, int16_t &z_result)
190 {
192 SENSORLIB_LOG_E("Failed to set CONTINUOUS_MEASUREMENT for selfTest");
193 return false;
194 }
195 hal->delay(20);
196
197 MagnetometerData data;
198
199 if (!readData(data)) {
200 SENSORLIB_LOG_E("Failed to read data before selfTest");
201 return false;
202 }
203 int16_t x_pre = data.raw.x;
204 int16_t y_pre = data.raw.y;
205 int16_t z_pre = data.raw.z;
206
207 setRegBit(REG_0x0B_CMD2, 6);
208 hal->delay(5);
209
210 if (!readData(data)) {
211 SENSORLIB_LOG_E("Failed to read data before selfTest");
212 return false;
213 }
214 x_result = data.raw.x - x_pre;
215 y_result = data.raw.y - y_pre;
216 z_result = data.raw.z - z_pre;
217
218 clrRegBit(REG_0x0B_CMD2, 6);
219
221 }
222
232 {
233 float full_scale = 0;
234 float sensitivity = 0.0f;
235 uint8_t range_value = 0;
236 switch (range) {
238 sensitivity = 0.001f; // 1000 LSB/Gauss
239 range_value = 0x00 << 2;
240 full_scale = 30.0f;
241 break;
243 sensitivity = 0.0004f; // 2500 LSB/Gauss
244 range_value = 0x01 << 2;
245 full_scale = 12.0f;
246 break;
248 sensitivity = 0.00026667f; // 3750 LSB/Gauss
249 range_value = 0x02 << 2;
250 full_scale = 8.0f;
251 break;
253 sensitivity = 0.00006667f; // 15000 LSB/Gauss
254 range_value = 0x03 << 2;
255 full_scale = 2.0f;
256 break;
257 default:
258 SENSORLIB_LOG_E("Invalid magnetometer range");
259 return false;
260 }
261
262 if (updateBits(REG_0x0B_CMD2, 0x0C, range_value) < 0) {
263 SENSORLIB_LOG_E("Failed to set full scale range.");
264 return false;
265 }
266 _sensitivity = sensitivity;
267 _config.range = full_scale;
268 return true;
269 }
270
277 bool setOutputDataRate(float odr) override
278 {
279 int rangeInt = static_cast<int>(odr * 100 + 0.5);
280 SENSORLIB_LOG_D("Input: %.2f, Integer: %d\n", odr, rangeInt);
281 uint8_t regValue = 0;
282 switch (rangeInt) {
283 case 1000: // 10.0
284 regValue = 0x00 << 2;
285 break;
286 case 5000: // 50.0
287 regValue = 0x01 << 2;
288 break;
289 case 10000: // 100.0
290 regValue = 0x02 << 2;
291 break;
292 case 20000: // 200.0
293 regValue = 0x03 << 2;
294 break;
295 default:
296 SENSORLIB_LOG_E("Invalid output data rate");
297 return false;
298 }
299 if (updateBits(REG_0x0A_CMD1, 0x0C, regValue) < 0) {
300 SENSORLIB_LOG_E("Failed to set bandwidth");
301 return false;
302 }
303 _config.sample_rate = odr;
304 return true;
305 }
306
314 bool setOperationMode(OperationMode mode) override
315 {
316 uint8_t mode_val = 0;
317 switch (mode) {
319 mode_val = 0x00;
320 break;
322 mode_val = 0x01;
323 break;
325 mode_val = 0x02;
326 break;
328 mode_val = 0x03;
329 break;
330 default:
331 SENSORLIB_LOG_E("Invalid operation mode");
332 return false;
333 }
334 if (updateBits(REG_0x0A_CMD1, 0x03, mode_val) < 0) {
335 SENSORLIB_LOG_E("Failed to set operation mode");
336 return false;
337 }
338 _config.mode = mode;
339 return true;
340 }
341
350 {
351 uint8_t osr_val = 0;
352 switch (osr) {
354 osr_val = 0x00 << 4;
356 break;
358 osr_val = 0x01 << 4;
360 break;
362 osr_val = 0x02 << 4;
364 break;
366 osr_val = 0x03 << 4;
368 break;
369 default:
370 SENSORLIB_LOG_E("Invalid oversampling rate");
371 return false;
372 }
373 return updateBits(REG_0x0A_CMD1, 0x30, osr_val) == 0;
374 }
375
384 {
385 uint8_t dsr_val = 0;
386 switch (dsr) {
388 dsr_val = 0x00 << 6;
389 break;
391 dsr_val = 0x01 << 6;
392 break;
394 dsr_val = 0x02 << 6;
395 break;
397 dsr_val = 0x03 << 6;
398 break;
399 default:
400 SENSORLIB_LOG_E("Invalid downsampling rate");
401 return false;
402 }
403 return updateBits(REG_0x0A_CMD1, 0xC0, dsr_val) == 0;
404 }
405
411 uint8_t getChipID() const
412 {
413 return _info.uid;
414 }
415
428 MagOverSampleRatio osr, MagDownSampleRatio dsr) override
429 {
430 if (!setOperationMode(mode)) {
431 return false;
432 }
433 if (!setFullScaleRange(range)) {
434 return false;
435 }
436 if (!setOutputDataRate(odr)) {
437 return false;
438 }
439 if (!setOversamplingRate(osr)) {
440 return false;
441 }
442 if (!setDownsamplingRate(dsr)) {
443 return false;
444 }
445 return true;
446 }
447
448private:
449 static constexpr uint8_t REG_0x00_CHIP_ID = 0x00;
450 static constexpr uint8_t REG_0x01_LSB_DX = 0x01;
451 static constexpr uint8_t REG_0x02_MSB_DX = 0x02;
452 static constexpr uint8_t REG_0x03_LSB_DY = 0x03;
453 static constexpr uint8_t REG_0x04_MSB_DY = 0x04;
454 static constexpr uint8_t REG_0x05_LSB_DZ = 0x05;
455 static constexpr uint8_t REG_0x06_MSB_DZ = 0x06;
456 static constexpr uint8_t REG_0x09_STAT = 0x09;
457 static constexpr uint8_t REG_0x0A_CMD1 = 0x0A;
458 static constexpr uint8_t REG_0x0B_CMD2 = 0x0B;
459 static constexpr uint8_t REG_0x29_SIGN = 0x29;
460
461 static constexpr uint8_t QMC6310_CHIP_ID = 0x80;
462 static constexpr uint8_t QMC5883P_CHIP_ID = 0x80;
463 static constexpr uint8_t QMC6309_CHIP_ID = 0x90;
464
465 ChipType _type;
466
467 bool initImpl(uint8_t param) override
468 {
469 uint8_t _chipId = 0;
470 reset();
471
472 hal->delay(20);
473
474 _info.uid = readReg(REG_0x00_CHIP_ID);
475 _info.manufacturer = "QSTMagnetic";
478 _info.version = 1; // Set a default version
479
480 switch (_addr) {
481 case QMC6310U_SLAVE_ADDRESS:
482 _type = CHIP_QMC6310U;
483 _info.model = "QMC6310U";
484 _chipId = QMC6310_CHIP_ID;
485 break;
486 case QMC6310N_SLAVE_ADDRESS:
487 _type = CHIP_QMC6310N;
488 _info.model = "QMC6310N";
489 _chipId = QMC6310_CHIP_ID;
490 break;
491 case QMC5883P_SLAVE_ADDRESS:
492 _type = CHIP_QMC5883P;
493 _info.model = "QMC5883P";
494 _chipId = QMC5883P_CHIP_ID;
495 break;
496 default:
497 _type = CHIP_UNKNOWN;
498 _info.model = "UNKNOWN";
499 return false;
500 }
501
502 if (_info.uid == 0) {
503 SENSORLIB_LOG_E("Failed to read chip ID.");
504 return false;
505 }
506
507 if (_info.uid != _chipId) {
508 SENSORLIB_LOG_E("Unexpected chip ID: 0x%02X", _chipId);
509 return false;
510 }
511
512 SENSORLIB_LOG_D("Magnetometer initialized successfully. read chip ID: 0x%02X", _info.uid );
513 // Set default configuration
516 50.0f,
519
521 _config.range = 8.0f;
522 _config.sample_rate = 50.0f;
523 _config.latency = 0;
525
526 return true;
527 }
528
529};
@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_8
8x down-sample ratio
@ DSR_2
2x down-sample ratio
@ DSR_4
4x down-sample ratio
@ 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_W(...)
#define SENSORLIB_LOG_E(...)
#define SENSORLIB_LOG_D(...)
std::unique_ptr< SensorHal > hal
SensorConfig _config
Current configuration.
SensorInfo _info
Sensor information.
bool clrRegBit(uint8_t reg, uint8_t bit)
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 setRegBit(uint8_t reg, uint8_t bit)
bool selfTest(int16_t &x_result, int16_t &y_result, int16_t &z_result)
Performs a self-test on the sensor.
bool setOutputDataRate(float odr) override
Sets the output data rate for the magnetometer.
uint8_t getChipID() const
Gets the chip ID of the magnetometer.
bool setFullScaleRange(MagFullScaleRange range) override
Sets the full-scale range of the magnetometer.
bool selfTest() override
Checks if the sensor is functioning correctly.
ChipType
Enumeration defining the types of supported magnetic sensor chips.
@ CHIP_UNKNOWN
Represents an unknown or unsupported chip type.
@ CHIP_QMC5883P
Represents the QMC5883P chip type.
@ CHIP_QMC6310N
Represents the QMC6310N chip type.
@ CHIP_QMC6310U
Represents the QMC6310U chip type.
bool setOversamplingRate(MagOverSampleRatio osr) override
Sets the oversampling rate of the magnetometer.
bool isDataReady() override
Checks if new data is available from the sensor.
bool isDataOverflow()
Checks if data overflow has occurred.
bool setDownsamplingRate(MagDownSampleRatio dsr) override
Sets the downsampling rate of the magnetometer.
bool setOperationMode(OperationMode mode) override
Sets the operation mode of the magnetometer.
~SensorQSTMagnetic()=default
Destructor.
bool configMagnetometer(OperationMode mode, MagFullScaleRange range, float odr, MagOverSampleRatio osr, MagDownSampleRatio dsr) override
Configures the magnetometer with multiple parameters.
bool reset() override
Resets the sensor to its default state.
SensorQSTMagnetic()
Default constructor.
bool readData(MagnetometerData &data) override
Reads the magnetic field data from the sensor.
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]