2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
26 #include "build/build_config.h"
27 #include "build/debug.h"
29 #include "barometer.h"
31 #include "drivers/bus.h"
32 #include "drivers/bus_i2c.h"
33 #include "drivers/bus_i2c_busdev.h"
34 #include "drivers/bus_spi.h"
35 #include "drivers/io.h"
36 #include "drivers/time.h"
38 #include "barometer_bmp280.h"
40 #if defined(USE_BARO) && (defined(USE_BARO_BMP280) || defined(USE_BARO_SPI_BMP280))
42 typedef struct bmp280_calib_param_s
{
43 uint16_t dig_T1
; /* calibration T1 data */
44 int16_t dig_T2
; /* calibration T2 data */
45 int16_t dig_T3
; /* calibration T3 data */
46 uint16_t dig_P1
; /* calibration P1 data */
47 int16_t dig_P2
; /* calibration P2 data */
48 int16_t dig_P3
; /* calibration P3 data */
49 int16_t dig_P4
; /* calibration P4 data */
50 int16_t dig_P5
; /* calibration P5 data */
51 int16_t dig_P6
; /* calibration P6 data */
52 int16_t dig_P7
; /* calibration P7 data */
53 int16_t dig_P8
; /* calibration P8 data */
54 int16_t dig_P9
; /* calibration P9 data */
55 int32_t t_fine
; /* calibration t_fine data */
56 } bmp280_calib_param_t
;
58 static uint8_t bmp280_chip_id
= 0;
59 STATIC_UNIT_TESTED bmp280_calib_param_t bmp280_cal
;
60 // uncompensated pressure and temperature
61 int32_t bmp280_up
= 0;
62 int32_t bmp280_ut
= 0;
64 static void bmp280_start_ut(baroDev_t
*baro
);
65 static void bmp280_get_ut(baroDev_t
*baro
);
66 static void bmp280_start_up(baroDev_t
*baro
);
67 static void bmp280_get_up(baroDev_t
*baro
);
69 STATIC_UNIT_TESTED
void bmp280_calculate(int32_t *pressure
, int32_t *temperature
);
71 void bmp280BusInit(busDevice_t
*busdev
)
73 #ifdef USE_BARO_SPI_BMP280
74 if (busdev
->bustype
== BUSTYPE_SPI
) {
75 IOHi(busdev
->busdev_u
.spi
.csnPin
); // Disable
76 IOInit(busdev
->busdev_u
.spi
.csnPin
, OWNER_BARO_CS
, 0);
77 IOConfigGPIO(busdev
->busdev_u
.spi
.csnPin
, IOCFG_OUT_PP
);
78 spiSetDivisor(busdev
->busdev_u
.spi
.instance
, SPI_CLOCK_STANDARD
); // XXX
85 void bmp280BusDeinit(busDevice_t
*busdev
)
87 #ifdef USE_BARO_SPI_BMP280
88 if (busdev
->bustype
== BUSTYPE_SPI
) {
89 IOConfigGPIO(busdev
->busdev_u
.spi
.csnPin
, IOCFG_IPU
);
90 IORelease(busdev
->busdev_u
.spi
.csnPin
);
91 IOInit(busdev
->busdev_u
.spi
.csnPin
, OWNER_SPI_PREINIT
, 0);
98 bool bmp280Detect(baroDev_t
*baro
)
102 busDevice_t
*busdev
= &baro
->busdev
;
103 bool defaultAddressApplied
= false;
105 bmp280BusInit(busdev
);
107 if ((busdev
->bustype
== BUSTYPE_I2C
) && (busdev
->busdev_u
.i2c
.address
== 0)) {
108 // Default address for BMP280
109 busdev
->busdev_u
.i2c
.address
= BMP280_I2C_ADDR
;
110 defaultAddressApplied
= true;
113 busReadRegisterBuffer(busdev
, BMP280_CHIP_ID_REG
, &bmp280_chip_id
, 1); /* read Chip Id */
115 if (bmp280_chip_id
!= BMP280_DEFAULT_CHIP_ID
) {
116 bmp280BusDeinit(busdev
);
117 if (defaultAddressApplied
) {
118 busdev
->busdev_u
.i2c
.address
= 0;
124 busReadRegisterBuffer(busdev
, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG
, (uint8_t *)&bmp280_cal
, 24);
126 // set oversampling + power mode (forced), and start sampling
127 busWriteRegister(busdev
, BMP280_CTRL_MEAS_REG
, BMP280_MODE
);
129 // these are dummy as temperature is measured as part of pressure
131 baro
->get_ut
= bmp280_get_ut
;
132 baro
->start_ut
= bmp280_start_ut
;
133 // only _up part is executed, and gets both temperature and pressure
134 baro
->start_up
= bmp280_start_up
;
135 baro
->get_up
= bmp280_get_up
;
136 baro
->up_delay
= ((T_INIT_MAX
+ T_MEASURE_PER_OSRS_MAX
* (((1 << BMP280_TEMPERATURE_OSR
) >> 1) + ((1 << BMP280_PRESSURE_OSR
) >> 1)) + (BMP280_PRESSURE_OSR
? T_SETUP_PRESSURE_MAX
: 0) + 15) / 16) * 1000;
137 baro
->calculate
= bmp280_calculate
;
142 static void bmp280_start_ut(baroDev_t
*baro
)
148 static void bmp280_get_ut(baroDev_t
*baro
)
154 static void bmp280_start_up(baroDev_t
*baro
)
157 // set oversampling + power mode (forced), and start sampling
158 busWriteRegister(&baro
->busdev
, BMP280_CTRL_MEAS_REG
, BMP280_MODE
);
161 static void bmp280_get_up(baroDev_t
*baro
)
163 uint8_t data
[BMP280_DATA_FRAME_SIZE
];
165 // read data from sensor
166 busReadRegisterBuffer(&baro
->busdev
, BMP280_PRESSURE_MSB_REG
, data
, BMP280_DATA_FRAME_SIZE
);
167 bmp280_up
= (int32_t)((((uint32_t)(data
[0])) << 12) | (((uint32_t)(data
[1])) << 4) | ((uint32_t)data
[2] >> 4));
168 bmp280_ut
= (int32_t)((((uint32_t)(data
[3])) << 12) | (((uint32_t)(data
[4])) << 4) | ((uint32_t)data
[5] >> 4));
171 // Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
172 // t_fine carries fine temperature as global value
173 static int32_t bmp280_compensate_T(int32_t adc_T
)
175 int32_t var1
, var2
, T
;
177 var1
= ((((adc_T
>> 3) - ((int32_t)bmp280_cal
.dig_T1
<< 1))) * ((int32_t)bmp280_cal
.dig_T2
)) >> 11;
178 var2
= (((((adc_T
>> 4) - ((int32_t)bmp280_cal
.dig_T1
)) * ((adc_T
>> 4) - ((int32_t)bmp280_cal
.dig_T1
))) >> 12) * ((int32_t)bmp280_cal
.dig_T3
)) >> 14;
179 bmp280_cal
.t_fine
= var1
+ var2
;
180 T
= (bmp280_cal
.t_fine
* 5 + 128) >> 8;
185 // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
186 // Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
187 static uint32_t bmp280_compensate_P(int32_t adc_P
)
189 int64_t var1
, var2
, p
;
190 var1
= ((int64_t)bmp280_cal
.t_fine
) - 128000;
191 var2
= var1
* var1
* (int64_t)bmp280_cal
.dig_P6
;
192 var2
= var2
+ ((var1
*(int64_t)bmp280_cal
.dig_P5
) << 17);
193 var2
= var2
+ (((int64_t)bmp280_cal
.dig_P4
) << 35);
194 var1
= ((var1
* var1
* (int64_t)bmp280_cal
.dig_P3
) >> 8) + ((var1
* (int64_t)bmp280_cal
.dig_P2
) << 12);
195 var1
= (((((int64_t)1) << 47) + var1
)) * ((int64_t)bmp280_cal
.dig_P1
) >> 33;
199 p
= (((p
<< 31) - var2
) * 3125) / var1
;
200 var1
= (((int64_t)bmp280_cal
.dig_P9
) * (p
>> 13) * (p
>> 13)) >> 25;
201 var2
= (((int64_t)bmp280_cal
.dig_P8
) * p
) >> 19;
202 p
= ((p
+ var1
+ var2
) >> 8) + (((int64_t)bmp280_cal
.dig_P7
) << 4);
206 STATIC_UNIT_TESTED
void bmp280_calculate(int32_t *pressure
, int32_t *temperature
)
211 t
= bmp280_compensate_T(bmp280_ut
);
212 p
= bmp280_compensate_P(bmp280_up
);
215 *pressure
= (int32_t)(p
/ 256);