Updated BME280.

This commit is contained in:
imi415 2022-07-22 21:51:23 +08:00
parent b726d03136
commit 238b4a2c80
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
2 changed files with 163 additions and 58 deletions

View File

@ -63,26 +63,36 @@ typedef struct {
ims_bme280_fiter_config_t filter;
} ims_bme280_config_t;
/* Result is multiplied by 10000. */
typedef struct {
int32_t temperature;
uint32_t pressure;
int32_t humidity;
} ims_bme280_result_int32_t;
typedef struct {
double temperature;
double pressure;
double humidity;
} ims_bme280_result_t;
} ims_bme280_result_float_t;
typedef struct {
ims_i2c_xfer_t i2c_xfer;
ims_delay_t delay;
} ims_bme280_cb_t;
typedef struct {
void *user_data;
ims_bme280_trim_t trim;
ims_bme280_cb_t cb;
uint8_t i2c_addr;
int32_t t_fine;
} ims_bme280_t;
ims_ret_t ims_bme280_init(ims_bme280_t *bme);
ims_ret_t ims_bme280_preset_config(ims_bme280_config_t *config, ims_bme280_mode_preset_t preset);
ims_ret_t ims_bme280_apply_config(ims_bme280_t *bme, ims_bme280_config_t *config);
ims_ret_t ims_bme280_measure(ims_bme280_t *bme, ims_bme280_result_t *result);
ims_ret_t ims_bme280_measure_int32(ims_bme280_t *bme, ims_bme280_result_int32_t *result);
ims_ret_t ims_bme280_measure_float(ims_bme280_t *bme, ims_bme280_result_float_t *result);
#endif

View File

