From 28201b6ba505ac1325129df75bd8df098d44258f Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Wed, 9 Apr 2025 13:21:51 +0200 Subject: [PATCH] get bem280 humidity reading working --- bme280.c | 107 ++++++++++++++++++++++++++++--------------------------- bme280.h | 11 +++--- node1.c | 2 +- 3 files changed, 62 insertions(+), 58 deletions(-) diff --git a/bme280.c b/bme280.c index 9bf5904..e432b26 100644 --- a/bme280.c +++ b/bme280.c @@ -46,37 +46,7 @@ // #define REG_PRESSURE_XLSB _u(0xF9) // #define REG_PRESSURE_LSB _u(0xF8) -#define REG_PRESSURE_MSB _u(0xF7) - -// calibration registers -#define REG_DIG_T1_LSB _u(0x88) -// #define REG_DIG_T1_MSB _u(0x89) -// #define REG_DIG_T2_LSB _u(0x8A) -// #define REG_DIG_T2_MSB _u(0x8B) -// #define REG_DIG_T3_LSB _u(0x8C) -// #define REG_DIG_T3_MSB _u(0x8D) -// #define REG_DIG_P1_LSB _u(0x8E) -// #define REG_DIG_P1_MSB _u(0x8F) -// #define REG_DIG_P2_LSB _u(0x90) -// #define REG_DIG_P2_MSB _u(0x91) -// #define REG_DIG_P3_LSB _u(0x92) -// #define REG_DIG_P3_MSB _u(0x93) -// #define REG_DIG_P4_LSB _u(0x94) -// #define REG_DIG_P4_MSB _u(0x95) -// #define REG_DIG_P5_LSB _u(0x96) -// #define REG_DIG_P5_MSB _u(0x97) -// #define REG_DIG_P6_LSB _u(0x98) -// #define REG_DIG_P6_MSB _u(0x99) -// #define REG_DIG_P7_LSB _u(0x9A) -// #define REG_DIG_P7_MSB _u(0x9B) -// #define REG_DIG_P8_LSB _u(0x9C) -// #define REG_DIG_P8_MSB _u(0x9D) -// #define REG_DIG_P9_LSB _u(0x9E) -// #define REG_DIG_P9_MSB _u(0x9F) - -// number of calibration registers to be read -// 17 * 2 = 34 -#define NUM_COMPENSATION_PARAMS 34 +// #define REG_PRESSURE_MSB _u(0xF7) static void bmp280_get_compensation_params(i2c_inst_t *i2c, bme280_compensation_params *params) { @@ -85,15 +55,12 @@ static void bmp280_get_compensation_params(i2c_inst_t *i2c, // there are 3 temperature params, and 9 pressure params, each with a LSB // and MSB register, so we read from 24 registers - uint8_t buf[NUM_COMPENSATION_PARAMS] = {0}; - uint8_t reg = REG_DIG_T1_LSB; - i2c_write_blocking(i2c, ADDR, ®, 1, - true); // true to keep master control of bus - // read in one go as register addresses auto-increment - i2c_read_blocking(i2c, ADDR, buf, NUM_COMPENSATION_PARAMS, - false); // false, we're done reading + // read the first 24 compensation params + uint8_t buf[25] = {0}; + uint8_t reg = 0x88; + i2c_write_blocking(i2c, ADDR, ®, 1, true); // true to keep master control of bus + i2c_read_blocking(i2c, ADDR, buf, 25, false); - // store these in a struct for later use params->dig_t1 = (uint16_t)(buf[1] << 8) | buf[0]; params->dig_t2 = (int16_t)(buf[3] << 8) | buf[2]; params->dig_t3 = (int16_t)(buf[5] << 8) | buf[4]; @@ -107,12 +74,21 @@ static void bmp280_get_compensation_params(i2c_inst_t *i2c, params->dig_p7 = (int16_t)(buf[19] << 8) | buf[18]; params->dig_p8 = (int16_t)(buf[21] << 8) | buf[20]; params->dig_p9 = (int16_t)(buf[23] << 8) | buf[22]; + params->dig_h1 = (int16_t)buf[24]; - params->dig_h1 = (int16_t)(buf[25] << 8) | buf[24]; - params->dig_h2 = (int16_t)(buf[27] << 8) | buf[26]; - params->dig_h3 = (int16_t)(buf[29] << 8) | buf[28]; - params->dig_h4 = (int16_t)(buf[31] << 8) | buf[30]; - params->dig_h5 = (int16_t)(buf[33] << 8) | buf[32]; + // read second set of compensation params + reg = 0xE1; + i2c_write_blocking(i2c, ADDR, ®, 1, true); // true to keep master control of bus + i2c_read_blocking(i2c, ADDR, buf, 7, false); // false, we're done reading + params->dig_h2 = (int16_t)(int16_t)(buf[1] << 8) | buf[0]; + params->dig_h3 = buf[2]; + int16_t dig_h4_msb = (int16_t)(int8_t)buf[3] * 16; + int16_t dig_h4_lsb = (int16_t)(buf[4] & 0x0F); + params->dig_h4 = dig_h4_msb | dig_h4_lsb; + int16_t dig_h5_msb = (int16_t)(int8_t)buf[5] * 16; + int16_t dig_h5_lsb = (int16_t)(buf[4] >> 4); + params->dig_h5 = dig_h5_msb | dig_h5_lsb; + params->dig_h6 = (int8_t)buf[6]; } // Main Config for the sensor. Defined here so it can be use to inital configure @@ -167,16 +143,17 @@ static void bme280_read_raw(bme280_config *config, int32_t *temp, int32_t *pressure, int32_t *humidity) { // TODO: burst read 0xF7 0xFE // pressure 20 bit, temp 20 bit, humidity 16 bit - uint8_t buf[6]; - uint8_t reg = REG_PRESSURE_MSB; + uint8_t buf[8]; + uint8_t reg = 0xF7; i2c_write_blocking(config->i2c, ADDR, ®, 1, true); // true to keep master control of bus - i2c_read_blocking(config->i2c, ADDR, buf, 6, + i2c_read_blocking(config->i2c, ADDR, buf, 8, false); // false - finished with bus // store the 20 bit read in a 32 bit signed integer for conversion *pressure = (buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4); *temp = (buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4); + *humidity = (buf[6] << 8) | buf[7]; } static int32_t bme280_caculate_t_fine(bme280_config *config, int32_t temp) { @@ -193,13 +170,13 @@ static int32_t bme280_caculate_t_fine(bme280_config *config, int32_t temp) { return var1 + var2; } -float bme280_convert_temp(int32_t t_fine) { +static float bme280_convert_temp(int32_t t_fine) { int32_t temp = (t_fine * 5 + 128) >> 8; return (float)temp / 100; } -float bmp280_convert_pressure(bme280_config *config, int32_t t_fine, - int32_t pressure) { +static float bme280_convert_pressure(bme280_config *config, int32_t t_fine, + int32_t pressure) { bme280_compensation_params params = config->params; int32_t var1, var2; uint32_t converted = 0.0; @@ -230,6 +207,32 @@ float bmp280_convert_pressure(bme280_config *config, int32_t t_fine, return (float)converted / 100; } +static float bmp280_convert_humidity(bme280_config *config, int32_t t_fine, + int32_t raw_humidity) { + double humidity_min = 0.0; + double humidity_max = 100.0; + double humidity, var1, var2, var3, var4, var5, var6; + + bme280_compensation_params params = config->params; + var1 = ((double)t_fine) - 76800.0; + var2 = (((double)params.dig_h4) * 64.0 + + (((double)params.dig_h5) / 16384.0) * var1); + var3 = raw_humidity - var2; + var4 = ((double)params.dig_h2) / 65536.0; + var5 = (1.0 + (((double)params.dig_h3) / 67108864.0) * var1); + var6 = 1.0 + (((double)params.dig_h6) / 67108864.0) * var1 * var5; + var6 = var3 * var4 * (var5 * var6); + humidity = var6 * (1.0 - ((double)params.dig_h1) * var6 / 524288.0); + + if (humidity > humidity_max) { + humidity = humidity_max; + } else if (humidity < humidity_min) { + humidity = humidity_min; + } + + return (float)humidity; +} + bme280_reading bme280_read(bme280_config *config) { // instruct sensor to make a reading since we are in forced mode bme280_proc_sensor_read(config); @@ -241,7 +244,7 @@ bme280_reading bme280_read(bme280_config *config) { bme280_reading reading; int32_t t_fine = bme280_caculate_t_fine(config, raw_temperature); reading.temperature = bme280_convert_temp(t_fine); - reading.pressure = bmp280_convert_pressure(config, t_fine, raw_pressure); - reading.humidity = raw_humidity; + reading.pressure = bme280_convert_pressure(config, t_fine, raw_pressure); + reading.humidity = bmp280_convert_humidity(config, t_fine, raw_humidity); return reading; } diff --git a/bme280.h b/bme280.h index d136be6..ed1fb6c 100644 --- a/bme280.h +++ b/bme280.h @@ -19,11 +19,12 @@ typedef struct { int16_t dig_p9; // humidity params - uint16_t dig_h1; + uint8_t dig_h1; int16_t dig_h2; - int16_t dig_h3; + uint8_t dig_h3; int16_t dig_h4; int16_t dig_h5; + int8_t dig_h6; } bme280_compensation_params; typedef struct { @@ -34,11 +35,11 @@ typedef struct { typedef struct { float temperature; float pressure; - int32_t humidity; + float humidity; } bme280_reading; -void bme280_init(bme280_config *config, i2c_inst_t *i2c, - uint8_t sda_pin, uint8_t scl_pin); +void bme280_init(bme280_config *config, i2c_inst_t *i2c, uint8_t sda_pin, + uint8_t scl_pin); bme280_reading bme280_read(bme280_config *config); #endif /* BME280_H */ diff --git a/node1.c b/node1.c index c71e210..371aa11 100644 --- a/node1.c +++ b/node1.c @@ -16,6 +16,6 @@ int main() { current_reading = bme280_read(&config); printf("Tempature: %.2f\n", current_reading.temperature); printf("Pressure: %.2f\n", current_reading.pressure); - printf("Humidity: %d\n", current_reading.humidity); + printf("Humidity: %.2f\n", current_reading.humidity); } }