Skip to content

Commit 6ee683a

Browse files
authored
Merge pull request #10382 from breadoven/abo_baro_temp_compensation
Accelerometer and Barometer temperature compensation
2 parents 48ba62a + ee8d4b1 commit 6ee683a

11 files changed

Lines changed: 197 additions & 19 deletions

File tree

docs/Sensors.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Sensors
2+
3+
## Temperature Correction
4+
Temperature related drift for the Nav Accelerometer Z axis and Barometer can be corrected using settings `acc_temp_correction` and `baro_temp_correction`. The settings are temperature correction factor in cms-2/K and cm/K respectively, limited to -50 to +50, and are based on a linear correction characteristic. It is possible to perform an auto calibration of the required correction value using a setting of 51 with the auto calibration ending after a 5 minute timeout or on first arm. It's also possible to simply enter a value and see how the sensor drifts as the FC warms up, e.g. a BMP280 barometer requires a value around 20 cm/K for the `baro_temp_correction` setting.
5+
6+
### Barometer Calibration
7+
Best calibrated by checking barometer altitude in the Configurator Sensor tab, powered just from USB or the main battery. First check Barometer altitude drift with `baro_temp_correction` set to 0 starting with a cold FC. Then change the setting to 51, power off and allow the FC to cool then power on again and recheck the barometer altitude in the Configurator Sensors tab. The barometer altitude will drift as before until 5 mins after bootup at which point, if the calibration has worked, the barometer altitude should fall close to 0. This will be accompanied by a "success" beep (may need battery power for this rather than just USB). The calibrated setting can be saved by switching to the CLI and hitting "Save Settings" (or use the Save stick command or CMS). Power off and allow the FC to cool down then recheck barometer altitude again, it should show much reduced altitude drift as it warms up.
8+
9+
### Nav Acceleromter Z Axis Calibration
10+
The Nav accelerometer Z axis is calibrated in a similar way to the Barometer except it isn't so easy to check while calibrating given the lack of direct feedback. The acc Z value in the Configurator Sensors tab isn't the corrected value so can't be used. Instead set `debug_mode` to `ALTITUDE` and check the behaviour of `Debug 3` in the Configurator Sensors Tab for Debug output. It will drift during calibration then show a sudden change when calibration is finished. After saving and rebooting check `Debug 3` in the Configurator Sensors tab, it should show much less drift from zero if the calibration was successful. Successful calibration can also be checked by making sure `acc_temp_correction` shows a value other than 0 or 51.
11+
12+
13+
14+
15+
16+
17+

docs/Settings.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,16 @@ Frequency of the software notch filter to remove mechanical vibrations from the
122122

123123
---
124124

125+
### acc_temp_correction
126+
127+
Accelerometer temperature correction factor to compensate for acceleromter drift with changes in acceleromter temperature [cm/s2 per Degs C]. Internally limited to between -50 and 50. Typical setting for MPU6000 acceleromter is around 2.5. Setting to 51 initiates auto calibration which ends after 5 minutes or on first Arm.
128+
129+
| Default | Min | Max |
130+
| --- | --- | --- |
131+
| 0 | -50 | 51 |
132+
133+
---
134+
125135
### accgain_x
126136

127137
Calculated value after '6 position avanced calibration'. Uncalibrated value is 4096. See Wiki page.
@@ -452,6 +462,16 @@ Selection of baro hardware. See Wiki Sensor auto detect and hardware failure det
452462

453463
---
454464

465+
### baro_temp_correction
466+
467+
Baro temperature correction factor to compensate for Baro altitude drift with changes in Baro temperature [cm/Degs C]. Internally limited to between -50 and 50. Typical setting for BMP280 Baro is around 20. Setting to 51 initiates auto calibration which ends after 5 minutes or on first Arm.
468+
469+
| Default | Min | Max |
470+
| --- | --- | --- |
471+
| 0 | -50 | 51 |
472+
473+
---
474+
455475
### bat_cells
456476

457477
Number of cells of the battery (0 = auto-detect), see battery documentation. 7S, 9S and 11S batteries cannot be auto-detected.

