forked from amperka/Troyka-IMU
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lis3mdl.cpp
143 lines (120 loc) · 3.14 KB
/
lis3mdl.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <Wire.h>
#include <Arduino.h>
#include "lis3mdl.h"
#define ADR_FS_4 0x00
#define ADR_FS_8 0x20
#define ADR_FS_12 0x40
#define ADR_FS_16 0x60
#define SENS_FS_4 6842
#define SENS_FS_8 3421
#define SENS_FS_12 2281
#define SENS_FS_16 1711
LIS3MDL_TWI::LIS3MDL_TWI(uint8_t addr) : AxisHw(addr) {
}
void LIS3MDL_TWI::begin() {
Wire.begin();
// устанавливаем чувствительность
setRange(RANGE_4_GAUSS);
writeCtrlReg3();
}
void LIS3MDL_TWI::setRange(uint8_t range) {
switch (range) {
case RANGE_4_GAUSS: {
_ctrlReg2 = ADR_FS_4;
_mult = SENS_FS_4;
break;
}
case RANGE_8_GAUSS: {
_ctrlReg2 = ADR_FS_8;
_mult = SENS_FS_8;
break;
}
case RANGE_12_GAUSS: {
_ctrlReg2 = ADR_FS_12;
_mult = SENS_FS_12;
break;
}
case RANGE_16_GAUSS: {
_ctrlReg2 = ADR_FS_16;
_mult = SENS_FS_16;
break;
}
default: {
_mult = SENS_FS_4;
}
break;
}
writeCtrlReg2();
}
void LIS3MDL_TWI::sleep(bool enable) {
if (enable)
_ctrlReg3 |= (3 << 0);
else
_ctrlReg3 &= ~(3 << 0);
writeCtrlReg3();
}
float LIS3MDL_TWI::readGaussX() {
return readX() / _mult;
}
float LIS3MDL_TWI::readGaussY() {
return readY() / _mult;
}
float LIS3MDL_TWI::readGaussZ() {
return readZ() / _mult;
}
float LIS3MDL_TWI::readCalibrateX() {
calibrate();
return _xCalibrate;
}
float LIS3MDL_TWI::readCalibrateY() {
calibrate();
return _yCalibrate;
}
float LIS3MDL_TWI::readCalibrateZ() {
calibrate();
return _zCalibrate;
}
float LIS3MDL_TWI::readCalibrateGaussX() {
return readCalibrateX()/_mult;
}
float LIS3MDL_TWI::readCalibrateGaussY() {
return readCalibrateY()/_mult;
}
float LIS3MDL_TWI::readCalibrateGaussZ() {
return readCalibrateZ()/_mult;
}
void LIS3MDL_TWI::calibrate() {
float result[3] = {0, 0, 0};
float uncalibratedValues[3];
uncalibratedValues[0] = readX() - _bias[0];
uncalibratedValues[1] = readY() - _bias[1];
uncalibratedValues[2] = readZ() - _bias[2];
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
result[i] += _calibrationMatrix[i][j] * uncalibratedValues[j];
}
}
_xCalibrate = result[0];
_yCalibrate = result[1];
_zCalibrate = result[2];
}
void LIS3MDL_TWI::calibrateMatrix(const double calibrationMatrix[3][3], const double bias[3]) {
memcpy (_bias, bias, 3 * sizeof (double));
memcpy (_calibrationMatrix, calibrationMatrix, 3 * 3 * sizeof (double));
}
void LIS3MDL_TWI::readCalibrateGaussXYZ(float *x, float *y, float *z) {
calibrate();
*x = _xCalibrate / _mult;
*y = _yCalibrate / _mult;
*z = _zCalibrate / _mult;
}
float LIS3MDL_TWI::readAzimut() {
calibrate();
float heading = atan2(_yCalibrate, _xCalibrate);
if(heading < 0)
heading += TWO_PI;
else if(heading > TWO_PI)
heading -= TWO_PI;
float headingDegrees = heading * RAD_TO_DEG;
return headingDegrees;
}