From d998301bef6364f3fcf7a8d857c0ec0f82910141 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 22 Apr 2018 11:54:59 +0200 Subject: [PATCH] Improve driver - switch to continuous measurement - switch to double precision compensation formulas (datasheet section 8.1) - uncrustify Output of BMP280 and MPL3115 are now quite similar: INFO src/main.c i2c_scanner | I2C Address 0x60 true INFO src/main.c i2c_scanner | I2C Address 0x76 true DEBUG src/mgos_barometer.c mgos_barometer_create_i2c | Successfully detected mgos_barometer_type 2 at I2C 0x60 DEBUG src/mgos_barometer.c mgos_barometer_create_i2c | Successfully created mgos_barometer_type 2 at I2C 0x60 DEBUG src/mgos_barometer.c mgos_barometer_create_i2c | Successfully detected mgos_barometer_type 3 at I2C 0x76 DEBUG src/mgos_barometer.c mgos_barometer_create_i2c | Successfully created mgos_barometer_type 3 at I2C 0x76 INFO src/main.c do_baro | Pressure 96623.25Pa INFO src/main.c do_baro | Temperature 16.75C INFO src/main.c do_baro | Pressure 96629.70Pa INFO src/main.c do_baro | Temperature 18.45C INFO src/main.c do_baro | Pressure 96620.50Pa INFO src/main.c do_baro | Temperature 16.75C INFO src/main.c do_baro | Pressure 96633.49Pa INFO src/main.c do_baro | Temperature 18.43C --- src/mgos_barometer_bme280.c | 106 ++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/src/mgos_barometer_bme280.c b/src/mgos_barometer_bme280.c index b144d9a..193d5e8 100644 --- a/src/mgos_barometer_bme280.c +++ b/src/mgos_barometer_bme280.c @@ -7,7 +7,9 @@ bool mgos_barometer_bme280_detect(struct mgos_barometer *dev) { int val; - if (!dev) return false; + if (!dev) { + return false; + } if ((val = mgos_i2c_read_reg_b(dev->i2c, dev->i2caddr, BME280_REG_DEVID)) < 0) { return false; @@ -17,11 +19,12 @@ bool mgos_barometer_bme280_detect(struct mgos_barometer *dev) { LOG(LL_INFO, ("Preproduction version of BMP280 detected (0x%02x)", val)); return true; } - if (val == 0x58) // Mass production BMP280 + if (val == 0x58) { // Mass production BMP280 return true; + } if (val == 0x60) { // Mass production BME280 - dev->capabilities|=MGOS_BAROMETER_CAP_HYGROMETER; + dev->capabilities |= MGOS_BAROMETER_CAP_HYGROMETER; return true; } @@ -31,41 +34,51 @@ bool mgos_barometer_bme280_detect(struct mgos_barometer *dev) { bool mgos_barometer_bme280_create(struct mgos_barometer *dev) { struct mgos_barometer_bme280_data *bme280_data; - if (!dev) return false; + if (!dev) { + return false; + } - bme280_data=calloc(1, sizeof(struct mgos_barometer_bme280_data)); - if (!bme280_data) return false; - dev->user_data=bme280_data; + bme280_data = calloc(1, sizeof(struct mgos_barometer_bme280_data)); + if (!bme280_data) { + return false; + } + dev->user_data = bme280_data; // Reset device - if (!mgos_i2c_write_reg_b(dev->i2c, dev->i2caddr, BME280_REG_RESET, 0xB6)) + if (!mgos_i2c_write_reg_b(dev->i2c, dev->i2caddr, BME280_REG_RESET, 0xB6)) { return false; + } mgos_usleep(10000); // Read calibration data - if (!mgos_i2c_read_reg_n(dev->i2c, dev->i2caddr, BME280_REG_TEMPERATURE_CALIB_DIG_T1_LSB, 24, (uint8_t *)bme280_data)) + if (!mgos_i2c_read_reg_n(dev->i2c, dev->i2caddr, BME280_REG_TEMPERATURE_CALIB_DIG_T1_LSB, 24, (uint8_t *)bme280_data)) { return false; + } // SPI | 0.5ms period | 16X IIR filter - if (!mgos_i2c_write_reg_b(dev->i2c, dev->i2caddr, BME280_REG_CONFIG, 0x00 | BME280_STANDBY_500us << 2 | BME280_FILTER_16X << 5)) + if (!mgos_i2c_write_reg_b(dev->i2c, dev->i2caddr, BME280_REG_CONFIG, 0x00 | BME280_STANDBY_500us << 2 | BME280_FILTER_16X << 5)) { return false; + } mgos_usleep(10000); // Mode | Pressure OS | Temp OS - if (!mgos_i2c_write_reg_b(dev->i2c, dev->i2caddr, BME280_REG_CTRL_MEAS, BME280_MODE_NORMAL | BME280_OVERSAMP_16X << 2 | BME280_OVERSAMP_2X << 5)) + if (!mgos_i2c_write_reg_b(dev->i2c, dev->i2caddr, BME280_REG_CTRL_MEAS, BME280_MODE_NORMAL | BME280_OVERSAMP_16X << 2 | BME280_OVERSAMP_2X << 5)) { return false; + } - dev->capabilities|=MGOS_BAROMETER_CAP_BAROMETER; - dev->capabilities|=MGOS_BAROMETER_CAP_THERMOMETER; + dev->capabilities |= MGOS_BAROMETER_CAP_BAROMETER; + dev->capabilities |= MGOS_BAROMETER_CAP_THERMOMETER; return true; } bool mgos_barometer_bme280_destroy(struct mgos_barometer *dev) { - if (!dev) return false; + if (!dev) { + return false; + } if (dev->user_data) { free(dev->user_data); - dev->user_data=NULL; + dev->user_data = NULL; } return true; } @@ -73,46 +86,55 @@ bool mgos_barometer_bme280_destroy(struct mgos_barometer *dev) { bool mgos_barometer_bme280_read(struct mgos_barometer *dev) { struct mgos_barometer_bme280_data *bme280_data; - if (!dev) return false; - bme280_data=(struct mgos_barometer_bme280_data *) dev->user_data; - if (!bme280_data) return false; + if (!dev) { + return false; + } + bme280_data = (struct mgos_barometer_bme280_data *)dev->user_data; + if (!bme280_data) { + return false; + } // read data from sensor uint8_t data[6]; - if (!mgos_i2c_read_reg_n(dev->i2c, dev->i2caddr, BME280_REG_PRESSURE_MSB, 6, data)) + if (!mgos_i2c_read_reg_n(dev->i2c, dev->i2caddr, BME280_REG_PRESSURE_MSB, 6, data)) { return false; + } int32_t Padc, Tadc; Padc = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4)); Tadc = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4)); // LOG(LL_DEBUG, ("Padc=%d Tadc=%d", Padc, Tadc)); - int32_t var1, var2, T, t_fine, P; - // Temp conversion: - var1 = ((((Tadc >> 3) - ((int32_t)bme280_data->calib.dig_T1 << 1))) * ((int32_t)bme280_data->calib.dig_T2)) >> 11; - var2 = (((((Tadc >> 4) - ((int32_t)bme280_data->calib.dig_T1)) * ((Tadc >> 4) - ((int32_t)bme280_data->calib.dig_T1))) >> 12) * ((int32_t)bme280_data->calib.dig_T3)) >> 14; - t_fine = var1 + var2; - T = (t_fine * 5 + 128) >> 8; // in hundredth of degrees C; 5123 means 51.23C - dev->temperature=(float)T/100.0; + // Convert data (from datasheet, section 8.1) + double var1, var2, T, P; + int32_t t_fine; - // Pressure conversion: - var1 = ((int64_t)t_fine) - 128000; - var2 = var1 * var1 * (int64_t)bme280_data->calib.dig_P6; - var2 = var2 + ((var1*(int64_t)bme280_data->calib.dig_P5) << 17); - var2 = var2 + (((int64_t)bme280_data->calib.dig_P4) << 35); - var1 = ((var1 * var1 * (int64_t)bme280_data->calib.dig_P3) >> 8) + ((var1 * (int64_t)bme280_data->calib.dig_P2) << 12); - var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bme280_data->calib.dig_P1) >> 33; - if (var1 == 0) { - P=0; + // Compensation for temperature -- double precision + var1 = (((double)Tadc) / 16384.0 - ((double)bme280_data->calib.dig_T1) / 1024.0) * ((double)bme280_data->calib.dig_T2); + var2 = ((((double)Tadc) / 131072.0 - ((double)bme280_data->calib.dig_T1) / 8192.0) * + (((double)Tadc) / 131072.0 - ((double)bme280_data->calib.dig_T1) / 8192.0)) * ((double)bme280_data->calib.dig_T3); + t_fine = (int32_t)(var1 + var2); + T = (var1 + var2) / 5120.0; + dev->temperature = (float)T; + + // Compensation for pressure -- double precision + var1 = ((double)t_fine / 2.0) - 64000.0; + var2 = var1 * var1 * ((double)bme280_data->calib.dig_P6) / 32768.0; + var2 = var2 + var1 * ((double)bme280_data->calib.dig_P5) * 2.0; + var2 = (var2 / 4.0) + (((double)bme280_data->calib.dig_P4) * 65536.0); + var1 = (((double)bme280_data->calib.dig_P3) * var1 * var1 / 524288.0 + ((double)bme280_data->calib.dig_P2) * var1) / 524288.0; + var1 = (1.0 + var1 / 32768.0) * ((double)bme280_data->calib.dig_P1); + if (var1 == 0.0) { + P = 0.0; } else { - P = 1048576 - Padc; - P = (((P << 31) - var2) * 3125) / var1; - var1 = (((int64_t)bme280_data->calib.dig_P9) * (P >> 13) * (P >> 13)) >> 25; - var2 = (((int64_t)bme280_data->calib.dig_P8) * P) >> 19; - P = ((P + var1 + var2) >> 8) + (((int64_t)bme280_data->calib.dig_P7) << 4); + P = 1048576.0 - (double)Padc; + P = (P - (var2 / 4096.0)) * 6250.0 / var1; + var1 = ((double)bme280_data->calib.dig_P9) * P * P / 2147483648.0; + var2 = P * ((double)bme280_data->calib.dig_P8) / 32768.0; + P = P + (var1 + var2 + ((double)bme280_data->calib.dig_P7)) / 16.0; } - dev->pressure=((float)P/256.0)*100; + dev->pressure = (float)P; + // LOG(LL_DEBUG, ("P=%.2f T=%.2f", dev->pressure, dev->temperature)); return true; } -