@ -2,112 +2,153 @@
#include <string.h>
#ifdef IMS_CFG_DHT_BME280_ENABLE_FLOAT
#define ims_bme280_compensate_T ims_bme280_compensate_T_double
#define ims_bme280_compensate_P ims_bme280_compensate_P_double
#define ims_bme280_compensate_H ims_bme280_compensate_H_double
#else
#define ims_bme280_compensate_T ims_bme280_compensate_T_int32
#define ims_bme280_compensate_P ims_bme280_compensate_P_int32
#define ims_bme280_compensate_H ims_bme280_compensate_H_int32
#endif
#define IMS_BME280_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb)
#ifdef IMS_CFG_DHT_BME280_ENABLE_FLOAT
static double ims_bme280_compensate_T_double(ims_bme280_t *bme, int32_t adc_T);
static double ims_bme280_compensate_P_double(ims_bme280_t *bme, int32_t adc_P);
static double ims_bme280_compensate_H_double(ims_bme280_t *bme, int32_t adc_H);
#else
static int32_t ims_bme280_compensate_T_int32(ims_bme280_t *bme, int32_t adc_T);
static uint32_t ims_bme280_compensate_P_int64(ims_bme280_t *bme, int32_t adc_P);
static uint32_t ims_bme280_compensate_H_int32(ims_bme280_t *bme, int32_t adc_H);
#endif
static ims_ret_t ims_bme280_read_register(ims_bme280_t *bme, uint8_t reg, uint8_t *data, uint16_t len) {
ims_i2c_xfer_desc_t xfer_desc = {
.tx_size = 1U,
.tx_data = &reg,
.rx_size = len,
.rx_data = data,
};
return bme->cb.i2c_xfer(bme->user_data, bme->i2c_addr, &xfer_desc);
}
static ims_ret_t ims_bme280_write_register(ims_bme280_t *bme, uint8_t reg, uint8_t data) {
uint8_t tx_buf[2] = {reg, data};
ims_i2c_xfer_desc_t xfer_desc = {
.tx_size = 2U,
.tx_data = tx_buf,
.rx_size = 0U,
.rx_data = NULL,
};
return bme->cb.i2c_xfer(bme->user_data, bme->i2c_addr, &xfer_desc);
}
static ims_ret_t ims_bme280_reset(ims_bme280_t *bme) {
return bme->cb.write_register_cb(bme->user_data, 0xE0, 0xB6);
return ims_bme280_write_register(bme, 0xE0, 0xB6);
}
static ims_ret_t ims_bme280_read_trim_data(ims_bme280_t *bme) {
ims_ret_t ret;
uint8_t rx_buf[2];
ret = bme->cb.read_register_cb(bme->user_data, 0x88, rx_buf, 0x02); // T1
ret = ims_bme280_read_register(bme, 0x88, rx_buf, 0x02); // T1
if (ret == IMS_FAIL) return ret;
bme->trim.dig_T1 = IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x8A, rx_buf, 0x02); // T2
ret = ims_bme280_read_register(bme, 0x8A, rx_buf, 0x02); // T2
if (ret == IMS_FAIL) return ret;
bme->trim.dig_T2 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x8C, rx_buf, 0x02); // T3
ret = ims_bme280_read_register(bme, 0x8C, rx_buf, 0x02); // T3
if (ret == IMS_FAIL) return ret;
bme->trim.dig_T3 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x8E, rx_buf, 0x02); // P1
ret = ims_bme280_read_register(bme, 0x8E, rx_buf, 0x02); // P1
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P1 = IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x90, rx_buf, 0x02); // P2
ret = ims_bme280_read_register(bme, 0x90, rx_buf, 0x02); // P2
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P2 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x92, rx_buf, 0x02); // P3
ret = ims_bme280_read_register(bme, 0x92, rx_buf, 0x02); // P3
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P3 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x94, rx_buf, 0x02); // P4
ret = ims_bme280_read_register(bme, 0x94, rx_buf, 0x02); // P4
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P4 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x96, rx_buf, 0x02); // P5
ret = ims_bme280_read_register(bme, 0x96, rx_buf, 0x02); // P5
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P5 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x98, rx_buf, 0x02); // P5
ret = ims_bme280_read_register(bme, 0x98, rx_buf, 0x02); // P5
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P6 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x9A, rx_buf, 0x02); // P7
ret = ims_bme280_read_register(bme, 0x9A, rx_buf, 0x02); // P7
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P7 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x9C, rx_buf, 0x02); // P8
ret = ims_bme280_read_register(bme, 0x9C, rx_buf, 0x02); // P8
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P8 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0x9E, rx_buf, 0x02); // P9
ret = ims_bme280_read_register(bme, 0x9E, rx_buf, 0x02); // P9
if (ret == IMS_FAIL) return ret;
bme->trim.dig_P9 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0xA1, rx_buf, 0x01); // H1
ret = ims_bme280_read_register(bme, 0xA1, rx_buf, 0x01); // H1
if (ret == IMS_FAIL) return ret;
bme->trim.dig_H1 = rx_buf[0];
ret = bme->cb.read_register_cb(bme->user_data, 0xE1, rx_buf, 0x02); // H2
ret = ims_bme280_read_register(bme, 0xE1, rx_buf, 0x02); // H2
if (ret == IMS_FAIL) return ret;
bme->trim.dig_H2 = (int16_t)IMS_BME280_CONCAT_BYTES(rx_buf[1], rx_buf[0]);
ret = bme->cb.read_register_cb(bme->user_data, 0xE3, rx_buf, 0x01); // H3
ret = ims_bme280_read_register(bme, 0xE3, rx_buf, 0x01); // H3
if (ret == IMS_FAIL) return ret;
bme->trim.dig_H3 = (uint8_t)rx_buf[0];
ret = bme->cb.read_register_cb(bme->user_data, 0xE4, rx_buf, 0x02); // H4
ret = ims_bme280_read_register(bme, 0xE4, rx_buf, 0x02); // H4
if (ret == IMS_FAIL) return ret;
bme->trim.dig_H4 = (int16_t)(((int8_t)rx_buf[0] << 0x04) | (rx_buf[1] & 0x0F));
ret = bme->cb.read_register_cb(bme->user_data, 0xE5, rx_buf, 0x02); // H5
ret = ims_bme280_read_register(bme, 0xE5, rx_buf, 0x02); // H5
if (ret == IMS_FAIL) return ret;
bme->trim.dig_H5 = (int16_t)(((int8_t)rx_buf[1] << 0x04) | (rx_buf[0] >> 0x04));
ret = bme->cb.read_register_cb(bme->user_data, 0xE7, rx_buf, 0x01); // H6
ret = ims_bme280_read_register(bme, 0xE7, rx_buf, 0x01); // H6
if (ret == IMS_FAIL) return ret;
bme->trim.dig_H6 = (int8_t)rx_buf[0];
return IMS_SUCCESS;
}
static ims_ret_t ims_bme280_measure_raw(ims_bme280_t *bme, uint32_t *raw_t, uint32_t *raw_p, uint32_t *raw_h) {
uint8_t measure_data[8];
uint8_t status = 0;
uint8_t ctrl_meas;
uint8_t loop_count = 0;
if (ims_bme280_read_register(bme, 0xF4, &ctrl_meas, 0x01) != IMS_SUCCESS) return IMS_FAIL;
ims_bme280_write_register(bme, 0xF4, ctrl_meas | IMS_BME280_MODE_FORCED);
do {
if (ims_bme280_read_register(bme, 0xF3, &status, 0x01) != IMS_SUCCESS) return IMS_FAIL;
loop_count++;
bme->cb.delay(bme->user_data, 100);
} while (status & 0x08 && (loop_count < 12));
if (ims_bme280_read_register(bme, 0xF7, measure_data, 0x08) != IMS_SUCCESS) return IMS_FAIL;
*raw_p =
((uint32_t)measure_data[0] << 12) | ((uint32_t)measure_data[1] << 0x04) | ((uint32_t)measure_data[2] >> 0x04);
*raw_t =
((uint32_t)measure_data[3] << 12) | ((uint32_t)measure_data[4] << 0x04) | ((uint32_t)measure_data[5] >> 0x04);
*raw_h = ((uint32_t)measure_data[6] << 8) | ((uint32_t)measure_data[7]);
}
ims_ret_t bme280_init(ims_bme280_t *bme) {
if (!bme) return IMS_FAIL;
if (ims_bme280_reset(bme) == IMS_FAIL) return IMS_FAIL;
bme->cb.delay_cb(bme->user_data, 100);
bme->cb.delay(bme->user_data, 100);
if (ims_bme280_read_trim_data(bme) == IMS_FAIL) return IMS_FAIL;
return IMS_SUCCESS;
}
ims_ret_t bme280_preset_config(ims_bme280_config_t *config, ims_bme280_mode_preset_t preset) {
ims_ret_t ims_bme280_preset_config(ims_bme280_config_t *config, ims_bme280_mode_preset_t preset) {
switch (preset) {
case IMS_BME280_PRESET_WEATHER:
config->mode = IMS_BME280_MODE_FORCED;
@ -141,42 +182,30 @@ ims_ret_t bme280_preset_config(ims_bme280_config_t *config, ims_bme280_mode_pres
return IMS_SUCCESS;
}
ims_ret_t bme280_apply_config(ims_bme280_t *bme, ims_bme280_config_t *config) {
ims_ret_t ims_bme280_apply_config(ims_bme280_t *bme, ims_bme280_config_t *config) {
uint8_t reg_config = config->filter << 0x02;
uint8_t reg_ctrl_measure = (uint8_t)((config->osrs_t << 0x05) | (config->osrs_p << 0x02) | config->mode);
uint8_t reg_ctrl_hum = config->osrs_h;
bme->cb.write_register_cb(bme->user_data, 0xF5, reg_config);
bme->cb.write_register_cb(bme->user_data, 0xF2, reg_ctrl_hum);
bme->cb.write_register_cb(bme->user_data, 0xF4, reg_ctrl_measure);
ims_bme280_write_register(bme, 0xF5, reg_config);
ims_bme280_write_register(bme, 0xF2, reg_ctrl_hum);
ims_bme280_write_register(bme, 0xF4, reg_ctrl_measure);
return IMS_SUCCESS;
}
ims_ret_t bme280_measure(ims_bme280_t *bme, ims_bme280_result_t *result) {
#ifdef IMS_CFG_DHT_BME280_ENABLE_FLOAT
ims_ret_t ims_bme280_measure_float(ims_bme280_t *bme, ims_bme280_result_float_t *result) {
uint32_t raw_P = 0x00;
uint32_t raw_T = 0x00;
uint32_t raw_H = 0x00;
uint8_t measure_data[8];
uint8_t status = 0;
uint8_t ctrl_meas;
uint8_t loop_count = 0;
if (bme->cb.read_register_cb(bme->user_data, 0xF4, &ctrl_meas, 0x01) != IMS_SUCCESS) return IMS_FAIL;
bme->cb.write_register_cb(bme->user_data, 0xF4, ctrl_meas | IMS_BME280_MODE_FORCED);
do {
if (bme->cb.read_register_cb(bme->user_data, 0xF3, &status, 0x01) != IMS_SUCCESS) return IMS_FAIL;
loop_count++;
bme->cb.delay_cb(bme->user_data, 100);
} while (status & 0x08 && (loop_count < 12));
if (ims_bme280_measure_raw(bme, &raw_T, &raw_P, &raw_H) != IMS_SUCCESS) {
return IMS_FAIL;
}
if (bme->cb.read_register_cb(bme->user_data, 0xF7, measure_data, 0x08) != IMS_SUCCESS) return IMS_FAIL;
raw_P =
((uint32_t)measure_data[0] << 12) | ((uint32_t)measure_data[1] << 0x04) | ((uint32_t)measure_data[2] >> 0x04);
raw_T =
((uint32_t)measure_data[3] << 12) | ((uint32_t)measure_data[4] << 0x04) | ((uint32_t)measure_data[5] >> 0x04);
raw_H = ((uint32_t)measure_data[6] << 8) | ((uint32_t)measure_data[7]);
result->temperature = ims_bme280_compensate_T(bme, raw_T);
result->pressure = ims_bme280_compensate_P(bme, raw_P);
result->humidity = ims_bme280_compensate_H(bme, raw_H);
result->temperature = ims_bme280_compensate_T_double(bme, raw_T);
result->pressure = ims_bme280_compensate_P_double(bme, raw_P);
result->humidity = ims_bme280_compensate_H_double(bme, raw_H);
return IMS_SUCCESS;
}
@ -224,3 +253,69 @@ static double ims_bme280_compensate_H_double(ims_bme280_t *bme, int32_t adc_H) {
var_H = 0.0;
return var_H;
}
#else
ims_ret_t ims_bme280_measure_int32(ims_bme280_t *bme, ims_bme280_result_int32_t *result) {
uint32_t raw_P = 0x00;
uint32_t raw_T = 0x00;
uint32_t raw_H = 0x00;
if (ims_bme280_measure_raw(bme, &raw_T, &raw_P, &raw_H) != IMS_SUCCESS) {
return IMS_FAIL;
}
result->temperature = ims_bme280_compensate_T_int32(bme, raw_T);
result->pressure = ims_bme280_compensate_P_int64(bme, raw_P);
result->humidity = ims_bme280_compensate_H_int32(bme, raw_H);
return IMS_SUCCESS;
}
static int32_t ims_bme280_compensate_T_int32(ims_bme280_t *bme, int32_t adc_T) {
int32_t var1, var2, T;
var1 = ((((adc_T >> 3) - ((int32_t)bme->trim.dig_T1 << 1))) * ((int32_t)bme->trim.dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((int32_t)bme->trim.dig_T1)) * ((adc_T >> 4) - ((int32_t)bme->trim.dig_T1))) >> 12) *
((int32_t)bme->trim.dig_T3)) >>
14;
bme->t_fine = var1 + var2;
T = (bme->t_fine * 5 + 128) >> 8;
return T;
}
static uint32_t ims_bme280_compensate_P_int64(ims_bme280_t *bme, int32_t adc_P) {
int64_t var1, var2, p;
var1 = ((int64_t)bme->t_fine) - 128000;
var2 = var1 * var1 * (int64_t)bme->trim.dig_P6;
var2 = var2 + ((var1 * (int64_t)bme->trim.dig_P5) << 17);
var2 = var2 + (((int64_t)bme->trim.dig_P4) << 35);
var1 = ((var1 * var1 * (int64_t)bme->trim.dig_P3) >> 8) + ((var1 * (int64_t)bme->trim.dig_P2) << 12);
var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bme->trim.dig_P1) >> 33;
if (var1 == 0) {
return 0; // avoid exception caused by division by zero
}
p = 1048576 - adc_P;
p = (((p << 31) - var2) * 3125) / var1;
var1 = (((int64_t)bme->trim.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((int64_t)bme->trim.dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)bme->trim.dig_P7) << 4);
return (uint32_t)p;
}
static uint32_t ims_bme280_compensate_H_int32(ims_bme280_t *bme, int32_t adc_H) {
int32_t v_x1_u32r;
v_x1_u32r = (bme->t_fine - ((int32_t)76800));
v_x1_u32r = (((((adc_H << 14) - (((int32_t)bme->trim.dig_H4) << 20) - (((int32_t)bme->trim.dig_H5) * v_x1_u32r)) +
((int32_t)16384)) >>
15) *
(((((((v_x1_u32r * ((int32_t)bme->trim.dig_H6)) >> 10) *
(((v_x1_u32r * ((int32_t)bme->trim.dig_H3)) >> 11) + ((int32_t)32768))) >>
10) +
((int32_t)2097152)) *
((int32_t)bme->trim.dig_H2) +
8192) >>
14));
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)bme->trim.dig_H1)) >> 4));
v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
return (uint32_t)(v_x1_u32r >> 12);
}
#endif