Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / sensors / barometer.c
blob6604ccc1c82664122fd9da36c5124dc0cfc71a34
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight 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.
9 * Cleanflight 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.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <math.h>
22 #include "platform.h"
23 #include "build/debug.h"
25 #include "common/calibration.h"
26 #include "common/log.h"
27 #include "common/maths.h"
28 #include "common/time.h"
29 #include "common/utils.h"
31 #include "config/parameter_group.h"
32 #include "config/parameter_group_ids.h"
34 #include "drivers/barometer/barometer.h"
35 #include "drivers/barometer/barometer_bmp085.h"
36 #include "drivers/barometer/barometer_bmp280.h"
37 #include "drivers/barometer/barometer_bmp388.h"
38 #include "drivers/barometer/barometer_lps25h.h"
39 #include "drivers/barometer/barometer_fake.h"
40 #include "drivers/barometer/barometer_ms56xx.h"
41 #include "drivers/barometer/barometer_spl06.h"
42 #include "drivers/barometer/barometer_dps310.h"
43 #include "drivers/barometer/barometer_2smpb_02b.h"
44 #include "drivers/barometer/barometer_msp.h"
45 #include "drivers/time.h"
47 #include "fc/runtime_config.h"
48 #include "fc/settings.h"
50 #include "sensors/barometer.h"
51 #include "sensors/sensors.h"
53 #ifdef USE_HARDWARE_REVISION_DETECTION
54 #include "hardware_revision.h"
55 #endif
57 baro_t baro; // barometer access functions
59 #ifdef USE_BARO
61 PG_REGISTER_WITH_RESET_TEMPLATE(barometerConfig_t, barometerConfig, PG_BAROMETER_CONFIG, 4);
63 PG_RESET_TEMPLATE(barometerConfig_t, barometerConfig,
64 .baro_hardware = SETTING_BARO_HARDWARE_DEFAULT,
65 .baro_calibration_tolerance = SETTING_BARO_CAL_TOLERANCE_DEFAULT
68 static zeroCalibrationScalar_t zeroCalibration;
69 static float baroGroundAltitude = 0;
70 static float baroGroundPressure = 101325.0f; // 101325 pascal, 1 standard atmosphere
72 bool baroDetect(baroDev_t *dev, baroSensor_e baroHardwareToUse)
74 // Detect what pressure sensors are available. baro->update() is set to sensor-specific update function
76 baroSensor_e baroHardware = BARO_NONE;
77 requestedSensors[SENSOR_INDEX_BARO] = baroHardwareToUse;
79 switch (baroHardwareToUse) {
80 case BARO_AUTODETECT:
81 case BARO_BMP085:
82 #ifdef USE_BARO_BMP085
83 if (bmp085Detect(dev)) {
84 baroHardware = BARO_BMP085;
85 break;
87 #endif
88 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
89 if (baroHardwareToUse != BARO_AUTODETECT) {
90 break;
92 FALLTHROUGH;
94 case BARO_MS5607:
95 #ifdef USE_BARO_MS5607
96 if (ms5607Detect(dev)) {
97 baroHardware = BARO_MS5607;
98 break;
100 #endif
101 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
102 if (baroHardwareToUse != BARO_AUTODETECT) {
103 break;
105 FALLTHROUGH;
107 case BARO_MS5611:
108 #ifdef USE_BARO_MS5611
109 if (ms5611Detect(dev)) {
110 baroHardware = BARO_MS5611;
111 break;
113 #endif
114 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
115 if (baroHardwareToUse != BARO_AUTODETECT) {
116 break;
118 FALLTHROUGH;
120 case BARO_BMP280:
121 #if defined(USE_BARO_BMP280) || defined(USE_BARO_SPI_BMP280)
122 if (bmp280Detect(dev)) {
123 baroHardware = BARO_BMP280;
124 break;
126 #endif
127 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
128 if (baroHardwareToUse != BARO_AUTODETECT) {
129 break;
131 FALLTHROUGH;
133 case BARO_BMP388:
134 #if defined(USE_BARO_BMP388) || defined(USE_BARO_SPI_BMP388)
135 if (bmp388Detect(dev)) {
136 baroHardware = BARO_BMP388;
137 break;
139 #endif
140 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
141 if (baroHardwareToUse != BARO_AUTODETECT) {
142 break;
144 FALLTHROUGH;
146 case BARO_SPL06:
147 #if defined(USE_BARO_SPL06) || defined(USE_BARO_SPI_SPL06)
148 if (spl06Detect(dev)) {
149 baroHardware = BARO_SPL06;
150 break;
152 #endif
153 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
154 if (baroHardwareToUse != BARO_AUTODETECT) {
155 break;
157 FALLTHROUGH;
159 case BARO_LPS25H:
160 #if defined(USE_BARO_LPS25H)
161 if (lps25hDetect(dev)) {
162 baroHardware = BARO_LPS25H;
163 break;
165 #endif
166 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
167 if (baroHardwareToUse != BARO_AUTODETECT) {
168 break;
170 FALLTHROUGH;
172 case BARO_DPS310:
173 #if defined(USE_BARO_DPS310)
174 if (baroDPS310Detect(dev)) {
175 baroHardware = BARO_DPS310;
176 break;
178 #endif
179 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
180 if (baroHardwareToUse != BARO_AUTODETECT) {
181 break;
183 FALLTHROUGH;
185 case BARO_B2SMPB:
186 #if defined(USE_BARO_B2SMPB)
187 if (baro2SMPB02BDetect(dev)) {
188 baroHardware = BARO_B2SMPB;
189 break;
191 #endif
192 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
193 if (baroHardwareToUse != BARO_AUTODETECT) {
194 break;
196 FALLTHROUGH;
198 case BARO_MSP:
199 #ifdef USE_BARO_MSP
200 // Skip autodetection for MSP baro, only allow manual config
201 if (baroHardwareToUse != BARO_AUTODETECT && mspBaroDetect(dev)) {
202 baroHardware = BARO_MSP;
203 break;
205 #endif
206 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
207 if (baroHardwareToUse != BARO_AUTODETECT) {
208 break;
210 FALLTHROUGH;
212 case BARO_FAKE:
213 #ifdef USE_FAKE_BARO
214 if (fakeBaroDetect(dev)) {
215 baroHardware = BARO_FAKE;
216 break;
218 #endif
219 /* If we are asked for a specific sensor - break out, otherwise - fall through and continue */
220 if (baroHardwareToUse != BARO_AUTODETECT) {
221 break;
223 FALLTHROUGH;
225 case BARO_NONE:
226 baroHardware = BARO_NONE;
227 break;
230 if (baroHardware == BARO_NONE) {
231 sensorsClear(SENSOR_BARO);
232 return false;
235 detectedSensors[SENSOR_INDEX_BARO] = baroHardware;
236 sensorsSet(SENSOR_BARO);
237 return true;
240 bool baroInit(void)
242 if (!baroDetect(&baro.dev, barometerConfig()->baro_hardware)) {
243 return false;
245 return true;
248 typedef enum {
249 BAROMETER_NEEDS_SAMPLES = 0,
250 BAROMETER_NEEDS_CALCULATION
251 } barometerState_e;
253 uint32_t baroUpdate(void)
255 static barometerState_e state = BAROMETER_NEEDS_SAMPLES;
257 #ifdef USE_SIMULATOR
258 if (ARMING_FLAG(SIMULATOR_MODE_HITL)) {
259 return 0;
261 #endif
263 switch (state) {
264 default:
265 case BAROMETER_NEEDS_SAMPLES:
266 if (baro.dev.get_ut) {
267 baro.dev.get_ut(&baro.dev);
269 if (baro.dev.start_up) {
270 baro.dev.start_up(&baro.dev);
272 state = BAROMETER_NEEDS_CALCULATION;
273 return baro.dev.up_delay;
274 break;
276 case BAROMETER_NEEDS_CALCULATION:
277 if (baro.dev.get_up) {
278 baro.dev.get_up(&baro.dev);
280 if (baro.dev.start_ut) {
281 baro.dev.start_ut(&baro.dev);
283 //output: baro.baroPressure, baro.baroTemperature
284 baro.dev.calculate(&baro.dev, &baro.baroPressure, &baro.baroTemperature);
285 state = BAROMETER_NEEDS_SAMPLES;
286 return baro.dev.ut_delay;
287 break;
291 static float pressureToAltitude(const float pressure)
293 return (1.0f - powf(pressure / 101325.0f, 0.190295f)) * 4433000.0f;
296 float altitudeToPressure(const float altCm)
298 return powf(1.0f - (altCm / 4433000.0f), 5.254999) * 101325.0f;
301 bool baroIsCalibrationComplete(void)
303 return zeroCalibrationIsCompleteS(&zeroCalibration) && zeroCalibrationIsSuccessfulS(&zeroCalibration);
306 void baroStartCalibration(void)
308 const float acceptedPressureVariance = (101325.0f - altitudeToPressure(barometerConfig()->baro_calibration_tolerance)); // max 30cm deviation during calibration (at sea level)
309 zeroCalibrationStartS(&zeroCalibration, CALIBRATING_BARO_TIME_MS, acceptedPressureVariance, false);
312 int32_t baroCalculateAltitude(void)
314 if (!baroIsCalibrationComplete()) {
315 zeroCalibrationAddValueS(&zeroCalibration, baro.baroPressure);
317 if (zeroCalibrationIsCompleteS(&zeroCalibration)) {
318 zeroCalibrationGetZeroS(&zeroCalibration, &baroGroundPressure);
319 baroGroundAltitude = pressureToAltitude(baroGroundPressure);
320 LOG_DEBUG(BARO, "Barometer calibration complete (%d)", (int)lrintf(baroGroundAltitude));
323 baro.BaroAlt = 0;
325 else {
326 // calculates height from ground via baro readings
327 baro.BaroAlt = pressureToAltitude(baro.baroPressure) - baroGroundAltitude;
330 return baro.BaroAlt;
333 int32_t baroGetLatestAltitude(void)
335 return baro.BaroAlt;
338 int16_t baroGetTemperature(void)
340 return CENTIDEGREES_TO_DECIDEGREES(baro.baroTemperature);
343 bool baroIsHealthy(void)
345 return sensors(SENSOR_BARO);
348 #endif /* BARO */