Skip to content

Commit 0113b28

Browse files
committed
add FC1
1 parent 604c0f9 commit 0113b28

File tree

8 files changed

+308
-35
lines changed

8 files changed

+308
-35
lines changed

extras/I2C_Chip_Scanner/I2C_Chip_Scanner.ino

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ TwoWire *i2c = &Wire;
2525
#define ESP32_SDA_PIN 23
2626
#define ESP32_SCL_PIN 22
2727

28-
#define RP2040_SDA_PIN 20 //Wire: 0, 4(default), 8, 12, 16, 20 Wire1: 2, 6, 10, 14, 18, 26(default)
29-
#define RP2040_SCL_PIN 21 //Wire: 1, 5(default), 9, 13, 17, 21 Wire1: 3, 7, 11, 15, 19, 27(default)
28+
#define RP2040_SDA_PIN 32 //RP2040/RP2350A Wire: 0, 4(default), 8, 12, 16, 20 Wire1: 2, 6, 10, 14, 18, 26(default)
29+
#define RP2040_SCL_PIN 33 //RP2040/RP2350A Wire: 1, 5(default), 9, 13, 17, 21 Wire1: 3, 7, 11, 15, 19, 27(default)
3030

3131
#define STM32_SDA_PIN PB9
3232
#define STM32_SCL_PIN PB8
3333

34-
#define I2C_FRQ 400000
34+
#define I2C_FRQ 100000
3535

3636

3737

