|
|
|
@ -0,0 +1,477 @@
@@ -0,0 +1,477 @@
|
|
|
|
|
/*
|
|
|
|
|
* bme280.c |
|
|
|
|
* |
|
|
|
|
* Created on: Feb 26, 2023 |
|
|
|
|
* Author: Daniel Peter Chokola |
|
|
|
|
* License: Beerware - Use this code however you'd like. If you find it |
|
|
|
|
* useful you can buy me a beer some time. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/* Includes */ |
|
|
|
|
#include "bme280.h" |
|
|
|
|
#include "spi.h" |
|
|
|
|
#include "util.h" |
|
|
|
|
|
|
|
|
|
/* Definitions */ |
|
|
|
|
/* BME280 registers */ |
|
|
|
|
#define BME280_REG_HUM_LSB (0xfe) |
|
|
|
|
#define BME280_REG_HUM_MSB (0xfd) |
|
|
|
|
#define BME280_REG_TEMP_XLSB (0xfc) |
|
|
|
|
#define BME280_REG_TEMP_LSB (0xfb) |
|
|
|
|
#define BME280_REG_TEMP_MSB (0xfa) |
|
|
|
|
#define BME280_REG_PRESS_XLSB (0xf9) |
|
|
|
|
#define BME280_REG_PRESS_LSB (0xf8) |
|
|
|
|
#define BME280_REG_PRESS_MSB (0xf7) |
|
|
|
|
#define BME280_REG_CONFIG (0xf5) |
|
|
|
|
#define BME280_REG_CTRL_MEAS (0xf4) |
|
|
|
|
#define BME280_REG_STATUS (0xf3) |
|
|
|
|
#define BME280_REG_CTRL_HUM (0xf2) |
|
|
|
|
#define BME280_REG_RESET (0xe0) |
|
|
|
|
#define BME280_REG_ID (0xd0) /* should return 0x60 when read (BME280) */ |
|
|
|
|
#define BME280_REG_CALIB26 (0xe1) |
|
|
|
|
#define BME280_REG_CALIB25 (0xa1) |
|
|
|
|
#define BME280_REG_CALIB00 (0x88) |
|
|
|
|
/* BME280 SPI Register Masks */ |
|
|
|
|
#define BME280_READ_MASK (0x80) |
|
|
|
|
#define BME280_WRITE_MASK (0x7f) |
|
|
|
|
/* BME280 Magic Register Values */ |
|
|
|
|
#define BME280_RESET (0xb6) |
|
|
|
|
#define BME280_ID (0x60) |
|
|
|
|
#define BMP280_ID_PROD (0x58) |
|
|
|
|
#define BMP280_ID_SAMP1 (0x56) |
|
|
|
|
#define BMP280_ID_SAMP2 (0x57) |
|
|
|
|
|
|
|
|
|
enum H_OSR { |
|
|
|
|
H_OSR_00 = 0, /* skip */ |
|
|
|
|
H_OSR_01, |
|
|
|
|
H_OSR_02, |
|
|
|
|
H_OSR_04, |
|
|
|
|
H_OSR_08, |
|
|
|
|
H_OSR_16 |
|
|
|
|
}; |
|
|
|
|
enum P_OSR { |
|
|
|
|
P_OSR_00 = 0, /* skip */ |
|
|
|
|
P_OSR_01, |
|
|
|
|
P_OSR_02, |
|
|
|
|
P_OSR_04, |
|
|
|
|
P_OSR_08, |
|
|
|
|
P_OSR_16 |
|
|
|
|
}; |
|
|
|
|
enum T_OSR { |
|
|
|
|
T_OSR_00 = 0, /* skip */ |
|
|
|
|
T_OSR_01, |
|
|
|
|
T_OSR_02, |
|
|
|
|
T_OSR_04, |
|
|
|
|
T_OSR_08, |
|
|
|
|
T_OSR_16 |
|
|
|
|
}; |
|
|
|
|
enum IIR_COEFF { |
|
|
|
|
IIR_OFF = 0, /* no filtering */ |
|
|
|
|
IIR_02, |
|
|
|
|
IIR_04, |
|
|
|
|
IIR_08, |
|
|
|
|
IIR_16, |
|
|
|
|
}; |
|
|
|
|
enum MODE { |
|
|
|
|
MODE_SLEEP = 0, |
|
|
|
|
MODE_FORCED1, |
|
|
|
|
MODE_FORCED2, |
|
|
|
|
MODE_NORMAL |
|
|
|
|
}; |
|
|
|
|
enum STBY_TIME { |
|
|
|
|
STBY_00_5ms = 0, |
|
|
|
|
STBY_62_5ms, |
|
|
|
|
STBY_125ms, |
|
|
|
|
STBY_250ms, |
|
|
|
|
STBY_500ms, |
|
|
|
|
STBY_1000ms, |
|
|
|
|
STBY_10ms, /* 2000 ms on BMP280 */ |
|
|
|
|
STBY_20ms, /* 4000 ms on BMP280 */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/* Data Structures */ |
|
|
|
|
|
|
|
|
|
/* Function Prototypes */ |
|
|
|
|
static int32_t bme280_cal_get(bme280_t *bme280); |
|
|
|
|
static int32_t bme280_writebyte(bme280_t *bme280, uint8_t reg, uint8_t byte); |
|
|
|
|
static int32_t bme280_readbyte(bme280_t *bme280, uint8_t reg, uint8_t *byte); |
|
|
|
|
static int32_t bme280_compensate_t(bme280_t *bme280, int32_t t); |
|
|
|
|
static uint32_t bme280_compensate_p(bme280_t *bme280, int32_t p_comp); |
|
|
|
|
static uint32_t bme280_compensate_h(bme280_t *bme280, int32_t h); |
|
|
|
|
|
|
|
|
|
/* Function Definitions */ |
|
|
|
|
int32_t bme280_init(bme280_t *bme280, SPI_HandleTypeDef *hspi, GPIO_TypeDef *port, uint16_t pin) |
|
|
|
|
{ |
|
|
|
|
uint8_t id = 0; |
|
|
|
|
|
|
|
|
|
return_val_if_fail(bme280, -1); |
|
|
|
|
return_val_if_fail(hspi, -1); |
|
|
|
|
|
|
|
|
|
bme280->hspi = hspi; |
|
|
|
|
bme280->port = port; |
|
|
|
|
bme280->pin = pin; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* toggle CS line and send a dummy byte to to put the chip in SPI mode and |
|
|
|
|
* let the SPI lines settle */ |
|
|
|
|
return_val_if_fail(bme280_writebyte(bme280, BME280_REG_RESET, 0x00) == 0, -1); |
|
|
|
|
|
|
|
|
|
/* reset */ |
|
|
|
|
return_val_if_fail(bme280_writebyte(bme280, BME280_REG_RESET, BME280_RESET) == 0, -1); |
|
|
|
|
HAL_Delay(1); /* give the chip a millisecond to come out of reset */ |
|
|
|
|
|
|
|
|
|
/* query chip ID */ |
|
|
|
|
return_val_if_fail(bme280_readbyte(bme280, BME280_REG_ID, &id) == 0, -1); |
|
|
|
|
switch(id) |
|
|
|
|
{ |
|
|
|
|
case BME280_ID: |
|
|
|
|
/* BME280 */ |
|
|
|
|
break; |
|
|
|
|
case BMP280_ID_PROD: |
|
|
|
|
case BMP280_ID_SAMP1: |
|
|
|
|
case BMP280_ID_SAMP2: |
|
|
|
|
/* maybe support these one day */ |
|
|
|
|
default: |
|
|
|
|
return -1; /* not a BME280 */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* fetch calibration constants */ |
|
|
|
|
return_val_if_fail(bme280_cal_get(bme280) == 0, -1); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* FIXME: don't hardcode these |
|
|
|
|
* Maybe leave the chip in sleep mode here and create new function(s) to |
|
|
|
|
* adjust config? |
|
|
|
|
*/ |
|
|
|
|
/* configure humidity acquisition options */ |
|
|
|
|
return_val_if_fail(bme280_writebyte(bme280, BME280_REG_CTRL_HUM, H_OSR_01) == 0, -1); |
|
|
|
|
/* configure temperature and pressure acquisition options and acquisition mode */ |
|
|
|
|
return_val_if_fail(bme280_writebyte(bme280, |
|
|
|
|
BME280_REG_CTRL_MEAS, |
|
|
|
|
(T_OSR_01 << 5) | (P_OSR_16 << 2) | MODE_NORMAL) == 0, |
|
|
|
|
-1); |
|
|
|
|
/* configure acquisition rate, IIR filtering, and SPI options */ |
|
|
|
|
return_val_if_fail(bme280_writebyte(bme280, |
|
|
|
|
BME280_REG_CONFIG, |
|
|
|
|
(STBY_00_5ms << 5) | (IIR_16 << 2) | 0) == 0, |
|
|
|
|
-1); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int32_t bme280_temp_get(bme280_t *bme280) |
|
|
|
|
{ |
|
|
|
|
uint8_t reg; |
|
|
|
|
uint8_t rxdata[3]; |
|
|
|
|
int32_t t; |
|
|
|
|
HAL_StatusTypeDef res; |
|
|
|
|
|
|
|
|
|
/* read temperature; data must be read in one transaction to guarantee consistency */ |
|
|
|
|
reg = BME280_REG_TEMP_MSB; |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_Transmit(bme280->hspi, ®, 1, 10); |
|
|
|
|
res |= HAL_SPI_Receive(bme280->hspi, &(rxdata[0]), 3, 10); |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
|
|
|
|
|
/* assemble raw temperature */ |
|
|
|
|
t = ((int32_t) rxdata[0] << 12) | ((uint32_t) rxdata[1] << 4) | ((uint32_t) rxdata[2] >> 4); |
|
|
|
|
|
|
|
|
|
return bme280_compensate_t(bme280, t); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int32_t bme280_press_get(bme280_t *bme280) |
|
|
|
|
{ |
|
|
|
|
uint8_t reg; |
|
|
|
|
uint8_t rxdata[3]; |
|
|
|
|
int32_t p; |
|
|
|
|
HAL_StatusTypeDef res; |
|
|
|
|
|
|
|
|
|
/* read pressure; data must be read in one transaction to guarantee consistency */ |
|
|
|
|
reg = BME280_REG_PRESS_MSB; |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_Transmit(bme280->hspi, ®, 1, 10); |
|
|
|
|
res |= HAL_SPI_Receive(bme280->hspi, &(rxdata[0]), 3, 10); |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
|
|
|
|
|
/* assemble raw temperature */ |
|
|
|
|
p = ((int32_t) rxdata[0] << 12) | ((uint32_t) rxdata[1] << 4) | ((uint32_t) rxdata[2] >> 4); |
|
|
|
|
|
|
|
|
|
return bme280_compensate_p(bme280, p); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int32_t bme280_hum_get(bme280_t *bme280) |
|
|
|
|
{ |
|
|
|
|
uint8_t reg; |
|
|
|
|
uint8_t rxdata[2]; |
|
|
|
|
int32_t h; |
|
|
|
|
HAL_StatusTypeDef res; |
|
|
|
|
|
|
|
|
|
/* read pressure; data must be read in one transaction to guarantee consistency */ |
|
|
|
|
reg = BME280_REG_HUM_MSB; |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_Transmit(bme280->hspi, ®, 1, 10); |
|
|
|
|
res |= HAL_SPI_Receive(bme280->hspi, &(rxdata[0]), 2, 10); |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
|
|
|
|
|
/* assemble raw temperature */ |
|
|
|
|
h = ((int32_t) rxdata[0] << 8) | rxdata[1]; |
|
|
|
|
|
|
|
|
|
return bme280_compensate_h(bme280, h); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int32_t bme280_cal_get(bme280_t *bme280) |
|
|
|
|
{ |
|
|
|
|
uint8_t reg; |
|
|
|
|
uint8_t calh[7]; /* humidity cal which needs some massaging */ |
|
|
|
|
int32_t i; |
|
|
|
|
HAL_StatusTypeDef res; |
|
|
|
|
|
|
|
|
|
for(i = 0; i < BME280_CAL_LEN; i++) |
|
|
|
|
{ |
|
|
|
|
bme280->cal.byte[i] = 0; |
|
|
|
|
} |
|
|
|
|
reg = BME280_REG_CALIB00; |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_Transmit(bme280->hspi, ®, 1, 10); |
|
|
|
|
res |= HAL_SPI_Receive(bme280->hspi, &(bme280->cal.byte[ 0]), 24, 10); |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
reg = BME280_REG_CALIB25; |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_Transmit(bme280->hspi, ®, 1, 10); |
|
|
|
|
res |= HAL_SPI_Receive(bme280->hspi, &(bme280->cal.byte[24]), 1, 10); |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
reg = BME280_REG_CALIB26; |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_Transmit(bme280->hspi, ®, 1, 10); |
|
|
|
|
res |= HAL_SPI_Receive(bme280->hspi, &(calh[0]), 7, 10); |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
/* massage the humidity cal into its struct */ |
|
|
|
|
bme280->cal.field.cal_h2 = ((int16_t) calh[1] << 8) | calh[0]; |
|
|
|
|
bme280->cal.field.cal_h3 = calh[2]; |
|
|
|
|
bme280->cal.field.cal_h4 = ((int16_t) calh[3] << 4) | (calh[4] & 0x0f); |
|
|
|
|
bme280->cal.field.cal_h5 = ((int16_t) calh[5] << 4) | ((calh[4] >> 4) & 0x0f); |
|
|
|
|
bme280->cal.field.cal_h6 = (int8_t) calh[6]; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int32_t bme280_writebyte(bme280_t *bme280, uint8_t reg, uint8_t byte) |
|
|
|
|
{ |
|
|
|
|
uint8_t txdata[2] = { reg & BME280_WRITE_MASK, byte }; |
|
|
|
|
HAL_StatusTypeDef res; |
|
|
|
|
|
|
|
|
|
/* assert chip select */ |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_Transmit(bme280->hspi, &(txdata[0]), 2, 10); |
|
|
|
|
/* deassert chip select */ |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int32_t bme280_readbyte(bme280_t *bme280, uint8_t reg, uint8_t *byte) |
|
|
|
|
{ |
|
|
|
|
uint8_t txdata[2] = { reg | BME280_READ_MASK, 0x00 }; |
|
|
|
|
uint8_t rxdata[2]; |
|
|
|
|
HAL_StatusTypeDef res; |
|
|
|
|
|
|
|
|
|
/* assert chip select */ |
|
|
|
|
bme280->port->BSRR = bme280->pin << 16; |
|
|
|
|
res = HAL_SPI_TransmitReceive(bme280->hspi, &(txdata[0]), &(rxdata[0]), 2, 10); |
|
|
|
|
/* deassert chip select */ |
|
|
|
|
bme280->port->BSRR = bme280->pin; |
|
|
|
|
return_val_if_fail(res == HAL_OK, -1); |
|
|
|
|
*byte = rxdata[1]; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns temperature in DegC, resolution is 0.01 DegC. Output value of |
|
|
|
|
* "5123" equals 51.23 DegC. |
|
|
|
|
*/ |
|
|
|
|
static int32_t bme280_compensate_t(bme280_t *bme280, int32_t t) |
|
|
|
|
{ |
|
|
|
|
int32_t var1; |
|
|
|
|
int32_t var2; |
|
|
|
|
int32_t t_comp; |
|
|
|
|
|
|
|
|
|
var1 = ((((t >> 3) - ((int32_t) bme280->cal.field.cal_t1 << 1))) * ((int32_t) bme280->cal.field.cal_t2)) >> 11; |
|
|
|
|
var2 = (((((t >> 4) - ((int32_t) bme280->cal.field.cal_t1)) * ((t >> 4) - ((int32_t) bme280->cal.field.cal_t1))) >> 12) * ((int32_t) bme280->cal.field.cal_t3)) >> 14; |
|
|
|
|
bme280->t_fine = var1 + var2; |
|
|
|
|
t_comp = (bme280->t_fine * 5 + 128) >> 8; |
|
|
|
|
|
|
|
|
|
return t_comp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 |
|
|
|
|
* integer bits and 8 fractional bits). |
|
|
|
|
* Output value of "24674867" represents 24674867/256 = 96386.2 Pa = |
|
|
|
|
* 963.862 hPa |
|
|
|
|
*/ |
|
|
|
|
static uint32_t bme280_compensate_p(bme280_t *bme280, int32_t p) |
|
|
|
|
{ |
|
|
|
|
int64_t var1; |
|
|
|
|
int64_t var2; |
|
|
|
|
int64_t p_comp; |
|
|
|
|
|
|
|
|
|
var1 = ((int64_t) bme280->t_fine) - 128000; |
|
|
|
|
var2 = var1 * var1 * (int64_t) bme280->cal.field.cal_p6; |
|
|
|
|
var2 = var2 + ((var1 * (int64_t) bme280->cal.field.cal_p5) << 17); |
|
|
|
|
var2 = var2 + (((int64_t) bme280->cal.field.cal_p4) << 35); |
|
|
|
|
var1 = ((var1 * var1 * (int64_t) bme280->cal.field.cal_p3) >> 8) + ((var1 * (int64_t) bme280->cal.field.cal_p2) << 12); |
|
|
|
|
var1 = (((((int64_t) 1) << 47) + var1)) * ((int64_t) bme280->cal.field.cal_p1) >> 33; |
|
|
|
|
if(var1 == 0) |
|
|
|
|
{ |
|
|
|
|
/* division by zero */ |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
p_comp = 1048576 - p; |
|
|
|
|
p_comp = (((p_comp << 31) - var2) * 3125) / var1; |
|
|
|
|
var1 = (((int64_t) bme280->cal.field.cal_p9) * (p_comp >> 13) * (p_comp >> 13)) >> 25; |
|
|
|
|
var2 = (((int64_t) bme280->cal.field.cal_p8) * p_comp) >> 19; |
|
|
|
|
p_comp = ((p_comp + var1 + var2) >> 8) + (((int64_t) bme280->cal.field.cal_p7) << 4); |
|
|
|
|
|
|
|
|
|
return (uint32_t) p_comp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 |
|
|
|
|
* integer and 10 fractional bits). |
|
|
|
|
* Output value of “47445” represents 47445/1024 = 46.333 %RH |
|
|
|
|
*/ |
|
|
|
|
static uint32_t bme280_compensate_h(bme280_t *bme280, int32_t h) |
|
|
|
|
{ |
|
|
|
|
int32_t h_comp; |
|
|
|
|
|
|
|
|
|
h_comp = (bme280->t_fine - ((int32_t) 76800)); |
|
|
|
|
h_comp = (((((h << 14) - (((int32_t) bme280->cal.field.cal_h4) << 20) - (((int32_t) bme280->cal.field.cal_h5) * |
|
|
|
|
h_comp)) + ((int32_t) 16384)) >> 15) * (((((((h_comp * |
|
|
|
|
((int32_t) bme280->cal.field.cal_h6)) >> 10) * (((h_comp * ((int32_t) bme280->cal.field.cal_h3)) >> 11) + |
|
|
|
|
((int32_t) 32768))) >> 10) + ((int32_t) 2097152)) * ((int32_t) bme280->cal.field.cal_h2) + |
|
|
|
|
8192) >> 14)); |
|
|
|
|
h_comp = (h_comp - (((((h_comp >> 15) * (h_comp >> 15)) >> 7) * |
|
|
|
|
((int32_t) bme280->cal.field.cal_h1)) >> 4)); |
|
|
|
|
h_comp = (h_comp < 0 ? 0 : h_comp); |
|
|
|
|
h_comp = (h_comp > 419430400 ? 419430400 : h_comp); |
|
|
|
|
|
|
|
|
|
return (uint32_t) (h_comp >> 12); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (0) /* crusty old code */ |
|
|
|
|
/* Global Variables */ |
|
|
|
|
/* Specify BME280 configuration */ |
|
|
|
|
uint8_t Posr = P_OSR_16; |
|
|
|
|
uint8_t Tosr = T_OSR_02; |
|
|
|
|
uint8_t Mode = normal; |
|
|
|
|
uint8_t IIRFilter = BW0_042ODR; |
|
|
|
|
uint8_t SBy = t_62_5ms; // set pressure and temperature output data rate
|
|
|
|
|
/* t_fine carries fine temperature as global value for BME280 */ |
|
|
|
|
int32_t t_fine; |
|
|
|
|
/* BME280 compensation parameters */ |
|
|
|
|
uint16_t dig_T1, dig_P1; |
|
|
|
|
int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9; |
|
|
|
|
double Temperature, Pressure; // stores BME280 pressures sensor pressure and temperature
|
|
|
|
|
int32_t rawPress, rawTemp; // pressure and temperature raw count output for BME280
|
|
|
|
|
|
|
|
|
|
/* Function Definitions */ |
|
|
|
|
int32_t readBME280Temperature() |
|
|
|
|
{ |
|
|
|
|
uint8_t rawData[3]; // 20-bit pressure register data stored here
|
|
|
|
|
|
|
|
|
|
HAL_I2C_Mem_Read(&hi2c1, BME280_ADDRESS, BME280_TEMP_MSB, 3, &rawData[0], 3, 10); |
|
|
|
|
|
|
|
|
|
return (int32_t) (((int32_t) rawData[0] << 16 | (int32_t) rawData[1] << 8 | rawData[2]) >> 4); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int32_t readBME280Pressure() |
|
|
|
|
{ |
|
|
|
|
uint8_t rawData[3]; // 20-bit pressure register data stored here
|
|
|
|
|
|
|
|
|
|
HAL_I2C_Mem_Read(&hi2c1, BME280_ADDRESS, BME280_PRESS_MSB, 3, &rawData[0], 3, 10); |
|
|
|
|
|
|
|
|
|
return (int32_t) (((int32_t) rawData[0] << 16 | (int32_t) rawData[1] << 8 | rawData[2]) >> 4); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void BME280Init() |
|
|
|
|
{ |
|
|
|
|
uint8_t TPosrMode = Tosr << 5 | Posr << 2 | Mode; |
|
|
|
|
uint8_t SByTimeIntervalModeAndBandwidth = SBy << 5 | IIRFilter << 2; |
|
|
|
|
uint8_t calib[24]; |
|
|
|
|
|
|
|
|
|
/* Configure the BME280 */ |
|
|
|
|
/* Set T and P oversampling rates and sensor mode */ |
|
|
|
|
HAL_I2C_Mem_Write(&hi2c1, BME280_ADDRESS, BME280_CTRL_MEAS, 1, &TPosrMode, 1, 10); |
|
|
|
|
/* Set standby time interval in normal mode and bandwidth */ |
|
|
|
|
HAL_I2C_Mem_Write(&hi2c1, BME280_ADDRESS, BME280_CONFIG, 1, &SByTimeIntervalModeAndBandwidth, 1, 10); |
|
|
|
|
/* Read and store calibration data */ |
|
|
|
|
HAL_I2C_Mem_Read(&hi2c1, BME280_ADDRESS, BME280_CALIB00, 24, &calib[0], 24, 10); |
|
|
|
|
dig_T1 = (uint16_t) (((uint16_t) calib[ 1] << 8) | calib[ 0]); |
|
|
|
|
dig_T2 = ( int16_t) ((( int16_t) calib[ 3] << 8) | calib[ 2]); |
|
|
|
|
dig_T3 = ( int16_t) ((( int16_t) calib[ 5] << 8) | calib[ 4]); |
|
|
|
|
dig_P1 = (uint16_t) (((uint16_t) calib[ 7] << 8) | calib[ 6]); |
|
|
|
|
dig_P2 = ( int16_t) ((( int16_t) calib[ 9] << 8) | calib[ 8]); |
|
|
|
|
dig_P3 = ( int16_t) ((( int16_t) calib[11] << 8) | calib[10]); |
|
|
|
|
dig_P4 = ( int16_t) ((( int16_t) calib[13] << 8) | calib[12]); |
|
|
|
|
dig_P5 = ( int16_t) ((( int16_t) calib[15] << 8) | calib[14]); |
|
|
|
|
dig_P6 = ( int16_t) ((( int16_t) calib[17] << 8) | calib[16]); |
|
|
|
|
dig_P7 = ( int16_t) ((( int16_t) calib[19] << 8) | calib[18]); |
|
|
|
|
dig_P8 = ( int16_t) ((( int16_t) calib[21] << 8) | calib[20]); |
|
|
|
|
dig_P9 = ( int16_t) ((( int16_t) calib[23] << 8) | calib[22]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns temperature in DegC, resolution is 0.01 DegC. Output value of |
|
|
|
|
* "5123" equals 51.23 DegC. |
|
|
|
|
*/ |
|
|
|
|
int32_t bmp280_compensate_T(int32_t adc_T) |
|
|
|
|
{ |
|
|
|
|
int32_t var1, var2, T; |
|
|
|
|
|
|
|
|
|
var1 = ((((adc_T >> 3) - ((int32_t) dig_T1 << 1))) * ((int32_t) dig_T2)) >> 11; |
|
|
|
|
var2 = (((((adc_T >> 4) - ((int32_t) dig_T1)) * ((adc_T >> 4) - ((int32_t) dig_T1))) >> 12) * ((int32_t) dig_T3)) >> 14; |
|
|
|
|
t_fine = var1 + var2; |
|
|
|
|
T = (t_fine * 5 + 128) >> 8; |
|
|
|
|
|
|
|
|
|
return T; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 |
|
|
|
|
* integer bits and 8 fractional bits). |
|
|
|
|
* Output value of "24674867" represents 24674867/256 = 96386.2 Pa = |
|
|
|
|
* 963.862 hPa |
|
|
|
|
*/ |
|
|
|
|
uint32_t bmp280_compensate_P(int32_t adc_P) |
|
|
|
|
{ |
|
|
|
|
uint64_t var1, var2, p; |
|
|
|
|
|
|
|
|
|
var1 = ((uint64_t) t_fine) - 128000; |
|
|
|
|
var2 = var1 * var1 * (uint64_t) dig_P6; |
|
|
|
|
var2 = var2 + ((var1 * (uint64_t) dig_P5) << 17); |
|
|
|
|
var2 = var2 + (((uint64_t) dig_P4) << 35); |
|
|
|
|
var1 = ((var1 * var1 * (uint64_t) dig_P3) >> 8) + ((var1 * (uint64_t) dig_P2) << 12); |
|
|
|
|
var1 = (((((uint64_t) 1) << 47) + var1)) * ((uint64_t) dig_P1) >> 33; |
|
|
|
|
if(var1 == 0) |
|
|
|
|
{ |
|
|
|
|
/* division by zero */ |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
p = 1048576 - adc_P; |
|
|
|
|
p = (((p << 31) - var2) * 3125) / var1; |
|
|
|
|
var1 = (((uint64_t) dig_P9) * (p >> 13) * (p >> 13)) >> 25; |
|
|
|
|
var2 = (((uint64_t) dig_P8) * p)>> 19; |
|
|
|
|
p = ((p + var1 + var2) >> 8) + (((uint64_t) dig_P7) << 4); |
|
|
|
|
|
|
|
|
|
return (uint32_t) p; |
|
|
|
|
} |
|
|
|
|
#endif /* crusty old code */ |