Skip to content

Commit 2d85e80

Browse files
committed
add RM3100 mag sensor
1 parent 5bcff94 commit 2d85e80

File tree

8 files changed

+284
-14
lines changed

8 files changed

+284
-14
lines changed

src/madflight/bar/BarGizmoHP203B.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ class BarGizmoHP203B: public BarGizmo {
1111
(void) sampleRate; //TODO
1212
if(i2c_adr == 0) i2c_adr = 0XEC; // fixed: 0XEC or 0xEE
1313
this->dev = new MF_I2CDevice(i2c, i2c_adr);
14-
dev->write(0b01010000, nullptr, 0); // ADC_CVT = 010, 100 OSR=256 (8.2ms), 00 press+temp
14+
dev->writeReg(0b01010000, nullptr, 0); // ADC_CVT = 010, 100 OSR=256 (8.2ms), 00 press+temp
15+
}
16+
17+
~BarGizmoHP203B() {
18+
delete dev;
1519
}
1620

1721
bool update(float *press, float *temp) override {
1822
uint8_t d[6];
19-
dev->read(0x10, d, 6); //READ_PT
23+
dev->readReg(0x10, d, 6); //READ_PT
2024
int32_t t = ((d[0] << 16) | (d[1] << 8) | d[2]) & 0x000fffff; //20 bit big-endian signed
2125
if(t & 0x00080000) t |= 0xfff00000; //20bit sign expansion
2226
uint32_t p = ((d[3] << 16) | (d[4] << 8) | d[5]) & 0x000fffff; //20 bit big-endian unsigned

src/madflight/cfg/cfg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ SOFTWARE.
216216
MF_PARAM( led_on, 0, int32_t, 'e', mf_LOW_IS_ON,mf_HIGH_IS_ON) \
217217
\
218218
/*MAG - Magnetometer*/ \
219-
MF_PARAM( mag_gizmo, 0, int32_t, 'e', mf_NONE,mf_QMC5883,mf_QMC6309) \
219+
MF_PARAM( mag_gizmo, 0, int32_t, 'e', mf_NONE,mf_QMC5883,mf_QMC6309,mf_RM3100) \
220220
MF_PARAM( mag_i2c_bus, -1, int32_t, 'i') \
221221
MF_PARAM( mag_i2c_adr, 0, int32_t, 'i') \
222222
MF_PARAM( mag_lp, 1e10, float, 'f') /*Magnetometer Gyro Low Pass Filter cutoff frequency in Hz (default 1e10Hz, i.e. no filtering) */ \

src/madflight/hal/MF_I2C.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ class MF_I2C {
4343

4444
class MF_I2CDevice {
4545
public:
46-
MF_I2C *i2c;
47-
uint8_t adr;
46+
MF_I2C *i2c = nullptr;
47+
uint8_t adr = 0;
4848

4949
MF_I2CDevice(MF_I2C *i2c, uint8_t adr) {
5050
this->i2c = i2c;
5151
this->adr = adr;
5252
}
5353

54-
uint32_t write(uint8_t reg, uint8_t *data, uint32_t len) {
54+
uint32_t writeReg(uint8_t reg, uint8_t *data, uint32_t len) {
5555
i2c->beginTransmission(adr);
5656
uint32_t rv = i2c->write(&reg, 1);
5757
if(len > 0) {
@@ -60,11 +60,11 @@ class MF_I2CDevice {
6060
return rv;
6161
}
6262

63-
uint32_t write(uint8_t reg, uint8_t data) {
64-
return write(reg, &data, 1);
63+
uint32_t writeReg(uint8_t reg, uint8_t data) {
64+
return writeReg(reg, &data, 1);
6565
}
6666

67-
uint32_t read(uint8_t reg, uint8_t *data, uint32_t len) {
67+
uint32_t readReg(uint8_t reg, uint8_t *data, uint32_t len) {
6868
uint32_t rv = 0;
6969
i2c->beginTransmission(adr);
7070
i2c->write(&reg, 1);
@@ -76,6 +76,12 @@ class MF_I2CDevice {
7676
return rv;
7777
}
7878

79+
uint8_t readReg(uint8_t reg) {
80+
uint8_t data;
81+
readReg(reg, &data, 1);
82+
return data;
83+
}
84+
7985
uint32_t transceive(uint8_t* wbuf, uint32_t wlen, uint8_t* rbuf, uint32_t rlen) {
8086
uint32_t rv = 0;
8187
i2c->beginTransmission(adr);

src/madflight/mag/MagGizmoQMC6309.h

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,55 @@
1+
/*==========================================================================================
2+
MIT License
3+
4+
Copyright (c) 2023-2025 https://madflight.com
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
===========================================================================================*/
24+
125
#pragma once
226

327
#include "mag.h"
428
#include "../hal/MF_I2C.h"
529

6-
730
class MagGizmoQMC6309 : public MagGizmo {
831
private:
9-
MF_I2CDevice *dev;
32+
MF_I2CDevice *dev = nullptr;
33+
1034
public:
1135
MagGizmoQMC6309(MF_I2C *i2c, int8_t i2c_adr) {
1236
i2c_adr = 0x7C; // fixed: 0x7C
1337
this->dev = new MF_I2CDevice(i2c, i2c_adr);
1438

1539
//setup for 16 sample moving average (my interpretation of data sheet OSR2 setting), sample rate = 1500Hz (continous mode)
16-
dev->write(0x0B, 0x04); //ODR=1Hz, Scale=8G, Reset
17-
dev->write(0x0A, 0xFD); //OSR2(filter)=16, OSR=1, Continuous Mode
40+
dev->writeReg(0x0B, 0x04); //ODR=1Hz, Scale=8G, Reset
41+
dev->writeReg(0x0A, 0xFD); //OSR2(filter)=16, OSR=1, Continuous Mode
1842
}
1943

44+
45+
~MagGizmoQMC6309() {
46+
delete dev;
47+
}
48+
49+
2050
bool update(float *x, float *y, float *z) override {
2151
uint8_t d[6];
22-
dev->read(0x01, d, 6);
52+
dev->readReg(0x01, d, 6);
2353
int16_t mx = d[0] | (d[1] << 8); //16 bit litte-endian signed
2454
int16_t my = d[2] | (d[3] << 8);
2555
int16_t mz = d[4] | (d[5] << 8);

src/madflight/mag/MagGizmoRM3100.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*==========================================================================================
2+
MIT License
3+
4+
Copyright (c) 2023-2025 https://madflight.com
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
===========================================================================================*/
24+
25+
#pragma once
26+
27+
#include "mag.h"
28+
#include "../hal/MF_I2C.h"
29+
#include "RM3100/RM3100.h"
30+
31+
class MagGizmoRM3100: public MagGizmo {
32+
protected:
33+
MagGizmoRM3100() {}; //protected constructor
34+
RM3100 *rm3100 = nullptr;
35+
36+
public:
37+
static MagGizmoRM3100* create(MF_I2C *i2c) {
38+
uint8_t probe_adr = RM3100::probe(i2c);
39+
if(probe_adr == 0) {
40+
Serial.printf("MAG: ERROR: RM3100 not detected\n", probe_adr);
41+
return nullptr;
42+
}
43+
44+
//create and configure gizmo
45+
auto gizmo = new MagGizmoRM3100();
46+
uint16_t cycle_count = 294; //cycle_count=294 gives approx 100Hz update rate
47+
gizmo->rm3100 = new RM3100(i2c, probe_adr, cycle_count);
48+
Serial.printf("MAG: RM3100 detected - i2c_adr:0x%02X cycle_count:%d resolution:%d nT/LSB\n", probe_adr, cycle_count, (int)(gizmo->rm3100->scale_uT*1000));
49+
return gizmo;
50+
}
51+
52+
bool update(float *x, float *y, float *z) override {
53+
rm3100->read(x,y,z);
54+
return true;
55+
}
56+
57+
~MagGizmoRM3100() {
58+
delete rm3100;
59+
}
60+
};
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*==========================================================================================
2+
MIT License
3+
4+
Copyright (c) 2023-2025 https://madflight.com
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
===========================================================================================*/
24+
25+
#include "RM3100.h"
26+
#include <Arduino.h> //delay()
27+
28+
#define RM3100_BASE_ADDRESS 0x20 // address with Pin 2 and Pin 4 set to LOW
29+
30+
// register addresses
31+
#define RM3100_REG_POLL 0x00 // Polls for single measurement
32+
#define RM3100_REG_CMM 0x01 // Continous mode
33+
#define RM3100_REG_CCX 0x04 // Cycle count X MSB (3*2 bytes)
34+
#define RM3100_REG_TMRC 0x0B // Continous mode data rate
35+
#define RM3100_REG_MX 0x24 // Measurement results X MSB (3*3 bytes)
36+
#define RM3100_REG_BIST 0x33 // Build-In Self Test
37+
#define RM3100_REG_STATUS 0x34 // Status of DRDY
38+
#define RM3100_REG_HSHAKE 0x35 // Handshake
39+
#define RM3100_REG_REVID 0x36 // Revision
40+
41+
42+
uint8_t RM3100::probe(MF_I2C *i2c) {
43+
MF_I2CDevice dev(i2c, 0);
44+
for(int i = 0; i < 4; i++) {
45+
dev.adr = RM3100_BASE_ADDRESS + i;
46+
uint8_t revid = 0;
47+
int rv = dev.readReg(RM3100_REG_REVID, &revid, 1); //returns 1 when data was received
48+
//Serial.printf("RM3100.probe(0x%02X) = 0x%02X rv=%d\n", dev.adr, revid, rv);
49+
if(revid == 0x22) return dev.adr;
50+
}
51+
return 0;
52+
}
53+
54+
55+
RM3100::~RM3100() {
56+
delete dev;
57+
}
58+
59+
60+
RM3100::RM3100(MF_I2C *i2c, uint8_t i2c_adr, uint16_t cycle_count) {
61+
dev = new MF_I2CDevice(i2c, i2c_adr);
62+
63+
//set cycle count
64+
uint8_t d[6];
65+
for(int i=0;i<6;i+=2) {
66+
d[i]= cycle_count >> 8;
67+
d[i+1] = cycle_count;
68+
}
69+
dev->writeReg(RM3100_REG_CCX, d, 6);
70+
71+
scale_uT = 1 / ((0.3671 * (float)cycle_count) + 1.5); //scale factor in uT/LSB
72+
//Note: should be 74LSB/uT at cc=200, but appears to be 10 times less with my sensor...
73+
74+
// Set delay time between readings - this appears not to work as documented, value is read as 0x71 after power-up
75+
//dev->writeReg(RM3100_REG_TMRC, 0x92); //1.7 ms
76+
77+
int tries = 10;
78+
while(tries) {
79+
// Continuous measurement
80+
dev->writeReg(RM3100_REG_CMM, 0x71);
81+
delay(10);
82+
83+
// Needed to get cmm started....
84+
if(dataReady()) break;
85+
tries--;
86+
}
87+
}
88+
89+
90+
bool RM3100::dataReady() {
91+
return ( (dev->readReg(RM3100_REG_STATUS) & 0x80) == 0x80 );
92+
}
93+
94+
95+
void RM3100::readRaw(int32_t *xyz) {
96+
uint8_t d[9];
97+
dev->readReg(RM3100_REG_MX, d, 9);
98+
//Serial.printf("RM3100.readRaw() %02X%02X%02X %02X%02X%02X %02X%02X%02X\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8]);
99+
100+
int j = 0;
101+
for(int i=0;i<3;i++) {
102+
xyz[i] = (d[j]<<16) | (d[j+1]<<8) | d[j+2];
103+
if(xyz[i] & 0x00800000) xyz[i] |= 0xFF000000; //24bit sign expansion
104+
j+=3;
105+
}
106+
//Serial.printf("RM3100.readRaw() %d %d %d %f\n", (int)xyz[0], (int)xyz[1], (int)xyz[2], scale_uT);
107+
}
108+
109+
110+
void RM3100::read(float *x, float *y, float *z) {
111+
int32_t xyz[3];
112+
readRaw(xyz);
113+
*x = xyz[0] * scale_uT;
114+
*y = xyz[1] * scale_uT;
115+
*z = xyz[2] * scale_uT;
116+
}

src/madflight/mag/RM3100/RM3100.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*==========================================================================================
2+
MIT License
3+
4+
Copyright (c) 2023-2025 https://madflight.com
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
===========================================================================================*/
24+
25+
#pragma once
26+
27+
#include "../../hal/MF_I2C.h"
28+
29+
class RM3100 {
30+
public:
31+
float scale_uT = 1;
32+
33+
//probe for RM3100, returns i2c address on success, or 0 on fail
34+
static uint8_t probe(MF_I2C *i2c);
35+
36+
RM3100(MF_I2C *i2c, uint8_t i2c_adr, uint16_t cycle_count=200);
37+
38+
~RM3100();
39+
40+
bool dataReady();
41+
42+
//returns xyz[3] with counts
43+
void readRaw(int32_t *xyz);
44+
45+
//returns x,y,z as uT values
46+
void read(float *x, float *y, float *z);
47+
48+
protected:
49+
MF_I2CDevice *dev;
50+
};

src/madflight/mag/mag.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ SOFTWARE.
2828
#include "mag.h"
2929
#include "MagGizmoQMC5883L.h"
3030
#include "MagGizmoQMC6309.h"
31+
#include "MagGizmoRM3100.h"
3132

3233
//create global module instance
3334
Mag mag;
@@ -59,6 +60,9 @@ int Mag::setup() {
5960
gizmo = new MagGizmoQMC6309(config.i2c_bus, config.i2c_adr);
6061
}
6162
break;
63+
case Cfg::mag_gizmo_enum::mf_RM3100 :
64+
gizmo = MagGizmoRM3100::create(config.i2c_bus);
65+
break;
6266
}
6367

6468
//check gizmo

0 commit comments

Comments
 (0)