@@ -46,6 +46,7 @@ void setup() {
4646
i2c->setSDA(RP2040_SDA_PIN);
4747
i2c->setSCL(RP2040_SCL_PIN);
4848
i2c->setClock(I2C_FRQ);
49+
i2c->setTimeout(25, true); //timeout, reset_with_timeout
4950
i2c->begin();
5051
#elif defined ARDUINO_ARCH_STM32
5152
i2c->setSDA(STM32_SDA_PIN);
@@ -63,16 +64,17 @@ void loop() {
6364

6465
Serial.printf("I2C: Scanning ...\n");
6566
int num_adr_found = 0;
66-
for (uint8_t adr = 8; adr < 120; adr++) {
67+
for (uint8_t adr = 1; adr < 128; adr++) {
6768
i2c->beginTransmission(adr); // Begin I2C transmission Address (i)
6869
if (i2c->endTransmission() == 0) { // Receive 0 = success (ACK response)
6970
Serial.printf("I2C: Found address: 0x%02X (decimal %d)\n",adr,adr);
7071
num_adr_found++;
7172
i2c_identify_chip(adr);
7273
}
74+
delay(10);
7375
}
7476
Serial.printf("I2C: Found %d device(s)\n", num_adr_found);
75-
delay(1000);
77+
delay(100);
7678
}
7779

7880
struct test_struct{
@@ -108,6 +110,7 @@ test_struct tests[] = {
108110
{0x68, 0x69, 0x75, 1, 0x75, "FAKE MPU9250, got WHO_AM_I=0x75, real chip returns 0x71"},
109111
{0x68, 0x69, 0x75, 1, 0x78, "FAKE MPU9250, got WHO_AM_I=0x78, real chip returns 0x71"},
110112
{0x68, 0x69, 0x75, 1, 0x98, "ICM20689 6DOF motion"},
113+
{0x76, 0x77, 0x8F, 1, 0x80, "HP203B pressure"}, //needs to be first 0x76 sensor, otherwise this sensor will lock up
111114
{0x76, 0x77, 0x00, 1, 0x50, "BMP388 pressure"},
112115
{0x76, 0x77, 0x00, 1, 0x60, "BMP390 pressure"},
113116
{0x76, 0x77, 0x0D, 1, 0x10, "DPS310, HP303B, or SPL06 pressure"},
@@ -117,6 +120,7 @@ test_struct tests[] = {
117120
{0x76, 0x77, 0xD0, 1, 0x58, "BMP280 pressure"},
118121
{0x76, 0x77, 0xD0, 1, 0x60, "BME280 pressure, temperature, humidity"},
119122
{0x76, 0x77, 0xD0, 1, 0x61, "BME680 pressure, temperature, humidity, gas sensor"},
123+
{0x7C, 0x7C, 0x00, 1, 0x90, "QMC6309 magnetometer"},
120124

121125
{0,0,0,0,0,""} //end
122126
};
@@ -202,6 +206,7 @@ void i2c_ReadRegs( uint8_t adr, uint8_t reg, uint8_t *data, uint8_t n ) {
202206
if(bytesReceived == n) {
203207
i2c->readBytes(data, bytesReceived);
204208
}
209+
i2c->endTransmission();
205210
}
206211

207212
void i2c_scan() {

src/madflight.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,8 @@ void madflight_setup() {
124124
cfg.load_madflight(madflight_board, madflight_config); //load config
125125

126126
#ifdef MF_DEBUG
127-
if(madflight_config) {
128-
Serial.println("\nDEBUG: madflight_config ==============\n");
129-
Serial.println(madflight_config);
130-
}
131-
Serial.println("\nDEBUG: cfg.list() ================\n");
132-
cfg.list();
127+
//Serial.println("\nDEBUG: cfg.list() ================\n");
128+
//cfg.list();
133129
#endif
134130

135131
cfg.printPins();

src/madflight/bar/BarGizmoHP203B.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,42 @@ class BarGizmoHP203B: public BarGizmo {
99
public:
1010
BarGizmoHP203B(MF_I2C *i2c, int8_t i2c_adr, uint32_t sampleRate) {
1111
(void) sampleRate; //TODO
12-
if(i2c_adr == 0) i2c_adr = 0XEC; // fixed: 0XEC or 0xEE
12+
if(i2c_adr == 0) i2c_adr = 0x76; // fixed: 0x76 or 0x77
1313
this->dev = new MF_I2CDevice(i2c, i2c_adr);
14-
dev->writeReg(0b01010000, nullptr, 0); // ADC_CVT = 010, 100 OSR=256 (8.2ms), 00 press+temp
14+
15+
dev->writeReg(0x06, nullptr, 0); //SOFT_RST soft reset
16+
dev->writeReg(0x28, nullptr, 0); //ANA_CAL Re-calibrate the Internal analog Blocks
17+
dev->writeReg(0b01010000, nullptr, 0); //start conversion: ADC_CVT = 010, 100 OSR=256 (8.2ms), 00 press+temp
1518
}
1619

1720
~BarGizmoHP203B() {
1821
delete dev;
1922
}
2023

24+
25+
26+
/*
27+
OSR T[ms] ADC_CVT
28+
128 4.1 0b01010100
29+
256 8.2 0b01010000
30+
512 16.4 0b01001100
31+
1024 32.8 0b01001000
32+
2048 65.6 0b01000100
33+
4096 131.1 0b01000000
34+
*/
2135
bool update(float *press, float *temp) override {
2236
uint8_t d[6];
23-
dev->readReg(0x10, d, 6); //READ_PT
37+
dev->readReg(0x10, d, 6); //READ_PT pressure [Pa] + temp [0.01*C]
38+
//dev->readReg(0x11, d, 6); //READ_AT altitude [0.01*m] + temp [0.01*C]
39+
dev->writeReg(0b01010000, nullptr, 0); //start conversion: ADC_CVT = 010, 100 OSR=256 (8.2ms), 00 press+temp
40+
2441
int32_t t = ((d[0] << 16) | (d[1] << 8) | d[2]) & 0x000fffff; //20 bit big-endian signed
2542
if(t & 0x00080000) t |= 0xfff00000; //20bit sign expansion
2643
uint32_t p = ((d[3] << 16) | (d[4] << 8) | d[5]) & 0x000fffff; //20 bit big-endian unsigned
2744

2845
*temp = t * 0.01; //temperature in [C]
29-
*press = 0.01 * p; //pressure in [Pa]
46+
*press = p; //pressure in [Pa]
47+
3048
return true;
3149
}
3250
};

src/madflight/cli/cli.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ void Cli::print_i2cScan() {
408408
if(i2c) {
409409
Serial.printf("I2C: Scanning i2c_bus:%d - ", bus_i);
410410
int count = 0;
411-
for (byte i = 8; i < 120; i++) {
411+
for (byte i = 1; i < 128; i++) {
412412
i2c->beginTransmission(i); // Begin I2C transmission Address (i)
413413
if (i2c->endTransmission() == 0) { // Receive 0 = success (ACK response)
414414
Serial.printf("0x%02X(%d) ", i, i);

src/madflight/cli/stat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ class Stat {
3636
return sqrt(var());
3737
}
3838
void print(const char *hdr) {
39-
Serial.printf("%s mean:%+f stdev:%f var:%f min:%+f max:%+f n:%d\n", hdr, mean(), std(), var(), min, max, n);
39+
Serial.printf("%s\tmean:%+f\tstdev:%f\tmin:%+f\tmax:%+f\tn:%d\n", hdr, mean(), std(), min, max, n);
4040
}
4141
};

src/madflight/mag/MagGizmoQMC6309.h

Lines changed: 144 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,163 @@ SOFTWARE.
2727
#include "mag.h"
2828
#include "../hal/MF_I2C.h"
2929

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+
3093
class MagGizmoQMC6309 : public MagGizmo {
3194
private:
3295
MF_I2CDevice *dev = nullptr;
3396

97+
3498
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;
38103

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;
42106
}
43107

108+
MagGizmoQMC6309(MF_I2C *i2c) {
109+
i2c->setClock(400000);
44110

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+
*/
47165
}
48166

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;
49170

50-
bool update(float *x, float *y, float *z) override {
51171
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;
60187
return true;
61188
}
62189
};

src/madflight/mag/mag.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ int Mag::setup() {
5757
break;
5858
case Cfg::mag_gizmo_enum::mf_QMC6309 :
5959
if(config.i2c_bus) {
60-
gizmo = new MagGizmoQMC6309(config.i2c_bus, config.i2c_adr);
60+
gizmo = new MagGizmoQMC6309(config.i2c_bus); //i2c address is always 0x7C
6161
}
6262
break;
6363
case Cfg::mag_gizmo_enum::mf_RM3100 :

0 commit comments

Comments
 (0)