Skip to content

Commit ae4af77

Browse files
Supported Sensors Magnetometers: QMC5883P (#184)
* Add files via upload * Add 'QMC5883P' to device choices in MagDevice * Add MAG_QMC5883P to MagDevice.h enum * Add support for MagQMC5338P device detection * Add QMC5883P to supported magnetometers list * Update MagDevice.cpp * BusDevice.cpp * Update MagQMC5338P.h * Update Hardware.cpp
1 parent 577efda commit ae4af77

File tree

5 files changed

+131
-3
lines changed

5 files changed

+131
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ After flashing you need to configure few things first:
9090

9191
* Gyro: MPU6050, MPU6000, MPU6500, MPU9250, ICM20602, BMI160
9292
* Barometers: BMP180, BMP280, SPL06
93-
* Magnetometers: HMC5883, QMC5883, AK8963
93+
* Magnetometers: HMC5883, QMC5883, AK8963, QMC5883P
9494
* Receivers: PPM, SBUS, IBUS, CRSF/ELRS
9595
* Esc Protocols: PWM, BRUSHED, ONESHOT125, ONESHOT42, MULTISHOT, DSHOT150, DSHOT300, DSHOT600
9696
* Other protocols: MSP, CLI, BLACKBOX, ESPNOW

lib/Espfc/src/Device/MagDevice.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Espfc::Device {
66

77
const char ** MagDevice::getNames()
88
{
9-
static const char* devChoices[] = { PSTR("AUTO"), PSTR("NONE"), PSTR("HMC5883L"), PSTR("AK8975"), PSTR("AK8963"), PSTR("QMC5883L"),NULL };
9+
static const char* devChoices[] = { PSTR("AUTO"), PSTR("NONE"), PSTR("HMC5883L"), PSTR("AK8975"), PSTR("AK8963"), PSTR("QMC5883L"),PSTR("QMC5883P"),NULL };
1010
return devChoices;
1111
}
1212

@@ -16,4 +16,4 @@ const char * MagDevice::getName(DeviceType type)
1616
return getNames()[type];
1717
}
1818

19-
}
19+
}

lib/Espfc/src/Device/MagDevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ enum MagDeviceType {
1212
MAG_AK8975 = 3,
1313
MAG_AK8963 = 4,
1414
MAG_QMC5883 = 5,
15+
MAG_QMC5883P= 6,
1516
MAG_MAX
1617
};
1718

