From 238b4a2c80f829f628a2df3007423a2af0377ffa Mon Sep 17 00:00:00 2001 From: imi415 Date: Fri, 22 Jul 2022 21:51:23 +0800 Subject: [PATCH] Updated BME280. --- include/imsensors/dht/dht_bme280.h | 14 +- src/dht/dht_bme280.c | 207 +++++++++++++++++++++-------- 2 files changed, 163 insertions(+), 58 deletions(-) diff --git a/include/imsensors/dht/dht_bme280.h b/include/imsensors/dht/dht_bme280.h index ee3bcc8..9c6eada 100644 --- a/include/imsensors/dht/dht_bme280.h +++ b/include/imsensors/dht/dht_bme280.h @@ -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 \ No newline at end of file diff --git a/src/dht/dht_bme280.c b/src/dht/dht_bme280.c index a74f464..59c1f08 100644 --- a/src/dht/dht_bme280.c +++ b/src/dht/dht_bme280.c @@ -2,112 +2,153 @@ #include -#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 = ®, + .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 \ No newline at end of file