src/main/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ main_sources(COMMON_SRC
216216
drivers/pitotmeter/pitotmeter_ms4525.c
217217
drivers/pitotmeter/pitotmeter_ms4525.h
218218
drivers/pitotmeter/pitotmeter_dlvr_l10d.c
219-
drivers/pitotmeter/pitotmeter_dlvr_l10d.h
219+
drivers/pitotmeter/pitotmeter_dlvr_l10d.h
220220
drivers/pitotmeter/pitotmeter_msp.c
221221
drivers/pitotmeter/pitotmeter_msp.h
222222
drivers/pitotmeter/pitotmeter_virtual.c
@@ -460,6 +460,7 @@ main_sources(COMMON_SRC
460460
sensors/esc_sensor.h
461461
sensors/irlock.c
462462
sensors/irlock.h
463+
sensors/sensors.c
463464
sensors/temperature.c
464465
sensors/temperature.h
465466

src/main/fc/settings.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,12 @@ groups:
467467
default_value: "BIQUAD"
468468
field: acc_soft_lpf_type
469469
table: filter_type
470+
- name: acc_temp_correction
471+
description: "Accelerometer temperature correction factor to compensate for acceleromter drift with changes in acceleromter temperature [cm/s2 per Degs C]. Internally limited to between -50 and 50. Typical setting for MPU6000 acceleromter is around 2.5. Setting to 51 initiates auto calibration which ends after 5 minutes or on first Arm."
472+
field: acc_temp_correction
473+
min: -50
474+
max: 51
475+
default_value: 0
470476
- name: acczero_x
471477
description: "Calculated value after '6 position avanced calibration'. See Wiki page."
472478
default_value: 0
@@ -642,6 +648,12 @@ groups:
642648
field: baro_calibration_tolerance
643649
min: 0
644650
max: 1000
651+
- name: baro_temp_correction
652+
description: "Baro temperature correction factor to compensate for Baro altitude drift with changes in Baro temperature [cm/Degs C]. Internally limited to between -50 and 50. Typical setting for BMP280 Baro is around 20. Setting to 51 initiates auto calibration which ends after 5 minutes or on first Arm."
653+
field: baro_temp_correction
654+
min: -50
655+
max: 51
656+
default_value: 0
645657

646658
- name: PG_PITOTMETER_CONFIG
647659
type: pitotmeterConfig_t

src/main/navigation/navigation_pos_estimator.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@
5050
#include "sensors/barometer.h"
5151
#include "sensors/compass.h"
5252
#include "sensors/gyro.h"
53-
#include "sensors/pitotmeter.h"
5453
#include "sensors/opflow.h"
54+
#include "sensors/pitotmeter.h"
55+
#include "sensors/sensors.h"
5556

5657
navigationPosEstimator_t posEstimator;
5758
static float initialBaroAltitudeOffset = 0.0f;
@@ -283,12 +284,12 @@ void updatePositionEstimator_BaroTopic(timeUs_t currentTimeUs)
283284
{
284285
float newBaroAlt = baroCalculateAltitude();
285286

286-
/* If we are required - keep altitude at zero */
287-
if (shouldResetReferenceAltitude()) {
288-
initialBaroAltitudeOffset = newBaroAlt;
289-
}
290-
291287
if (sensors(SENSOR_BARO) && baroIsCalibrationComplete()) {
288+
/* If required - keep altitude at zero */
289+
if (shouldResetReferenceAltitude()) {
290+
initialBaroAltitudeOffset = newBaroAlt;
291+
}
292+
292293
const timeUs_t baroDtUs = currentTimeUs - posEstimator.baro.lastUpdateTime;
293294

294295
posEstimator.baro.alt = newBaroAlt - initialBaroAltitudeOffset;
@@ -434,6 +435,7 @@ static void updateIMUTopic(timeUs_t currentTimeUs)
434435
}
435436
#endif
436437
posEstimator.imu.accelNEU.z -= posEstimator.imu.calibratedGravityCMSS;
438+
posEstimator.imu.accelNEU.z += applySensorTempCompensation(10 * gyroGetTemperature(), imuMeasuredAccelBF.z, SENSOR_INDEX_ACC);
437439
}
438440
else { // If calibration is incomplete - report zero acceleration
439441
posEstimator.imu.accelNEU.x = 0.0f;

src/main/sensors/acceleration.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static EXTENDED_FASTRAM void *accNotchFilter[XYZ_AXIS_COUNT];
8585
static EXTENDED_FASTRAM float fAccZero[XYZ_AXIS_COUNT];
8686
static EXTENDED_FASTRAM float fAccGain[XYZ_AXIS_COUNT];
8787

88-
PG_REGISTER_WITH_RESET_FN(accelerometerConfig_t, accelerometerConfig, PG_ACCELEROMETER_CONFIG, 5);
88+
PG_REGISTER_WITH_RESET_FN(accelerometerConfig_t, accelerometerConfig, PG_ACCELEROMETER_CONFIG, 6);
8989

9090
void pgResetFn_accelerometerConfig(accelerometerConfig_t *instance)
9191
{
@@ -94,7 +94,8 @@ void pgResetFn_accelerometerConfig(accelerometerConfig_t *instance)
9494
.acc_lpf_hz = SETTING_ACC_LPF_HZ_DEFAULT,
9595
.acc_notch_hz = SETTING_ACC_NOTCH_HZ_DEFAULT,
9696
.acc_notch_cutoff = SETTING_ACC_NOTCH_CUTOFF_DEFAULT,
97-
.acc_soft_lpf_type = SETTING_ACC_LPF_TYPE_DEFAULT
97+
.acc_soft_lpf_type = SETTING_ACC_LPF_TYPE_DEFAULT,
98+
.acc_temp_correction = SETTING_ACC_TEMP_CORRECTION_DEFAULT
9899
);
99100
RESET_CONFIG_2(flightDynamicsTrims_t, &instance->accZero,
100101
.raw[X] = SETTING_ACCZERO_X_DEFAULT,
@@ -557,8 +558,8 @@ void accUpdate(void)
557558

558559
if (!ARMING_FLAG(SIMULATOR_MODE_SITL)) {
559560
performAcclerationCalibration();
560-
applyAccelerationZero();
561-
}
561+
applyAccelerationZero();
562+
}
562563

563564
applySensorAlignment(accADC, accADC, acc.dev.accAlign);
564565
applyBoardAlignment(accADC);
@@ -637,7 +638,7 @@ bool accIsClipped(void)
637638

638639
void accSetCalibrationValues(void)
639640
{
640-
if (!ARMING_FLAG(SIMULATOR_MODE_SITL) &&
641+
if (!ARMING_FLAG(SIMULATOR_MODE_SITL) &&
641642
((accelerometerConfig()->accZero.raw[X] == 0) && (accelerometerConfig()->accZero.raw[Y] == 0) && (accelerometerConfig()->accZero.raw[Z] == 0) &&
642643
(accelerometerConfig()->accGain.raw[X] == 4096) && (accelerometerConfig()->accGain.raw[Y] == 4096) &&(accelerometerConfig()->accGain.raw[Z] == 4096))) {
643644
DISABLE_STATE(ACCELEROMETER_CALIBRATED);
@@ -648,12 +649,12 @@ void accSetCalibrationValues(void)
648649
}
649650

650651
void accInitFilters(void)
651-
{
652+
{
652653
accSoftLpfFilterApplyFn = nullFilterApply;
653654

654655
if (acc.accTargetLooptime && accelerometerConfig()->acc_lpf_hz) {
655656

656-
switch (accelerometerConfig()->acc_soft_lpf_type)
657+
switch (accelerometerConfig()->acc_soft_lpf_type)
657658
{
658659
case FILTER_PT1:
659660
accSoftLpfFilterApplyFn = (filterApplyFnPtr)pt1FilterApply;

src/main/sensors/acceleration.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ typedef struct accelerometerConfig_s {
7474
flightDynamicsTrims_t accGain; // Accelerometer gain to read exactly 1G
7575
uint8_t acc_notch_hz; // Accelerometer notch filter frequency
7676
uint8_t acc_notch_cutoff; // Accelerometer notch filter cutoff frequency
77-
uint8_t acc_soft_lpf_type; // Accelerometer LPF type
77+
uint8_t acc_soft_lpf_type; // Accelerometer LPF type
78+
float acc_temp_correction; // Accelerometer temperature compensation factor
7879
} accelerometerConfig_t;
7980

8081
PG_DECLARE(accelerometerConfig_t, accelerometerConfig);

src/main/sensors/barometer.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,12 @@ baro_t baro; // barometer access functions
5858

5959
#ifdef USE_BARO
6060

61-
PG_REGISTER_WITH_RESET_TEMPLATE(barometerConfig_t, barometerConfig, PG_BAROMETER_CONFIG, 4);
61+
PG_REGISTER_WITH_RESET_TEMPLATE(barometerConfig_t, barometerConfig, PG_BAROMETER_CONFIG, 5);
6262

6363
PG_RESET_TEMPLATE(barometerConfig_t, barometerConfig,
6464
.baro_hardware = SETTING_BARO_HARDWARE_DEFAULT,
65-
.baro_calibration_tolerance = SETTING_BARO_CAL_TOLERANCE_DEFAULT
65+
.baro_calibration_tolerance = SETTING_BARO_CAL_TOLERANCE_DEFAULT,
66+
.baro_temp_correction = SETTING_BARO_TEMP_CORRECTION_DEFAULT,
6667
);
6768

6869
static zeroCalibrationScalar_t zeroCalibration;
@@ -325,6 +326,7 @@ int32_t baroCalculateAltitude(void)
325326
else {
326327
// calculates height from ground via baro readings
327328
baro.BaroAlt = pressureToAltitude(baro.baroPressure) - baroGroundAltitude;
329+
baro.BaroAlt += applySensorTempCompensation(baro.baroTemperature, baro.BaroAlt, SENSOR_INDEX_BARO);
328330
}
329331

330332
return baro.BaroAlt;
@@ -336,7 +338,7 @@ int32_t baroGetLatestAltitude(void)
336338
}
337339

338340
int16_t baroGetTemperature(void)
339-
{
341+
{
340342
return CENTIDEGREES_TO_DECIDEGREES(baro.baroTemperature);
341343
}
342344

src/main/sensors/barometer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ extern baro_t baro;
5252
typedef struct barometerConfig_s {
5353
uint8_t baro_hardware; // Barometer hardware to use
5454
uint16_t baro_calibration_tolerance; // Baro calibration tolerance (cm at sea level)
55+
float baro_temp_correction; // Baro temperature correction value (cm/K)
5556
} barometerConfig_t;
5657

5758
PG_DECLARE(barometerConfig_t, barometerConfig);
5859

59-
6060
bool baroInit(void);
6161
bool baroIsCalibrationComplete(void);
6262
void baroStartCalibration(void);

src/main/sensors/sensors.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* This file is part of INAV.
3+
*
4+
* INAV is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* INAV is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with INAV. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "platform.h"
19+
20+
#include "build/debug.h"
21+
22+
#include "common/maths.h"
23+
24+
#include "config/parameter_group.h"
25+
#include "config/parameter_group_ids.h"
26+
27+
#include "drivers/time.h"
28+
29+
#include "fc/runtime_config.h"
30+
31+
#include "io/beeper.h"
32+
33+
#include "sensors/acceleration.h"
34+
#include "sensors/barometer.h"
35+
#include "sensors/sensors.h"
36+
37+
sensor_compensation_t sensor_comp_data[SENSOR_INDEX_COUNT];
38+
39+
float applySensorTempCompensation(int16_t sensorTemp, float sensorMeasurement, sensorIndex_e sensorType)
40+
{
41+
float setting = 0.0f;
42+
if (sensorType == SENSOR_INDEX_ACC) {
43+
setting = accelerometerConfig()->acc_temp_correction;
44+
}
45+
#ifdef USE_BARO
46+
else if (sensorType == SENSOR_INDEX_BARO) {
47+
setting = barometerConfig()->baro_temp_correction;
48+
}
49+
#endif
50+
if (!setting) {
51+
return 0.0f;
52+
}
53+
54+
if (sensor_comp_data[sensorType].calibrationState == SENSOR_TEMP_CAL_COMPLETE) {
55+
return sensor_comp_data[sensorType].correctionFactor * CENTIDEGREES_TO_DEGREES(sensor_comp_data[sensorType].referenceTemp - sensorTemp);
56+
}
57+
58+
static timeMs_t startTimeMs = 0;
59+
60+
if (!ARMING_FLAG(WAS_EVER_ARMED)) {
61+
if (sensor_comp_data[sensorType].calibrationState == SENSOR_TEMP_CAL_INITIALISE) {
62+
sensor_comp_data[sensorType].referenceTemp = sensorTemp;
63+
sensor_comp_data[sensorType].calibrationState = SENSOR_TEMP_CAL_IN_PROGRESS;
64+
}
65+
66+
if (setting == 51.0f) { // initiate auto calibration
67+
if (sensor_comp_data[sensorType].referenceTemp == sensorTemp) {
68+
sensor_comp_data[sensorType].referenceMeasurement = sensorMeasurement;
69+
sensor_comp_data[sensorType].lastTemp = sensorTemp;
70+
startTimeMs = millis();
71+
}
72+
73+
float referenceDeltaTemp = ABS(sensorTemp - sensor_comp_data[sensorType].referenceTemp); // centidegrees
74+
if (referenceDeltaTemp > 300 && referenceDeltaTemp > ABS(sensor_comp_data[sensorType].lastTemp - sensor_comp_data[sensorType].referenceTemp)) {
75+
/* Min 3 deg reference temperature difference required for valid calibration.
76+
* Correction adjusted only if temperature difference to reference temperature increasing
77+
* Calibration assumes a simple linear relationship */
78+
sensor_comp_data[sensorType].lastTemp = sensorTemp;
79+
sensor_comp_data[sensorType].correctionFactor = 0.9f * sensor_comp_data[sensorType].correctionFactor + 0.1f * (sensorMeasurement - sensor_comp_data[sensorType].referenceMeasurement) / CENTIDEGREES_TO_DEGREES(sensor_comp_data[sensorType].lastTemp - sensor_comp_data[sensorType].referenceTemp);
80+
sensor_comp_data[sensorType].correctionFactor = constrainf(sensor_comp_data[sensorType].correctionFactor, -50.0f, 50.0f);
81+
}
82+
} else {
83+
sensor_comp_data[sensorType].correctionFactor = setting;
84+
sensor_comp_data[sensorType].calibrationState = SENSOR_TEMP_CAL_COMPLETE;
85+
}
86+
}
87+
88+
// Calibration ends on first Arm or after 5 min timeout
89+
if (sensor_comp_data[sensorType].calibrationState == SENSOR_TEMP_CAL_IN_PROGRESS && (ARMING_FLAG(WAS_EVER_ARMED) || millis() > startTimeMs + 300000)) {
90+
if (!ARMING_FLAG(WAS_EVER_ARMED)) {
91+
beeper(sensor_comp_data[sensorType].correctionFactor ? BEEPER_ACTION_SUCCESS : BEEPER_ACTION_FAIL);
92+
}
93+
94+
if (sensorType == SENSOR_INDEX_ACC) {
95+
accelerometerConfigMutable()->acc_temp_correction = sensor_comp_data[sensorType].correctionFactor;
96+
}
97+
#ifdef USE_BARO
98+
else if (sensorType == SENSOR_INDEX_BARO) {
99+
barometerConfigMutable()->baro_temp_correction = sensor_comp_data[sensorType].correctionFactor;
100+
}
101+
#endif
102+
sensor_comp_data[sensorType].calibrationState = SENSOR_TEMP_CAL_COMPLETE;
103+
startTimeMs = 0;
104+
}
105+
106+
return 0.0f;
107+
}

0 commit comments

Comments
 (0)