From 76f67eb554ad3bce5c7d79094a68231c72241a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claudio=20Donat=C3=A9?= Date: Sat, 26 Dec 2020 00:06:19 -0300 Subject: [PATCH 1/2] feat: add read burst Read all measurements in one read command Read Datasheed section 4 Data readout for reason behing this feature --- src/SparkFunBME280.cpp | 104 +++++++++++++++++++++++++++++++++++++++++ src/SparkFunBME280.h | 15 ++++++ 2 files changed, 119 insertions(+) diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index 235e259..39a7e2e 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -355,6 +355,29 @@ void BME280::reset( void ) } +//****************************************************************************// +// +// Burst Measurement Section +// +//****************************************************************************// + +//Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout +//tempScale = 0 for Celsius scale +//tempScale = 1 for Fahrenheit scale +void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale){ + + uint8_t dataBurst[8]; + readRegisterRegion(dataBurst, BME280_MEASUREMENTS_REG, 8); + + if(tempScale == 0){ + readTempCFromBurst(dataBurst, measurements); + }else{ + readTempFFromBurst(dataBurst, measurements); + } + readFloatPressureFromBurst(dataBurst, measurements); + readFloatHumidityFromBurst(dataBurst, measurements); +} + //****************************************************************************// // // Pressure Section @@ -390,6 +413,37 @@ float BME280::readFloatPressure( void ) } +void BME280::readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) +{ + + // Set pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). + // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa + + int32_t adc_P = ((uint32_t)buffer[0] << 12) | ((uint32_t)buffer[1] << 4) | ((buffer[2] >> 4) & 0x0F); + + int64_t var1, var2, p_acc; + var1 = ((int64_t)t_fine) - 128000; + var2 = var1 * var1 * (int64_t)calibration.dig_P6; + var2 = var2 + ((var1 * (int64_t)calibration.dig_P5)<<17); + var2 = var2 + (((int64_t)calibration.dig_P4)<<35); + var1 = ((var1 * var1 * (int64_t)calibration.dig_P3)>>8) + ((var1 * (int64_t)calibration.dig_P2)<<12); + var1 = (((((int64_t)1)<<47)+var1))*((int64_t)calibration.dig_P1)>>33; + if (var1 == 0) + { + measurements->pressure = 0; // avoid exception caused by division by zero + } + else + { + p_acc = 1048576 - adc_P; + p_acc = (((p_acc<<31) - var2)*3125)/var1; + var1 = (((int64_t)calibration.dig_P9) * (p_acc>>13) * (p_acc>>13)) >> 25; + var2 = (((int64_t)calibration.dig_P8) * p_acc) >> 19; + p_acc = ((p_acc + var1 + var2) >> 8) + (((int64_t)calibration.dig_P7)<<4); + + measurements->pressure = (float)p_acc / 256.0; + } +} + // Sets the internal variable _referencePressure so the altitude is calculated properly. // This is also known as "sea level pressure" and is in Pascals. The value is probably // within 10% of 101325. This varies based on the weather: @@ -459,6 +513,25 @@ float BME280::readFloatHumidity( void ) return (float)(var1>>12) / 1024.0; } +void BME280::readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) +{ + + // Set humidity in %RH as unsigned 32 bit integer in Q22. 10 format (22 integer and 10 fractional bits). + // Output value of “47445” represents 47445/1024 = 46. 333 %RH + int32_t adc_H = ((uint32_t)buffer[6] << 8) | ((uint32_t)buffer[7]); + + int32_t var1; + var1 = (t_fine - ((int32_t)76800)); + var1 = (((((adc_H << 14) - (((int32_t)calibration.dig_H4) << 20) - (((int32_t)calibration.dig_H5) * var1)) + + ((int32_t)16384)) >> 15) * (((((((var1 * ((int32_t)calibration.dig_H6)) >> 10) * (((var1 * ((int32_t)calibration.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * + ((int32_t)calibration.dig_H2) + 8192) >> 14)); + var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * ((int32_t)calibration.dig_H1)) >> 4)); + var1 = (var1 < 0 ? 0 : var1); + var1 = (var1 > 419430400 ? 419430400 : var1); + + measurements->humidity = (float)(var1>>12) / 1024.0; +} + //****************************************************************************// // // Temperature Section @@ -494,6 +567,29 @@ float BME280::readTempC( void ) return output; } +float BME280::readTempFromBurst(uint8_t buffer[]) +{ + int32_t adc_T = ((uint32_t)buffer[3] << 12) | ((uint32_t)buffer[4] << 4) | ((buffer[5] >> 4) & 0x0F); + + //By datasheet, calibrate + int64_t var1, var2; + + var1 = ((((adc_T>>3) - ((int32_t)calibration.dig_T1<<1))) * ((int32_t)calibration.dig_T2)) >> 11; + var2 = (((((adc_T>>4) - ((int32_t)calibration.dig_T1)) * ((adc_T>>4) - ((int32_t)calibration.dig_T1))) >> 12) * + ((int32_t)calibration.dig_T3)) >> 14; + t_fine = var1 + var2; + float output = (t_fine * 5 + 128) >> 8; + + output = output / 100 + settings.tempCorrection; + + return output; +} + +void BME280::readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) +{ + measurements->temperature = readTempFromBurst(buffer); +} + float BME280::readTempF( void ) { float output = readTempC(); @@ -502,6 +598,14 @@ float BME280::readTempF( void ) return output; } +void BME280::readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) +{ + float output = readTempFromBurst(buffer); + output = (output * 9) / 5 + 32; + + measurements->temperature = output; +} + //****************************************************************************// // // Dew point Section diff --git a/src/SparkFunBME280.h b/src/SparkFunBME280.h index 77667b3..f2dc15b 100644 --- a/src/SparkFunBME280.h +++ b/src/SparkFunBME280.h @@ -105,6 +105,7 @@ Distributed as-is; no warranty is given. #define BME280_STAT_REG 0xF3 //Status Reg #define BME280_CTRL_MEAS_REG 0xF4 //Ctrl Measure Reg #define BME280_CONFIG_REG 0xF5 //Configuration Reg +#define BME280_MEASUREMENTS_REG 0xF7 //Measurements register start #define BME280_PRESSURE_MSB_REG 0xF7 //Pressure MSB #define BME280_PRESSURE_LSB_REG 0xF8 //Pressure LSB #define BME280_PRESSURE_XLSB_REG 0xF9 //Pressure XLSB @@ -172,6 +173,14 @@ struct SensorCalibration }; +struct BME280_SensorMeasurements +{ + public: + float temperature; + float pressure; + float humidity; +}; + //This is the main operational class of the driver. class BME280 @@ -215,18 +224,22 @@ class BME280 //Software reset routine void reset( void ); + void readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale = 0); //Returns the values as floats. float readFloatPressure( void ); float readFloatAltitudeMeters( void ); float readFloatAltitudeFeet( void ); + void readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); float readFloatHumidity( void ); + void readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); //Temperature related methods void setTemperatureCorrection(float corr); float readTempC( void ); float readTempF( void ); + float readTempFromBurst(uint8_t buffer[]); //Dewpoint related methods //From Pavel-Sayekat: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/pull/6/files @@ -248,6 +261,8 @@ class BME280 private: uint8_t checkSampleValue(uint8_t userValue); //Checks for valid over sample values + void readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); + void readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); uint8_t _wireType = HARD_WIRE; //Default to Wire.h TwoWire *_hardPort = NO_WIRE; //The generic connection to user's chosen I2C hardware From ac0b596992fa2364b541dfd7ed5a357d98e7cbec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claudio=20Donat=C3=A9?= Date: Wed, 30 Dec 2020 14:46:11 -0300 Subject: [PATCH 2/2] feat: create burst measurement example add documentation for the default scale on burst read --- .../Example11_BurstRead.ino | 68 +++++++++++++++++++ src/SparkFunBME280.cpp | 2 +- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 examples/Example11_BurstRead/Example11_BurstRead.ino diff --git a/examples/Example11_BurstRead/Example11_BurstRead.ino b/examples/Example11_BurstRead/Example11_BurstRead.ino new file mode 100644 index 0000000..0e0a2f7 --- /dev/null +++ b/examples/Example11_BurstRead/Example11_BurstRead.ino @@ -0,0 +1,68 @@ +/* + Get environmental readings as a burst from the BME280 + By: Claudio Donaté + Date: December 30th, 2020 + License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). + + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/14348 - Qwiic Combo Board + https://www.sparkfun.com/products/13676 - BME280 Breakout Board + + This example shows how to read humidity, pressure, and current temperature from the BME280 over I2C reading all registers at once. + Please check BME280 Datasheet, section 4, Data readout for detail explanations on why. + + Hardware connections: + BME280 -> Arduino + GND -> GND + 3.3 -> 3.3 + SDA -> A4 + SCL -> A5 +*/ + +#include + +#include "SparkFunBME280.h" + +#define CELSIUS_SCALE 0 //Default +#define FAHRENHEIT_SCALE 1 + +BME280 mySensor; +BME280_SensorMeasurements measurements; + +void setup() +{ + Serial.begin(9600); + Serial.println("Reading basic values from BME280 as a Burst"); + + Wire.begin(); + + if (mySensor.beginI2C() == false) //Begin communication over I2C + { + Serial.println("The sensor did not respond. Please check wiring."); + while(1); //Freeze + } +} + +void loop() +{ + while (mySensor.isMeasuring()) // Wait for sensor to finish measuring + { + Serial.print("."); + }; + + mySensor.readAllMeasurements(&measurements); // Return temperature in Celsius + // mySensor.readAllMeasurements(&measurements, FAHRENHEIT_SCALE); + + Serial.print("\nHumidity: "); + Serial.print(measurements.humidity, 0); + + Serial.print(" Pressure: "); + Serial.print(measurements.pressure, 0); + + Serial.print(" Temp: "); + Serial.print(measurements.temperature, 2); + + Serial.println(); + + delay(50); +} diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index 39a7e2e..0dc9920 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -362,7 +362,7 @@ void BME280::reset( void ) //****************************************************************************// //Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout -//tempScale = 0 for Celsius scale +//tempScale = 0 for Celsius scale (default setting) //tempScale = 1 for Fahrenheit scale void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale){