From 659e98dbc6cecee0ca22616f46926e3f76f8ad0d Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Wed, 9 Apr 2025 11:31:58 +0200 Subject: [PATCH] switch bme280 to forced mode --- bme280.c | 109 ++++++++++++++++++++++++++++++++++++++----------------- bme280.h | 2 +- node1.c | 4 +- 3 files changed, 78 insertions(+), 37 deletions(-) diff --git a/bme280.c b/bme280.c index d888468..74bd2dd 100644 --- a/bme280.c +++ b/bme280.c @@ -18,6 +18,11 @@ https://shop.pimoroni.com/products/bme280-breakout?variant=29420960677971 - pimoroni pico sdk https://github.com/boschsensortec/BME280_SensorAPI/tree/c47f06eb44fc96970f0abfcc941ec16425b2a9e6 + + Suggested Settings: + - forced mode at 1 sample per min + - oversampling * 1 on temp, humidity, and pressure + - IIR Filter off */ // Define the custom pins for I2C @@ -73,7 +78,8 @@ // 17 * 2 = 34 #define NUM_COMPENSATION_PARAMS 34 -static void bmp280_get_compensation_params(i2c_inst_t *i2c, bme280_compensation_params *params) { +static void bmp280_get_compensation_params(i2c_inst_t *i2c, + bme280_compensation_params *params) { // raw temp and pressure values need to be calibrated according to // parameters generated during the manufacturing of the sensor // there are 3 temperature params, and 9 pressure params, each with a LSB @@ -109,6 +115,10 @@ static void bmp280_get_compensation_params(i2c_inst_t *i2c, bme280_compensation_ params->dig_h5 = (int16_t)(buf[33] << 8) | buf[32]; } +// Main Config for the sensor. Defined here so it can be use to inital configure the sensor and to proc further reads +// 001 sets osrs_t temp over sampling to 1, 001 sets osrs_p pressure +// oversampling to 1, 01 sets sensor mode to forced +static const uint8_t main_config = 0b00100101; void bme280_init(bme280_config *config, i2c_inst_t *i2c, uint8_t sda_pin, uint8_t scl_pin) { i2c_init(i2c, 100 * 1000); @@ -116,24 +126,25 @@ void bme280_init(bme280_config *config, i2c_inst_t *i2c, uint8_t sda_pin, gpio_set_function(scl_pin, GPIO_FUNC_I2C); gpio_pull_up(sda_pin); gpio_pull_up(scl_pin); - // use the "handheld device dynamic" optimal setting (see datasheet) - // bi_decl(bi_2pins_with_func(sda_pin, scl_pin, GPIO_FUNC_I2C)); - // bi_decl(bi_program_description("BMP280 I2C LIB")); uint8_t buf[2]; - // 500ms sampling time, x16 filter - const uint8_t reg_config_val = ((0x04 << 5) | (0x05 << 2)) & 0xFC; - - // send register number followed by its corresponding value - buf[0] = REG_CONFIG; - buf[1] = reg_config_val; + // 000 for t_sb is normal mode sample rate n/a, 000 turns filter off, 0 turns + // off spi + buf[0] = 0xF5; // config + buf[1] = 0x00; // all zeros i2c_write_blocking(i2c, ADDR, buf, 2, false); - // osrs_t x1, osrs_p x4, normal mode operation - const uint8_t reg_ctrl_meas_val = (0x01 << 5) | (0x03 << 2) | (0x03); - buf[0] = REG_CTRL_MEAS; - buf[1] = reg_ctrl_meas_val; + // send humidity oversample config + // 001 at the end sets over sampling to 1 + const uint8_t humidity_config = 0b00000001; + buf[0] = 0xF2; // ctrl_hum + buf[1] = humidity_config; + i2c_write_blocking(i2c, ADDR, buf, 2, false); + + // send temp oversample, pressure oversample, and mode configs + buf[0] = 0xF4; // ctrl_meas + buf[1] = main_config; i2c_write_blocking(i2c, ADDR, buf, 2, false); bme280_compensation_params params; @@ -144,29 +155,59 @@ void bme280_init(bme280_config *config, i2c_inst_t *i2c, uint8_t sda_pin, return; } -static void bmp280_read_raw(bme280_config *config, int32_t* temp, int32_t* pressure, int32_t* humidity) { - // BMP280 data registers are auto-incrementing and we have 3 temperature and - // pressure registers each, so we start at 0xF7 and read 6 bytes to 0xFC - // note: normal mode does not require further ctrl_meas and config register writes +/** + *Instructs the BME280 sensor to take a measurement in forced mode. + */ +static void bme280_proc_sensor_read(bme280_config *config) { + uint8_t buf[2] = {0xF4, main_config}; + i2c_write_blocking(config->i2c, ADDR, buf, 2, false); +} - uint8_t buf[6]; - uint8_t reg = REG_PRESSURE_MSB; - i2c_write_blocking(config->i2c, ADDR, ®, 1, true); // true to keep master control of bus - i2c_read_blocking(config->i2c, ADDR, buf, 6, false); // false - finished with bus +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; + i2c_write_blocking(config->i2c, ADDR, ®, 1, + true); // true to keep master control of bus + i2c_read_blocking(config->i2c, ADDR, buf, 6, + 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); + // 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); +} + +float bmp280_convert_temp(bme280_config *config, int32_t temp) { + bme280_compensation_params params = config->params; + int32_t var1, var2; + var1 = ((((temp >> 3) - ((int32_t)params.dig_t1 << 1))) * + ((int32_t)params.dig_t2)) >> + 11; + var2 = (((((temp >> 4) - ((int32_t)params.dig_t1)) * + ((temp >> 4) - ((int32_t)params.dig_t1))) >> + 12) * + ((int32_t)params.dig_t3)) >> + 14; + int32_t var3 = var1 + var2; + // uses the BMP280 calibration parameters to compensate the temperature value + // read from its registers + int32_t var4 = (var3 * 5 + 128) >> 8; + return (float)var4 / 100; } bme280_reading bme280_read(bme280_config *config) { - int32_t raw_temperature = 0; - int32_t raw_pressure = 0; - int32_t raw_humidity = 0; - bmp280_read_raw(config, &raw_temperature, &raw_pressure, &raw_humidity); - bme280_reading reading; - reading.temperature = raw_temperature; - reading.pressure = raw_pressure; - reading.humidity = raw_humidity; - return reading; + // instruct sensor to make a reading since we are in forced mode + bme280_proc_sensor_read(config); + + int32_t raw_temperature = 0; + int32_t raw_pressure = 0; + int32_t raw_humidity = 0; + bme280_read_raw(config, &raw_temperature, &raw_pressure, &raw_humidity); + bme280_reading reading; + reading.temperature = bmp280_convert_temp(config, raw_temperature); + reading.pressure = raw_pressure; + reading.humidity = raw_humidity; + return reading; } diff --git a/bme280.h b/bme280.h index a3e6caa..4eef6a7 100644 --- a/bme280.h +++ b/bme280.h @@ -32,7 +32,7 @@ typedef struct { } bme280_config; typedef struct { - int32_t temperature; + float temperature; int32_t pressure; int32_t humidity; } bme280_reading; diff --git a/node1.c b/node1.c index 2d10ece..474cf8f 100644 --- a/node1.c +++ b/node1.c @@ -11,10 +11,10 @@ int main() { bme280_init(&config, i2c1, 14, 15); bme280_reading current_reading; while (true) { - sleep_ms(2500); + sleep_ms(5000); // wait 5 sec printf("Making reading\n"); current_reading = bme280_read(&config); - printf("Tempature: %d\n", current_reading.temperature); + printf("Tempature: %.2f\n", current_reading.temperature); printf("Pressure: %d\n", current_reading.pressure); printf("Humidity: %d\n", current_reading.humidity); }