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/build_config.h"
24 #include "common/utils.h"
26 #include "drivers/barometer/barometer.h"
28 #include "drivers/time.h"
29 #include "drivers/bus.h"
30 #include "drivers/nvic.h"
31 #include "drivers/io.h"
33 #include "drivers/barometer/barometer_bmp085.h"
35 #if defined(USE_BARO_BMP085)
37 #define BMP085_I2C_ADDR 0x77
38 #define BMP085_CHIP_ID 0x55
52 } bmp085_smd500_calibration_param_t
;
55 bmp085_smd500_calibration_param_t cal_param
;
57 int16_t oversampling_setting
;
60 #define BOSCH_PRESSURE_BMP085 85
61 #define BMP085_CHIP_ID_REG 0xD0
62 #define BMP085_VERSION_REG 0xD1
63 #define E_SENSOR_NOT_DETECTED (char) 0
64 #define BMP085_PROM_START__ADDR 0xaa
65 #define BMP085_PROM_DATA__LEN 22
66 #define BMP085_T_MEASURE 0x2E // temperature measurent
67 #define BMP085_P_MEASURE 0x34 // pressure measurement
68 #define BMP085_CTRL_MEAS_REG 0xF4
69 #define BMP085_ADC_OUT_MSB_REG 0xF6
70 #define BMP085_ADC_OUT_LSB_REG 0xF7
71 #define BMP085_CHIP_ID__POS 0
72 #define BMP085_CHIP_ID__MSK 0xFF
73 #define BMP085_CHIP_ID__LEN 8
74 #define BMP085_CHIP_ID__REG BMP085_CHIP_ID_REG
76 #define BMP085_ML_VERSION__POS 0
77 #define BMP085_ML_VERSION__LEN 4
78 #define BMP085_ML_VERSION__MSK 0x0F
79 #define BMP085_ML_VERSION__REG BMP085_VERSION_REG
81 #define BMP085_AL_VERSION__POS 4
82 #define BMP085_AL_VERSION__LEN 4
83 #define BMP085_AL_VERSION__MSK 0xF0
84 #define BMP085_AL_VERSION__REG BMP085_VERSION_REG
86 #define BMP085_GET_BITSLICE(regvar, bitname) ((regvar & bitname##__MSK) >> bitname##__POS)
87 #define BMP085_SET_BITSLICE(regvar, bitname, val) ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
89 #define SMD500_PARAM_MG 3038 //calibration parameter
90 #define SMD500_PARAM_MH -7357 //calibration parameter
91 #define SMD500_PARAM_MI 3791 //calibration parameter
93 STATIC_UNIT_TESTED bmp085_t bmp085
;
95 #define UT_DELAY 6000 // 1.5ms margin according to the spec (4.5ms T conversion time)
96 #define UP_DELAY 27000 // 6000+21000=27000 1.5ms margin according to the spec (25.5ms P conversion time with OSS=3)
98 STATIC_UNIT_TESTED
uint16_t bmp085_ut
; // static result of temperature measurement
99 STATIC_UNIT_TESTED
uint32_t bmp085_up
; // static result of pressure measurement
101 static void bmp085_get_cal_param(baroDev_t
*baro
)
103 uint8_t data
[BMP085_PROM_DATA__LEN
];
104 busReadBuf(baro
->busDev
, BMP085_PROM_START__ADDR
, data
, BMP085_PROM_DATA__LEN
);
106 /* parameters AC1-AC6 */
107 bmp085
.cal_param
.ac1
= (data
[0] << 8) | data
[1];
108 bmp085
.cal_param
.ac2
= (data
[2] << 8) | data
[3];
109 bmp085
.cal_param
.ac3
= (data
[4] << 8) | data
[5];
110 bmp085
.cal_param
.ac4
= (data
[6] << 8) | data
[7];
111 bmp085
.cal_param
.ac5
= (data
[8] << 8) | data
[9];
112 bmp085
.cal_param
.ac6
= (data
[10] << 8) | data
[11];
114 /* parameters B1,B2 */
115 bmp085
.cal_param
.b1
= (data
[12] << 8) | data
[13];
116 bmp085
.cal_param
.b2
= (data
[14] << 8) | data
[15];
118 /* parameters MB,MC,MD */
119 bmp085
.cal_param
.mb
= (data
[16] << 8) | data
[17];
120 bmp085
.cal_param
.mc
= (data
[18] << 8) | data
[19];
121 bmp085
.cal_param
.md
= (data
[20] << 8) | data
[21];
124 static int32_t bmp085_get_temperature(uint32_t ut
)
129 x1
= (((int32_t) ut
- (int32_t) bmp085
.cal_param
.ac6
) * (int32_t) bmp085
.cal_param
.ac5
) >> 15;
130 x2
= ((int32_t) bmp085
.cal_param
.mc
<< 11) / (x1
+ bmp085
.cal_param
.md
);
131 bmp085
.param_b5
= x1
+ x2
;
132 temperature
= ((bmp085
.param_b5
* 10 + 8) >> 4); // temperature in 0.01 C (make same as MS5611)
137 static int32_t bmp085_get_pressure(uint32_t up
)
139 int32_t pressure
, x1
, x2
, x3
, b3
, b6
;
142 b6
= bmp085
.param_b5
- 4000;
143 // *****calculate B3************
144 x1
= (b6
* b6
) >> 12;
145 x1
*= bmp085
.cal_param
.b2
;
148 x2
= (bmp085
.cal_param
.ac2
* b6
);
153 b3
= (((((int32_t) bmp085
.cal_param
.ac1
) * 4 + x3
) << bmp085
.oversampling_setting
) + 2) >> 2;
155 // *****calculate B4************
156 x1
= (bmp085
.cal_param
.ac3
* b6
) >> 13;
157 x2
= (bmp085
.cal_param
.b1
* ((b6
* b6
) >> 12)) >> 16;
158 x3
= ((x1
+ x2
) + 2) >> 2;
159 b4
= (bmp085
.cal_param
.ac4
* (uint32_t)(x3
+ 32768)) >> 15;
161 b7
= ((uint32_t)(up
- b3
) * (50000 >> bmp085
.oversampling_setting
));
162 if (b7
< 0x80000000) {
163 pressure
= (b7
<< 1) / b4
;
165 pressure
= (b7
/ b4
) << 1;
170 x1
= (x1
* SMD500_PARAM_MG
) >> 16;
171 x2
= (pressure
* SMD500_PARAM_MH
) >> 16;
172 pressure
+= (x1
+ x2
+ SMD500_PARAM_MI
) >> 4; // pressure in Pa
177 static bool bmp085_start_ut(baroDev_t
*baro
)
179 bool ack
= busWrite(baro
->busDev
, BMP085_CTRL_MEAS_REG
, BMP085_T_MEASURE
);
183 static bool bmp085_get_ut(baroDev_t
*baro
)
186 bool ack
= busReadBuf(baro
->busDev
, BMP085_ADC_OUT_MSB_REG
, data
, 2);
188 bmp085_ut
= (data
[0] << 8) | data
[1];
194 static bool bmp085_start_up(baroDev_t
*baro
)
196 uint8_t ctrl_reg_data
= BMP085_P_MEASURE
+ (bmp085
.oversampling_setting
<< 6);
197 bool ack
= busWrite(baro
->busDev
, BMP085_CTRL_MEAS_REG
, ctrl_reg_data
);
201 /** read out up for pressure conversion
202 depending on the oversampling ratio setting up can be 16 to 19 bit
203 \return up parameter that represents the uncompensated pressure value
205 static bool bmp085_get_up(baroDev_t
*baro
)
208 bool ack
= busReadBuf(baro
->busDev
, BMP085_ADC_OUT_MSB_REG
, data
, 3);
211 bmp085_up
= (((uint32_t) data
[0] << 16) | ((uint32_t) data
[1] << 8) | (uint32_t) data
[2]) >> (8 - bmp085
.oversampling_setting
);
217 STATIC_UNIT_TESTED
bool bmp085_calculate(baroDev_t
*baro
, int32_t *pressure
, int32_t *temperature
)
222 temp
= bmp085_get_temperature(bmp085_ut
);
223 press
= bmp085_get_pressure(bmp085_up
);
232 #define DETECTION_MAX_RETRY_COUNT 5
233 static bool deviceDetect(busDevice_t
* busDev
)
235 for (int retry
= 0; retry
< DETECTION_MAX_RETRY_COUNT
; retry
++) {
240 bool ack
= busRead(busDev
, BMP085_CHIP_ID__REG
, &chipId
);
241 if (ack
&& BMP085_GET_BITSLICE(chipId
, BMP085_CHIP_ID
) == BMP085_CHIP_ID
) {
249 bool bmp085Detect(baroDev_t
*baro
)
251 baro
->busDev
= busDeviceInit(BUSTYPE_ANY
, DEVHW_BMP085
, 0, OWNER_BARO
);
252 if (baro
->busDev
== NULL
) {
256 if (!deviceDetect(baro
->busDev
)) {
257 busDeviceDeInit(baro
->busDev
);
261 bmp085
.oversampling_setting
= 3;
262 bmp085_get_cal_param(baro
); /* readout bmp085 calibparam structure */
264 baro
->ut_delay
= UT_DELAY
;
265 baro
->start_ut
= bmp085_start_ut
;
266 baro
->get_ut
= bmp085_get_ut
;
268 baro
->up_delay
= UP_DELAY
;
269 baro
->start_up
= bmp085_start_up
;
270 baro
->get_up
= bmp085_get_up
;
272 baro
->calculate
= bmp085_calculate
;