lib/Espfc/src/Device/MagQMC5338P.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#ifndef _ESPFC_DEVICE_MAG_QMC5338P_H_
2+
#define _ESPFC_DEVICE_MAG_QMC5338P_H_
3+
4+
#include "MagDevice.h"
5+
#include "BusDevice.h"
6+
7+
// address for QMC5883P
8+
#define QMC5883P_ADDRESS 0x2C
9+
#define QMC5883P_DEFAULT_ADDRESS 0x2C
10+
11+
// QMC5883P records according to Adafruit specifications
12+
#define QMC5883P_REG_CHIPID 0x00
13+
#define QMC5883P_REG_XOUT_LSB 0x01
14+
#define QMC5883P_REG_XOUT_MSB 0x02
15+
#define QMC5883P_REG_YOUT_LSB 0x03
16+
#define QMC5883P_REG_YOUT_MSB 0x04
17+
#define QMC5883P_REG_ZOUT_LSB 0x05
18+
#define QMC5883P_REG_ZOUT_MSB 0x06
19+
#define QMC5883P_REG_STATUS 0x09
20+
#define QMC5883P_REG_CONTROL1 0x0A
21+
#define QMC5883P_REG_CONTROL2 0x0B
22+
23+
// Range values (as defined in Adafruit lib)
24+
#define QMC5883P_RANGE_30G 0x00
25+
#define QMC5883P_RANGE_12G 0x01
26+
#define QMC5883P_RANGE_8G 0x02
27+
#define QMC5883P_RANGE_2G 0x03
28+
29+
// Mode values
30+
#define QMC5883P_MODE_CONTINUOUS 0x03 // Continuous measurement mode
31+
32+
namespace Espfc {
33+
namespace Device {
34+
35+
class MagQMC5338P : public MagDevice
36+
{
37+
public:
38+
int begin(BusDevice* bus) override
39+
{
40+
return begin(bus, QMC5883P_DEFAULT_ADDRESS);
41+
}
42+
43+
int begin(BusDevice* bus, uint8_t addr) override {
44+
setBus(bus, addr);
45+
46+
if (!testConnection()) return 0;
47+
48+
// We use ±8G (0x02) as the default range for the drone.
49+
_currentRange = QMC5883P_RANGE_8G;
50+
setMode(_currentRange);
51+
52+
// Continuous operating mode
53+
uint8_t ctrl1 = (QMC5883P_MODE_CONTINUOUS) | // bits [1:0]
54+
(0x02 << 2) | // ODR = 100Hz (0x02)
55+
(0x03 << 4) | // OSR = 1 (0x03) ← faster
56+
(0x00 << 6); // DSR = 1
57+
_bus->writeByte(_addr, QMC5883P_REG_CONTROL1, ctrl1);
58+
59+
// Initial reading
60+
uint8_t buffer[6];
61+
_bus->read(_addr, QMC5883P_REG_XOUT_LSB, 6, buffer);
62+
63+
return 1;
64+
}
65+
66+
int readMag(VectorInt16& v) override {
67+
uint8_t buffer[6];
68+
if (_bus->read(_addr, QMC5883P_REG_XOUT_LSB, 6, buffer) != 6) {
69+
return 0;
70+
}
71+
72+
// in QMC5883P: X = [MSB=0x02, LSB=0x01] → buffer[1], buffer[0]
73+
v.x = (int16_t)((buffer[1] << 8) | buffer[0]);
74+
v.y = (int16_t)((buffer[3] << 8) | buffer[2]);
75+
v.z = (int16_t)((buffer[5] << 8) | buffer[4]);
76+
77+
return 1;
78+
}
79+
80+
const VectorFloat convert(const VectorInt16& v) const override {
81+
float lsb_per_gauss;
82+
switch (_currentRange) {
83+
case QMC5883P_RANGE_30G: lsb_per_gauss = 1000.0f; break;
84+
case QMC5883P_RANGE_12G: lsb_per_gauss = 2500.0f; break;
85+
case QMC5883P_RANGE_8G: lsb_per_gauss = 3750.0f; break;
86+
case QMC5883P_RANGE_2G: lsb_per_gauss = 15000.0f; break;
87+
default: lsb_per_gauss = 3750.0f; // fallback to 8G
88+
}
89+
float scale = 1.0f / lsb_per_gauss;
90+
return VectorFloat{ v.x * scale, v.y * scale, v.z * scale };
91+
}
92+
93+
int getRate() const override {
94+
return 100; // Based on ODR = 100Hz
95+
}
96+
97+
virtual MagDeviceType getType() const override {
98+
return MAG_QMC5883P;
99+
}
100+
101+
void setMode(uint8_t range) {
102+
_currentRange = range;
103+
// Set the bits to [3:2] in CONTROL2
104+
uint8_t ctrl2 = (range << 2);
105+
_bus->writeByte(_addr, QMC5883P_REG_CONTROL2, ctrl2);
106+
}
107+
108+
bool testConnection() override {
109+
uint8_t chip_id;
110+
if (_bus->read(_addr, QMC5883P_REG_CHIPID, 1, &chip_id) != 1) {
111+
return false;
112+
}
113+
return chip_id == 0x80;
114+
}
115+
116+
private:
117+
uint8_t _currentRange = QMC5883P_RANGE_8G;
118+
};
119+
120+
}
121+
}
122+
123+
#endif

lib/Espfc/src/Hardware.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "Device/GyroBMI160.h"
99
#include "Device/MagHMC5338L.h"
1010
#include "Device/MagQMC5338L.h"
11+
#include "Device/MagQMC5338P.h"
1112
#include "Device/MagAK8963.h"
1213
#include "Device/BaroDevice.h"
1314
#include "Device/BaroBMP085.h"
@@ -40,6 +41,7 @@ namespace {
4041
static Espfc::Device::GyroBMI160 bmi160;
4142
static Espfc::Device::MagHMC5338L hmc5883l;
4243
static Espfc::Device::MagQMC5338L qmc5883l;
44+
static Espfc::Device::MagQMC5338P qmc5883p;
4345
static Espfc::Device::MagAK8963 ak8963;
4446
static Espfc::Device::BaroBMP085 bmp085;
4547
static Espfc::Device::BaroBMP280 bmp280;
@@ -128,13 +130,15 @@ void Hardware::detectMag()
128130
if(!detectedMag && detectDevice(ak8963, i2cBus)) detectedMag = &ak8963;
129131
if(!detectedMag && detectDevice(hmc5883l, i2cBus)) detectedMag = &hmc5883l;
130132
if(!detectedMag && detectDevice(qmc5883l, i2cBus)) detectedMag = &qmc5883l;
133+
if(!detectedMag && detectDevice(qmc5883p, i2cBus)) detectedMag = &qmc5883p;
131134
}
132135
#endif
133136
if(gyroSlaveBus.getBus())
134137
{
135138
if(!detectedMag && detectDevice(ak8963, gyroSlaveBus)) detectedMag = &ak8963;
136139
if(!detectedMag && detectDevice(hmc5883l, gyroSlaveBus)) detectedMag = &hmc5883l;
137140
if(!detectedMag && detectDevice(qmc5883l, gyroSlaveBus)) detectedMag = &qmc5883l;
141+
if(!detectedMag && detectDevice(qmc5883p, gyroSlaveBus)) detectedMag = &qmc5883p;
138142

139143
}
140144
_model.state.mag.dev = detectedMag;

0 commit comments

Comments
 (0)