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/>.
23 #include "build_config.h"
25 #include "barometer.h"
30 #include "barometer_bmp280.h"
34 // BMP280, address 0x76
36 #define BMP280_I2C_ADDR (0x76)
37 #define BMP280_DEFAULT_CHIP_ID (0x58)
39 #define BMP280_CHIP_ID_REG (0xD0) /* Chip ID Register */
40 #define BMP280_RST_REG (0xE0) /* Softreset Register */
41 #define BMP280_STAT_REG (0xF3) /* Status Register */
42 #define BMP280_CTRL_MEAS_REG (0xF4) /* Ctrl Measure Register */
43 #define BMP280_CONFIG_REG (0xF5) /* Configuration Register */
44 #define BMP280_PRESSURE_MSB_REG (0xF7) /* Pressure MSB Register */
45 #define BMP280_PRESSURE_LSB_REG (0xF8) /* Pressure LSB Register */
46 #define BMP280_PRESSURE_XLSB_REG (0xF9) /* Pressure XLSB Register */
47 #define BMP280_TEMPERATURE_MSB_REG (0xFA) /* Temperature MSB Reg */
48 #define BMP280_TEMPERATURE_LSB_REG (0xFB) /* Temperature LSB Reg */
49 #define BMP280_TEMPERATURE_XLSB_REG (0xFC) /* Temperature XLSB Reg */
50 #define BMP280_FORCED_MODE (0x01)
52 #define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG (0x88)
53 #define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH (24)
54 #define BMP280_DATA_FRAME_SIZE (6)
56 #define BMP280_OVERSAMP_SKIPPED (0x00)
57 #define BMP280_OVERSAMP_1X (0x01)
58 #define BMP280_OVERSAMP_2X (0x02)
59 #define BMP280_OVERSAMP_4X (0x03)
60 #define BMP280_OVERSAMP_8X (0x04)
61 #define BMP280_OVERSAMP_16X (0x05)
63 // configure pressure and temperature oversampling, forced sampling mode
64 #define BMP280_PRESSURE_OSR (BMP280_OVERSAMP_8X)
65 #define BMP280_TEMPERATURE_OSR (BMP280_OVERSAMP_1X)
66 #define BMP280_MODE (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_FORCED_MODE)
68 #define T_INIT_MAX (20)
70 #define T_MEASURE_PER_OSRS_MAX (37)
72 #define T_SETUP_PRESSURE_MAX (10)
75 typedef struct bmp280_calib_param_s
{
76 uint16_t dig_T1
; /* calibration T1 data */
77 int16_t dig_T2
; /* calibration T2 data */
78 int16_t dig_T3
; /* calibration T3 data */
79 uint16_t dig_P1
; /* calibration P1 data */
80 int16_t dig_P2
; /* calibration P2 data */
81 int16_t dig_P3
; /* calibration P3 data */
82 int16_t dig_P4
; /* calibration P4 data */
83 int16_t dig_P5
; /* calibration P5 data */
84 int16_t dig_P6
; /* calibration P6 data */
85 int16_t dig_P7
; /* calibration P7 data */
86 int16_t dig_P8
; /* calibration P8 data */
87 int16_t dig_P9
; /* calibration P9 data */
88 int32_t t_fine
; /* calibration t_fine data */
89 } bmp280_calib_param_t
;
91 static uint8_t bmp280_chip_id
= 0;
92 static bool bmp280InitDone
= false;
93 STATIC_UNIT_TESTED bmp280_calib_param_t bmp280_cal
;
94 // uncompensated pressure and temperature
95 STATIC_UNIT_TESTED
int32_t bmp280_up
= 0;
96 STATIC_UNIT_TESTED
int32_t bmp280_ut
= 0;
98 static void bmp280_start_ut(void);
99 static void bmp280_get_ut(void);
100 static void bmp280_start_up(void);
101 static void bmp280_get_up(void);
102 STATIC_UNIT_TESTED
void bmp280_calculate(int32_t *pressure
, int32_t *temperature
);
104 bool bmp280Detect(baro_t
*baro
)
111 i2cRead(BMP280_I2C_ADDR
, BMP280_CHIP_ID_REG
, 1, &bmp280_chip_id
); /* read Chip Id */
112 if (bmp280_chip_id
!= BMP280_DEFAULT_CHIP_ID
)
116 i2cRead(BMP280_I2C_ADDR
, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG
, 24, (uint8_t *)&bmp280_cal
);
117 // set oversampling + power mode (forced), and start sampling
118 i2cWrite(BMP280_I2C_ADDR
, BMP280_CTRL_MEAS_REG
, BMP280_MODE
);
120 bmp280InitDone
= true;
122 // these are dummy as temperature is measured as part of pressure
124 baro
->get_ut
= bmp280_get_ut
;
125 baro
->start_ut
= bmp280_start_ut
;
127 // only _up part is executed, and gets both temperature and pressure
128 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;
129 baro
->start_up
= bmp280_start_up
;
130 baro
->get_up
= bmp280_get_up
;
131 baro
->calculate
= bmp280_calculate
;
136 static void bmp280_start_ut(void)
141 static void bmp280_get_ut(void)
146 static void bmp280_start_up(void)
149 // set oversampling + power mode (forced), and start sampling
150 i2cWrite(BMP280_I2C_ADDR
, BMP280_CTRL_MEAS_REG
, BMP280_MODE
);
153 static void bmp280_get_up(void)
155 uint8_t data
[BMP280_DATA_FRAME_SIZE
];
157 // read data from sensor
158 i2cRead(BMP280_I2C_ADDR
, BMP280_PRESSURE_MSB_REG
, BMP280_DATA_FRAME_SIZE
, data
);
159 bmp280_up
= (int32_t)((((uint32_t)(data
[0])) << 12) | (((uint32_t)(data
[1])) << 4) | ((uint32_t)data
[2] >> 4));
160 bmp280_ut
= (int32_t)((((uint32_t)(data
[3])) << 12) | (((uint32_t)(data
[4])) << 4) | ((uint32_t)data
[5] >> 4));
163 // Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
164 // t_fine carries fine temperature as global value
165 static int32_t bmp280_compensate_T(int32_t adc_T
)
167 int32_t var1
, var2
, T
;
169 var1
= ((((adc_T
>> 3) - ((int32_t)bmp280_cal
.dig_T1
<< 1))) * ((int32_t)bmp280_cal
.dig_T2
)) >> 11;
170 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;
171 bmp280_cal
.t_fine
= var1
+ var2
;
172 T
= (bmp280_cal
.t_fine
* 5 + 128) >> 8;
177 // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
178 // Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
179 static uint32_t bmp280_compensate_P(int32_t adc_P
)
181 int64_t var1
, var2
, p
;
182 var1
= ((int64_t)bmp280_cal
.t_fine
) - 128000;
183 var2
= var1
* var1
* (int64_t)bmp280_cal
.dig_P6
;
184 var2
= var2
+ ((var1
*(int64_t)bmp280_cal
.dig_P5
) << 17);
185 var2
= var2
+ (((int64_t)bmp280_cal
.dig_P4
) << 35);
186 var1
= ((var1
* var1
* (int64_t)bmp280_cal
.dig_P3
) >> 8) + ((var1
* (int64_t)bmp280_cal
.dig_P2
) << 12);
187 var1
= (((((int64_t)1) << 47) + var1
)) * ((int64_t)bmp280_cal
.dig_P1
) >> 33;
191 p
= (((p
<< 31) - var2
) * 3125) / var1
;
192 var1
= (((int64_t)bmp280_cal
.dig_P9
) * (p
>> 13) * (p
>> 13)) >> 25;
193 var2
= (((int64_t)bmp280_cal
.dig_P8
) * p
) >> 19;
194 p
= ((p
+ var1
+ var2
) >> 8) + (((int64_t)bmp280_cal
.dig_P7
) << 4);
198 STATIC_UNIT_TESTED
void bmp280_calculate(int32_t *pressure
, int32_t *temperature
)
203 t
= bmp280_compensate_T(bmp280_ut
);
204 p
= bmp280_compensate_P(bmp280_up
);
207 *pressure
= (int32_t)(p
/ 256);