Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
bmp280_i2c.c
Go to the documentation of this file.
1 /*
2  * Chris Efstathiou hendrixgr@gmail.com
3  * This file is part of paparazzi.
4  *
5  * paparazzi is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * paparazzi is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with paparazzi; see the file COPYING. If not, see
17  * <http://www.gnu.org/licenses/>.
18  */
19 
27 #include "peripherals/bmp280_i2c.h"
28 
32 static void parse_sensor_data(struct Bmp280_I2c *bmp);
33 static void parse_calib_data(struct Bmp280_I2c *bmp);
34 PRINT_CONFIG_MSG("BMP280 uses double precision compensation")
35 static double compensate_pressure(struct Bmp280_I2c *bmp);
36 static double compensate_temperature(struct Bmp280_I2c *bmp);
37 
39 
40 // init function
41 void bmp280_i2c_init(struct Bmp280_I2c *bmp, struct i2c_periph *i2c_p, uint8_t addr)
42 {
43  // set i2c_peripheral
44  bmp->i2c_p = i2c_p;
45 
46  // slave address
47  bmp->i2c_trans.slave_addr = addr;
48  // set initial status: Done
49  bmp->i2c_trans.status = I2CTransDone;
50 
51  bmp->data_available = false;
52  bmp->initialized = false;
53  bmp->status = BMP280_STATUS_UNINIT;
54 }
55 
56 // Start new measurement if sensor ready
58 {
59  if (bmp->i2c_trans.status != I2CTransDone) {
60  return; // transaction not finished
61  }
62 
63  switch (bmp->status) {
65  bmp->data_available = false;
66  bmp->initialized = false;
68  break;
69 
71  // request calibration data
74  break;
75 
77  // From datasheet, recommended config for drone usecase:
78  // osrs_p = 8, osrs_t = 1
79  // IIR filter = 2 (note: this one doesn't exist...)
85  break;
86 
88  // READ THE STATUS BYTE
90  i2c_transceive(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 1, 1);
91  break;
92 
94  // READ ALL 6 DATA REGISTERS
97  break;
98 
99  default:
100  break;
101  }
102 }
103 
104 void bmp280_i2c_event(struct Bmp280_I2c *bmp)
105 {
106  if (bmp->i2c_trans.status == I2CTransSuccess) {
107  switch (bmp->status) {
108 
110  // compute calib
111  parse_calib_data(bmp);
113  break;
114 
116  // nothing else to do, start reading
118  bmp->initialized = true;
119  break;
120 
122  // check status byte
123  if ((bmp->i2c_trans.buf[0] & (BMP280_EOC_BIT | BMP280_NVRAM_COPY_BIT)) == 0) {
125  }
126  break;
127 
129  // parse sensor data, compensate temperature first, then pressure
130  parse_sensor_data(bmp);
132  compensate_pressure(bmp);
133  bmp->data_available = true;
135  break;
136 
137  default:
138  bmp->status = BMP280_STATUS_GET_CALIB; // just to avoid the compiler's warning message
139  break;
140  }
142  } else if (bmp->i2c_trans.status == I2CTransFailed) {
143  /* try again */
144  if (!bmp->initialized) {
146  }
148  }
149 
150  return;
151 }
152 
153 static void parse_sensor_data(struct Bmp280_I2c *bmp)
154 {
155  /* Temporary variables to store the sensor data */
156  uint32_t data_xlsb;
157  uint32_t data_lsb;
158  uint32_t data_msb;
159 
160  // BMP280 HAS THE 6 DATA REGISTERS START AT F7 AND GOING UP TO FC MSB FIRST THEN LSB AND LAST THE XLSB BYTE.
161  // THE FIRST THREE BYTES ARE THE PRESSURE AND THE NEXT 3 THE TEMPERATURE.
162  /* Store the parsed register values for pressure data */
163  data_msb = (uint32_t)bmp->i2c_trans.buf[0] << 16;
164  data_lsb = (uint32_t)bmp->i2c_trans.buf[1] << 8;
165  data_xlsb = (uint32_t)bmp->i2c_trans.buf[2];
166  bmp->raw_pressure = (int32_t)((data_msb | data_lsb | data_xlsb) >> 4);
167 
168  /* Store the parsed register values for temperature data */
169  data_msb = (uint32_t)bmp->i2c_trans.buf[3] << 16;
170  data_lsb = (uint32_t)bmp->i2c_trans.buf[4] << 8;
171  data_xlsb = (uint32_t)bmp->i2c_trans.buf[5];
172  bmp->raw_temperature = (int32_t)((data_msb | data_lsb | data_xlsb) >> 4);
173 }
174 
175 
180 static void parse_calib_data(struct Bmp280_I2c *bmp)
181 {
182  uint8_t *data = (uint8_t *)bmp->i2c_trans.buf; // we know that this buffer will not be modified during this call
183 
184  bmp->calib.dig_t1 = BMP280_CONCAT_BYTES(data[1], data[0]);
185  bmp->calib.dig_t2 = (int16_t)BMP280_CONCAT_BYTES(data[3], data[2]);
186  bmp->calib.dig_t3 = (int16_t)BMP280_CONCAT_BYTES(data[5], data[4]);
187 
188  bmp->calib.dig_p1 = BMP280_CONCAT_BYTES(data[7], data[6]);
189  bmp->calib.dig_p2 = (int16_t)BMP280_CONCAT_BYTES(data[9], data[8]);
190  bmp->calib.dig_p3 = (int16_t)BMP280_CONCAT_BYTES(data[11], data[10]);
191  bmp->calib.dig_p4 = (int16_t)BMP280_CONCAT_BYTES(data[13], data[12]);
192  bmp->calib.dig_p5 = (int16_t)BMP280_CONCAT_BYTES(data[15], data[14]);
193  bmp->calib.dig_p6 = (int16_t)BMP280_CONCAT_BYTES(data[17], data[16]);
194  bmp->calib.dig_p7 = (int16_t)BMP280_CONCAT_BYTES(data[19], data[18]);
195  bmp->calib.dig_p8 = (int16_t)BMP280_CONCAT_BYTES(data[21], data[20]);
196  bmp->calib.dig_p9 = (int16_t)BMP280_CONCAT_BYTES(data[23], data[22]);
197 
198  return;
199 }
200 
205 static double compensate_temperature(struct Bmp280_I2c *bmp)
206 {
207 
208  double var1;
209  double var2;
210 
211  var1 = (((double)bmp->raw_temperature / 16384.0) - ((double)bmp->calib.dig_t1 / 1024.0)) * ((double)bmp->calib.dig_t2);
212  var2 = ((double)bmp->raw_temperature / 131072.0) - ((double)bmp->calib.dig_t1 / 8192.0);
213  var2 = (var2 * var2) * (double)bmp->calib.dig_t3;
214  t_fine = (int64_t)(var1 + var2);
215 
216  /* Store t_lin in dev. structure for pressure calculation */
217  bmp->calib.t_fine = t_fine;
218  /* Store compensated temperature in float in structure */
219  bmp->temperature = (((var1 + var2) / 5120.f) * 100);
220 
221  return (double)bmp->temperature;
222 }
223 
228 static double compensate_pressure(struct Bmp280_I2c *bmp)
229 {
230  double var1;
231  double var2;
232  double p;
233 
234  var1 = ((double)t_fine / 2) - 64000.0;
235  var2 = (var1 * var1 * (double)bmp->calib.dig_p5) / 32768.0;
236  var2 = var2 + (var1 * (double)bmp->calib.dig_p5 * 2.0);
237  var2 = (var2 / 4.0) + ((double)bmp->calib.dig_p4 * 65536.0);
238  var1 = (((double)bmp->calib.dig_p3 * var1 * (var1 / 524288.0)) + ((double)bmp->calib.dig_p2 * var1)) / 524288.0;
239  var1 = (1 + (var1 / 32768.0)) * (double)bmp->calib.dig_p1;
240  p = 1048576.0 - (double)bmp->raw_pressure;
241  p = (p - (var2 / 4096.0)) * (6250.0 / var1);
242  var1 = ((double)bmp->calib.dig_p9 * p) * (p / 2147483648.0);
243  var2 = (p * ((double)bmp->calib.dig_p8)) / 32768.0;
244  p = p + ((var1 + var2 + (double)bmp->calib.dig_p7) / 16.0);
245  bmp->pressure = p;
246 
247  return (p);
248 }
bmp280_i2c_init
void bmp280_i2c_init(struct Bmp280_I2c *bmp, struct i2c_periph *i2c_p, uint8_t addr)
Definition: bmp280_i2c.c:41
BMP280_STATUS_READ_STATUS_REG
@ BMP280_STATUS_READ_STATUS_REG
Definition: bmp280_regs.h:152
i2c_transaction::buf
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition: i2c.h:122
BMP280_STATUS_GET_CALIB
@ BMP280_STATUS_GET_CALIB
Definition: bmp280_regs.h:150
Bmp280_I2c::status
enum Bmp280Status status
state machine status
Definition: bmp280_i2c.h:38
compensate_temperature
static double compensate_temperature(struct Bmp280_I2c *bmp)
This internal API is used to compensate the raw temperature data and return the compensated temperatu...
Definition: bmp280_i2c.c:205
Bmp280_I2c::data_available
volatile bool data_available
data ready flag
Definition: bmp280_i2c.h:40
BMP280_CTRL_MEAS_REG_ADDR
#define BMP280_CTRL_MEAS_REG_ADDR
Definition: bmp280_regs.h:71
Bmp280_I2c::i2c_p
struct i2c_periph * i2c_p
Definition: bmp280_i2c.h:36
BMP280_OVERSAMPLING_1X_T
#define BMP280_OVERSAMPLING_1X_T
Definition: bmp280_regs.h:90
bmp280_reg_calib_data::dig_p6
int16_t dig_p6
Definition: bmp280_regs.h:166
I2CTransFailed
@ I2CTransFailed
transaction failed
Definition: i2c.h:58
BMP280_STATUS_READ_DATA_REGS
@ BMP280_STATUS_READ_DATA_REGS
Definition: bmp280_regs.h:153
uint32_t
unsigned long uint32_t
Definition: types.h:18
int64_t
signed long long int64_t
Definition: types.h:21
BMP280_EOC_BIT
#define BMP280_EOC_BIT
Definition: bmp280_regs.h:85
bmp280_reg_calib_data::dig_p8
int16_t dig_p8
Definition: bmp280_regs.h:168
BMP280_INACTIVITY_62_5_MS
#define BMP280_INACTIVITY_62_5_MS
Definition: bmp280_regs.h:109
bmp280_i2c_event
void bmp280_i2c_event(struct Bmp280_I2c *bmp)
Definition: bmp280_i2c.c:104
BMP280_NVRAM_COPY_BIT
#define BMP280_NVRAM_COPY_BIT
Definition: bmp280_regs.h:86
I2CTransSuccess
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition: i2c.h:57
BMP280_POWER_NORMAL_MODE
#define BMP280_POWER_NORMAL_MODE
Definition: bmp280_regs.h:105
i2c_transmit
bool i2c_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction.
Definition: i2c.c:324
Bmp280_I2c::raw_pressure
uint32_t raw_pressure
uncompensated pressure
Definition: bmp280_i2c.h:42
bmp280_reg_calib_data::dig_p1
uint16_t dig_p1
Definition: bmp280_regs.h:161
parse_calib_data
static void parse_calib_data(struct Bmp280_I2c *bmp)
This internal API is used to parse the calibration data, compensates it and store it in device struct...
Definition: bmp280_i2c.c:180
Bmp280_I2c::initialized
bool initialized
config done flag
Definition: bmp280_i2c.h:39
BMP280_STATUS_UNINIT
@ BMP280_STATUS_UNINIT
Definition: bmp280_regs.h:149
i2c_transceive
bool i2c_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction.
Definition: i2c.c:344
int16_t
signed short int16_t
Definition: types.h:17
bmp280_reg_calib_data::dig_p4
int16_t dig_p4
Definition: bmp280_regs.h:164
uint8_t
unsigned char uint8_t
Definition: types.h:14
BMP280_STATUS_CONFIGURE
@ BMP280_STATUS_CONFIGURE
Definition: bmp280_regs.h:151
bmp280_reg_calib_data::t_fine
int32_t t_fine
Definition: bmp280_regs.h:170
Bmp280_I2c::i2c_trans
struct i2c_transaction i2c_trans
Definition: bmp280_i2c.h:37
i2c_transaction::status
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
BMP280_CONCAT_BYTES
#define BMP280_CONCAT_BYTES(msb, lsb)
Definition: bmp280_regs.h:139
bmp280_reg_calib_data::dig_t3
int16_t dig_t3
Definition: bmp280_regs.h:160
bmp280_reg_calib_data::dig_p2
int16_t dig_p2
Definition: bmp280_regs.h:162
Bmp280_I2c::temperature
float temperature
temperature in deg Celcius
Definition: bmp280_i2c.h:45
f
uint16_t f
Camera baseline, in meters (i.e. horizontal distance between the two cameras of the stereo setup)
Definition: wedgebug.c:204
i2c_transaction::slave_addr
uint8_t slave_addr
Slave address.
Definition: i2c.h:104
bmp280_reg_calib_data::dig_t1
uint16_t dig_t1
Definition: bmp280_regs.h:158
t_fine
int64_t t_fine
Definition: bmp280_i2c.c:38
Bmp280_I2c::calib
struct bmp280_reg_calib_data calib
calibration data
Definition: bmp280_i2c.h:41
PRINT_CONFIG_MSG
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
bmp280_reg_calib_data::dig_p3
int16_t dig_p3
Definition: bmp280_regs.h:163
BMP280_DATA_START_REG_ADDR
#define BMP280_DATA_START_REG_ADDR
Definition: bmp280_regs.h:63
bmp280_reg_calib_data::dig_t2
int16_t dig_t2
Definition: bmp280_regs.h:159
Bmp280_I2c::raw_temperature
uint32_t raw_temperature
uncompensated temperature
Definition: bmp280_i2c.h:43
BMP280_OVERSAMPLING_8X_P
#define BMP280_OVERSAMPLING_8X_P
Definition: bmp280_regs.h:100
BMP280_CONFIG_LEN
#define BMP280_CONFIG_LEN
Definition: bmp280_regs.h:62
int32_t
signed long int32_t
Definition: types.h:19
BMP280_STATUS_REG_ADDR
#define BMP280_STATUS_REG_ADDR
Definition: bmp280_regs.h:70
parse_sensor_data
static void parse_sensor_data(struct Bmp280_I2c *bmp)
local function to extract raw data from i2c buffer and compute compensation with selected precision
Definition: bmp280_i2c.c:153
bmp280_reg_calib_data::dig_p7
int16_t dig_p7
Definition: bmp280_regs.h:167
I2CTransDone
@ I2CTransDone
transaction set to done by user level
Definition: i2c.h:59
Bmp280_I2c
Definition: bmp280_i2c.h:35
bmp280_i2c.h
Sensor driver for BMP280 sensor via I2C.
bmp280_reg_calib_data::dig_p5
int16_t dig_p5
Definition: bmp280_regs.h:165
bmp280_reg_calib_data::dig_p9
int16_t dig_p9
Definition: bmp280_regs.h:169
bmp280_i2c_periodic
void bmp280_i2c_periodic(struct Bmp280_I2c *bmp)
Definition: bmp280_i2c.c:57
i2c_periph
Definition: i2c.h:144
BMP280_CALIB_LSB_DATA_ADDR
#define BMP280_CALIB_LSB_DATA_ADDR
Definition: bmp280_regs.h:44
BMP280_P_T_DATA_LEN
#define BMP280_P_T_DATA_LEN
Definition: bmp280_regs.h:64
p
static float p[2][2]
Definition: ins_alt_float.c:268
BMP280_IIR_FILTER_COEFF_2
#define BMP280_IIR_FILTER_COEFF_2
Definition: bmp280_regs.h:118
BMP280_CONFIG_REG_ADDR
#define BMP280_CONFIG_REG_ADDR
Definition: bmp280_regs.h:72
BMP280_CALIB_DATA_LEN
#define BMP280_CALIB_DATA_LEN
Definition: bmp280_regs.h:45
Bmp280_I2c::pressure
float pressure
pressure in Pascal
Definition: bmp280_i2c.h:44
compensate_pressure
static double compensate_pressure(struct Bmp280_I2c *bmp)
This internal API is used to compensate the raw pressure data and return the compensated pressure dat...
Definition: bmp280_i2c.c:228