@@ -27,36 +27,163 @@ SOFTWARE.
27
27
#include " mag.h"
28
28
#include " ../hal/MF_I2C.h"
29
29
30
+ // #include "../cli/stat.h" //for debugging
31
+
32
+
33
+ // https://www.lcsc.com/datasheet/lcsc_datasheet_2410121623_QST-QMC6309_C5439871.pdf
34
+
35
+ // Who Am I register
36
+ #define QMC6309_WAI_REG 0x00
37
+
38
+ #define QMC6309_WAI_VALUE 0x90
39
+
40
+ // Data register
41
+ #define QMC6309_OUTX_REG 0x01
42
+
43
+ // Status register {DRDY:1;OVFL:1;...}
44
+ #define QMC6309_STAT_REG 0x09
45
+
46
+ #define QMC6309_STAT_DRDY 0x01 // 1=data ready
47
+ #define QMC6309_STAT_OVFL 0x02 // 1=overflow
48
+ #define QMC6309_STAT_ST_RDY 0x04 // 1=self test ready
49
+ #define QMC6309_STAT_NVM_RDY 0x08 // 1=nvm ready for access
50
+ #define QMC6309_STAT_NVM_LOAD_DONE 0x10 // 1=nvm loading done
51
+
52
+ // Control register 1 {MD:2;:1;OSR:2;LPF:3;}
53
+ #define QMC6309_CTRL1_REG 0x0A
54
+
55
+ #define QMC6309_CTRL1_MD_SUSPEND 0b00
56
+ #define QMC6309_CTRL1_MD_NORMAL 0b01
57
+ #define QMC6309_CTRL1_MD_SINGLE 0b10
58
+ #define QMC6309_CTRL1_MD_CONTINUOUS 0b11
59
+
60
+ #define QMC6309_CTRL1_OSR_1 (0b11 <<3 )
61
+ #define QMC6309_CTRL1_OSR_2 (0b10 <<3 )
62
+ #define QMC6309_CTRL1_OSR_4 (0b01 <<3 )
63
+ #define QMC6309_CTRL1_OSR_8 (0b00 <<3 )
64
+
65
+ #define QMC6309_CTRL1_LPF_1 (0b000 <<5 )
66
+ #define QMC6309_CTRL1_LPF_2 (0b001 <<5 )
67
+ #define QMC6309_CTRL1_LPF_4 (0b010 <<5 )
68
+ #define QMC6309_CTRL1_LPF_8 (0b011 <<5 )
69
+ #define QMC6309_CTRL1_LPF_16 (0b100 <<5 )
70
+
71
+ // Control register 2 {SET:2;RGN:2;ODR:3;SRT:1;}
72
+ #define QMC6309_CTRL2_REG 0x0B
73
+
74
+ #define QMC6309_CTRL2_SET_RESET_ON 0b00
75
+ #define QMC6309_CTRL2_SET_ONLY 0b01
76
+ #define QMC6309_CTRL2_SET_RESET_OFF 0b11
77
+
78
+ #define QMC6309_CTRL2_RNG_32G (0b00 <<2 )
79
+ #define QMC6309_CTRL2_RNG_16G (0b01 <<2 )
80
+ #define QMC6309_CTRL2_RNG_8G (0b10 <<2 )
81
+
82
+ // output data rate for normal mode
83
+ #define QMC6309_CTRL2_ODR_1Hz (0b000 <<4 )
84
+ #define QMC6309_CTRL2_ODR_10Hz (0b001 <<4 )
85
+ #define QMC6309_CTRL2_ODR_50Hz (0b010 <<4 )
86
+ #define QMC6309_CTRL2_ODR_100Hz (0b011 <<4 )
87
+ #define QMC6309_CTRL2_ODR_200Hz (0b100 <<4 )
88
+
89
+ #define QMC6309_CTRL2_SOFT_RESET_START 0x80
90
+ #define QMC6309_CTRL2_SOFT_RESET_STOP 0x00
91
+
92
+
30
93
class MagGizmoQMC6309 : public MagGizmo {
31
94
private:
32
95
MF_I2CDevice *dev = nullptr ;
33
96
97
+
34
98
public:
35
- MagGizmoQMC6309 (MF_I2C *i2c, int8_t i2c_adr) {
36
- i2c_adr = 0x7C ; // fixed: 0x7C
37
- this ->dev = new MF_I2CDevice (i2c, i2c_adr);
99
+ const float scale_uT = 0.025 ; // scale factor to uT (at +/-800uT (+/-8G) RNG)
100
+ int16_t mx; // raw adc values
101
+ int16_t my;
102
+ int16_t mz;
38
103
39
- // setup for 16 sample moving average (my interpretation of data sheet OSR2 setting), sample rate = 1500Hz (continous mode)
40
- dev->writeReg (0x0B , 0x04 ); // ODR=1Hz, Scale=8G, Reset
41
- dev->writeReg (0x0A , 0xFD ); // OSR2(filter)=16, OSR=1, Continuous Mode
104
+ ~MagGizmoQMC6309 () {
105
+ delete dev;
42
106
}
43
107
108
+ MagGizmoQMC6309 (MF_I2C *i2c) {
109
+ i2c->setClock (400000 );
44
110
45
- ~MagGizmoQMC6309 () {
46
- delete dev;
111
+ this ->dev = new MF_I2CDevice (i2c, 0x7C ); // i2c address is always 0x7C
112
+
113
+ // soft reset
114
+ // dev->writeReg(QMC6309_CTRL2_REG, QMC6309_CTRL2_SOFT_RESET_START);
115
+ // dev->writeReg(QMC6309_CTRL2_REG, QMC6309_CTRL2_SOFT_RESET_STOP);
116
+
117
+ // configure 220Hz update rate with LPF_16
118
+ uint8_t ctrl2_val = QMC6309_CTRL2_SET_RESET_ON | QMC6309_CTRL2_RNG_8G | QMC6309_CTRL2_ODR_100Hz;
119
+ uint8_t ctrl1_val = QMC6309_CTRL1_MD_CONTINUOUS | QMC6309_CTRL1_OSR_8 | QMC6309_CTRL1_LPF_16; // mx mean:-10.982379 stdev:1.401531 min:-14.000000 max:-8.000000 n:227
120
+ // uint8_t ctrl1_val = QMC6309_CTRL1_MD_CONTINUOUS | QMC6309_CTRL1_OSR_8 | QMC6309_CTRL1_LPF_1; //mx mean:-10.060345 stdev:6.673316 min:-33.000000 max:+4.000000 n:232
121
+ // uint8_t ctrl1_val = QMC6309_CTRL1_MD_CONTINUOUS | QMC6309_CTRL1_OSR_1 | QMC6309_CTRL1_LPF_1; //mx mean:-11.925335 stdev:38.645042 min:-119.000000 max:+106.000000 n:1125
122
+
123
+ int tries = 20 ;
124
+ uint8_t wai = 0 ;
125
+ while (tries) {
126
+ uint8_t ctrl1 = dev->readReg (QMC6309_CTRL1_REG);
127
+ uint8_t ctrl2 = dev->readReg (QMC6309_CTRL2_REG);
128
+ wai = dev->readReg (QMC6309_WAI_REG);
129
+
130
+ // setup
131
+ if (ctrl2 != ctrl2_val) dev->writeReg (QMC6309_CTRL2_REG, ctrl2_val);
132
+ if (ctrl1 != ctrl1_val) dev->writeReg (QMC6309_CTRL1_REG, ctrl1_val);
133
+ delay (1 );
134
+
135
+ uint8_t stat = dev->readReg (QMC6309_STAT_REG);
136
+ if (stat & QMC6309_STAT_DRDY) {
137
+ break ;
138
+ }
139
+
140
+ tries--;
141
+
142
+ // Serial.printf("try wai=%02X stat=%02X ctrl2=%02X(%02X) ctrl1=%02X(%02X)\n", wai, stat, ctrl2, ctrl2_val, ctrl1, ctrl1_val);
143
+ }
144
+ if (!tries) Serial.printf (" MAG: ERROR could not configure QMC6309. wai:0x%02X, expected 0x%02X\n " , wai, QMC6309_WAI_VALUE);
145
+
146
+ /* //DEBUG
147
+ while(1) {
148
+ Stat mx,my,mz;
149
+ uint32_t start_ts = micros();
150
+ while(micros() - start_ts < 1000000) {
151
+ float x,y,z;
152
+ if(update(&x,&y,&z)) {
153
+ mx.append(x);
154
+ my.append(y);
155
+ mz.append(z);
156
+ }
157
+ }
158
+
159
+ Serial.println("=== Magnetometer (external) ===");
160
+ mx.print("mx");
161
+ my.print("my");
162
+ mz.print("mz");
163
+ }
164
+ */
47
165
}
48
166
167
+ bool update_raw () {
168
+ uint8_t stat = dev->readReg (QMC6309_STAT_REG);
169
+ if ((stat & QMC6309_STAT_DRDY) == 0 || (stat & QMC6309_STAT_OVFL) != 0 ) return false ;
49
170
50
- bool update (float *x, float *y, float *z) override {
51
171
uint8_t d[6 ];
52
- dev->readReg (0x01 , d, 6 );
53
- int16_t mx = d[0 ] | (d[1 ] << 8 ); // 16 bit litte-endian signed
54
- int16_t my = d[2 ] | (d[3 ] << 8 );
55
- int16_t mz = d[4 ] | (d[5 ] << 8 );
56
-
57
- *x = 200e-9 * mx; // in [T]
58
- *y = 200e-9 * my;
59
- *z = 200e-9 * mz;
172
+ dev->readReg (QMC6309_OUTX_REG, d, 6 );
173
+
174
+ mx = d[0 ] | (d[1 ] << 8 ); // 16 bit litte-endian signed - 40LSB/uT at +/-800uT scale
175
+ my = d[2 ] | (d[3 ] << 8 );
176
+ mz = d[4 ] | (d[5 ] << 8 );
177
+
178
+ return true ;
179
+ }
180
+
181
+ bool update (float *x, float *y, float *z) override {
182
+ if (!update_raw ()) return false ;
183
+
184
+ *x = scale_uT * mx;
185
+ *y = scale_uT * my;
186
+ *z = scale_uT * mz;
60
187
return true ;
61
188
}
62
189
};
0 commit comments