From 62d8a50a53b6d2f7334eb923e1ffb746847618aa Mon Sep 17 00:00:00 2001 From: Christian Stehno Date: Tue, 26 Nov 2019 17:26:16 +0100 Subject: [PATCH 01/17] Add method for setting temperature correction --- src/SparkFunBME280.cpp | 7 ++++++- src/SparkFunBME280.h | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index c312244..31d5377 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -47,7 +47,7 @@ BME280::BME280( void ) settings.tempOverSample = 1; settings.pressOverSample = 1; settings.humidOverSample = 1; - settings.tempCorrection = 0.0; // correction of temperature - added to the result + settings.tempCorrection = 0.f; // correction of temperature - added to the result } @@ -453,6 +453,11 @@ float BME280::readFloatHumidity( void ) // //****************************************************************************// +void BME280::setTemperatureCorrection(float corr) +{ + settings.tempCorrection = corr; +} + float BME280::readTempC( void ) { // Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. diff --git a/src/SparkFunBME280.h b/src/SparkFunBME280.h index 0b7b766..77667b3 100644 --- a/src/SparkFunBME280.h +++ b/src/SparkFunBME280.h @@ -223,7 +223,8 @@ class BME280 float readFloatHumidity( void ); - //Temperature related methods + //Temperature related methods + void setTemperatureCorrection(float corr); float readTempC( void ); float readTempF( void ); @@ -258,4 +259,4 @@ class BME280 float _referencePressure = 101325.0; //Default but is changeable }; -#endif // End of __BME280_H__ definition check \ No newline at end of file +#endif // End of __BME280_H__ definition check From 8e57734a46eb4f5425b170c76036520352bca139 Mon Sep 17 00:00:00 2001 From: AndyEngland521 Date: Wed, 27 Nov 2019 11:57:24 -0700 Subject: [PATCH 02/17] bumping library.properties to add get/set for temp correction --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 7fd0ba7..10c1a7e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun BME280 -version=2.0.7 +version=2.0.8 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A library to drive the Bosch BME280 Altimeter and Pressure sensor From ebc56a7f1f546614ad10f4c0df47f64a4b7b98d2 Mon Sep 17 00:00:00 2001 From: ted Date: Fri, 2 Oct 2020 17:45:46 -0700 Subject: [PATCH 03/17] add some comments about "refPressure" There are too many units and names for this, so at least provide some hints to what it means. I'm already distracted and it's Friday so I put some Sparkfun style commentary in it. --- src/SparkFunBME280.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index 31d5377..235e259 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -390,7 +390,13 @@ float BME280::readFloatPressure( void ) } -//Sets the internal variable _referencePressure so the +// 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: +// https://en.wikipedia.org/wiki/Atmospheric_pressure#Mean_sea-level_pressure +// +// if you are concerned about accuracy or precision, make sure to pull the +// "sea level pressure"value from a trusted source like NOAA. void BME280::setReferencePressure(float refPressure) { _referencePressure = refPressure; @@ -406,7 +412,13 @@ float BME280::readFloatAltitudeMeters( void ) { float heightOutput = 0; - //heightOutput = ((float)-45846.2)*(pow(((float)readFloatPressure()/(float)_referencePressure), 0.190263) - (float)1); + // Getting height from a pressure reading is called the "international barometric height formula". + // The magic value of 44330.77 was adjusted in issue #30. + // There's also some discussion of it here: https://www.sparkfun.com/tutorials/253 + // This calculation is NOT designed to work on non-Earthlike planets such as Mars or Venus; + // see NRLMSISE-00. That's why it is the "international" formula, not "interplanetary". + // Sparkfun is not liable for incorrect altitude calculations from this + // code on those planets. Interplanetary selfies are welcome, however. heightOutput = ((float)-44330.77)*(pow(((float)readFloatPressure()/(float)_referencePressure), 0.190263) - (float)1); //Corrected, see issue 30 return heightOutput; From 9e01070491e60288e609801ea62a324af75287c3 Mon Sep 17 00:00:00 2001 From: santaimpersonator <36016723+santaimpersonator@users.noreply.github.com> Date: Thu, 8 Oct 2020 14:08:41 -0600 Subject: [PATCH 04/17] Link Qwiic BME280 product Link Qwiic BME280 product to listed products and product repositories, under documentation. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index abb6523..4602114 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,16 @@ Documentation -------------- * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. -* **[Product Repository](https://github.com/sparkfun/BME280-Breakout-Board)** - Main repository (including hardware files) for the SparkFun BME280 Breakout. +* **Product Repositories:** (including hardware files) + * [SparkFun BME280 Breakout](https://github.com/sparkfun/BME280-Breakout-Board) - Original product repository + * [SparkFun Environmental Combo Breakout - CCS811/BME280 (Qwiic)](https://www.sparkfun.com/products/14348) + * [SparkFun Atmospheric Sensor Breakout - BME280 (Qwiic)](https://github.com/sparkfun/Qwiic_Atmospheric_Sensor_Breakout_BME280) * **[Hookup Guide](https://learn.sparkfun.com/tutorials/sparkfun-bme280-breakout-hookup-guide)** - Basic hookup guide for the SparkFun BME280 Breakout. Products that use this Library --------------------------------- +* [*SEN-15440*](https://www.sparkfun.com/products/15440) * [*SEN-14348*](https://www.sparkfun.com/products/14348) * [*SEN-13676*](https://www.sparkfun.com/products/13676) From bbe667988d2c7ad1f1987968fa25aba15819f195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= Date: Sat, 24 Oct 2020 13:21:14 +0200 Subject: [PATCH 05/17] Include math.h SparkFunBME280.cpp uses math functions pow, log and log10. This produces errors such as "pow was not declared in this scope". Found this while packaging this library for RIOT-OS. The library works with Arduino because math.h is included somewhere else. But I think it's better or more correct to include the headers for the functions used. Fixes #48 --- src/SparkFunBME280.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index 235e259..1e624da 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -20,6 +20,7 @@ Distributed as-is; no warranty is given. ******************************************************************************/ //See SparkFunBME280.h for additional topology notes. +#include #include "SparkFunBME280.h" //****************************************************************************// 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 06/17] 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 07/17] 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){ From 3b07e8c403a081d80683ad1046dbd0c5489ea1ad Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 30 Dec 2020 13:36:11 -0700 Subject: [PATCH 08/17] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4602114..3f3fc4b 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ Some examples include a circular buffer class for averaging. Thanks to: * calvin1564 for [fixing a name collision](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/34) * LukaHitH for adding [BMP280 support](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/23) +* cdonate for adding [burst read](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/50) +* jdavid for integrating [math.h](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/49) Repository Contents ------------------- From ab32ea0ea99c2b101d71690e31e2f9e133fb65dd Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 30 Dec 2020 13:40:56 -0700 Subject: [PATCH 09/17] Change examples to 115200bps to match style guide --- examples/Example10_DewPoint/Example10_DewPoint.ino | 2 +- examples/Example11_BurstRead/Example11_BurstRead.ino | 2 +- examples/Example1_BasicReadings/Example1_BasicReadings.ino | 2 +- examples/Example2_I2CAddress/Example2_I2CAddress.ino | 2 +- examples/Example3_CSVOutput/Example3_CSVOutput.ino | 2 +- examples/Example4_Settings/Example4_Settings.ino | 2 +- .../Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino | 2 +- examples/Example6_LowPower/Example6_LowPower.ino | 2 +- .../Example7_RelativeAltitudeChange.ino | 2 +- examples/Example8_LocalPressure/Example8_LocalPressure.ino | 2 +- examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/Example10_DewPoint/Example10_DewPoint.ino b/examples/Example10_DewPoint/Example10_DewPoint.ino index 6c1b4b6..fa0781b 100644 --- a/examples/Example10_DewPoint/Example10_DewPoint.ino +++ b/examples/Example10_DewPoint/Example10_DewPoint.ino @@ -25,7 +25,7 @@ BME280 mySensor; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Example showing dewpoint calculation"); mySensor.setI2CAddress(0x76); //Connect to a second sensor diff --git a/examples/Example11_BurstRead/Example11_BurstRead.ino b/examples/Example11_BurstRead/Example11_BurstRead.ino index 0e0a2f7..6e94e7f 100644 --- a/examples/Example11_BurstRead/Example11_BurstRead.ino +++ b/examples/Example11_BurstRead/Example11_BurstRead.ino @@ -31,7 +31,7 @@ BME280_SensorMeasurements measurements; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Reading basic values from BME280 as a Burst"); Wire.begin(); diff --git a/examples/Example1_BasicReadings/Example1_BasicReadings.ino b/examples/Example1_BasicReadings/Example1_BasicReadings.ino index a4078f8..3fe99c4 100644 --- a/examples/Example1_BasicReadings/Example1_BasicReadings.ino +++ b/examples/Example1_BasicReadings/Example1_BasicReadings.ino @@ -26,7 +26,7 @@ BME280 mySensor; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Reading basic values from BME280"); Wire.begin(); diff --git a/examples/Example2_I2CAddress/Example2_I2CAddress.ino b/examples/Example2_I2CAddress/Example2_I2CAddress.ino index d277347..7d97120 100644 --- a/examples/Example2_I2CAddress/Example2_I2CAddress.ino +++ b/examples/Example2_I2CAddress/Example2_I2CAddress.ino @@ -27,7 +27,7 @@ BME280 mySensorB; //Uses I2C address 0x76 (jumper closed) void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Example showing alternate I2C addresses"); Wire.begin(); diff --git a/examples/Example3_CSVOutput/Example3_CSVOutput.ino b/examples/Example3_CSVOutput/Example3_CSVOutput.ino index 03e9d43..cb34eff 100644 --- a/examples/Example3_CSVOutput/Example3_CSVOutput.ino +++ b/examples/Example3_CSVOutput/Example3_CSVOutput.ino @@ -21,7 +21,7 @@ unsigned long sampleNumber = 0; void setup() { - Serial.begin(9600); + Serial.begin(115200); Wire.begin(); diff --git a/examples/Example4_Settings/Example4_Settings.ino b/examples/Example4_Settings/Example4_Settings.ino index b9e61f9..f51b795 100644 --- a/examples/Example4_Settings/Example4_Settings.ino +++ b/examples/Example4_Settings/Example4_Settings.ino @@ -17,7 +17,7 @@ BME280 mySensor; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Example showing alternate I2C addresses"); Wire.begin(); diff --git a/examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino b/examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino index f15eda4..85acc6a 100644 --- a/examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino +++ b/examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino @@ -23,7 +23,7 @@ BME280 mySensor; void setup() { - Serial.begin(9600); + Serial.begin(115200); while(!Serial); //Needed for printing correctly when using a Teensy Serial.println("Reading all registers from BME280"); diff --git a/examples/Example6_LowPower/Example6_LowPower.ino b/examples/Example6_LowPower/Example6_LowPower.ino index e2fd8a6..c42abe8 100644 --- a/examples/Example6_LowPower/Example6_LowPower.ino +++ b/examples/Example6_LowPower/Example6_LowPower.ino @@ -18,7 +18,7 @@ BME280 mySensor; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Example showing alternate I2C addresses"); Wire.begin(); diff --git a/examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino b/examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino index 7b3e136..586ed2d 100644 --- a/examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino +++ b/examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino @@ -41,7 +41,7 @@ float localAltitude = 0; void setup() { - Serial.begin(9600); + Serial.begin(115200); while(!Serial); //Wait for user to get terminal open Serial.println("Output a local changing altitude"); Serial.println("Press any key to zero local altitude"); diff --git a/examples/Example8_LocalPressure/Example8_LocalPressure.ino b/examples/Example8_LocalPressure/Example8_LocalPressure.ino index d1a4fcd..552be86 100644 --- a/examples/Example8_LocalPressure/Example8_LocalPressure.ino +++ b/examples/Example8_LocalPressure/Example8_LocalPressure.ino @@ -25,7 +25,7 @@ BME280 mySensor; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Example showing alternate I2C addresses"); Wire.begin(); diff --git a/examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino b/examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino index b5c3c6a..f47d0b1 100644 --- a/examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino +++ b/examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino @@ -31,7 +31,7 @@ BME280 mySensor; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("Example showing alternate I2C addresses"); myWire.begin(); From d2eda03f8ded9f1621e37bf5217f08b7548848a3 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 30 Dec 2020 13:42:31 -0700 Subject: [PATCH 10/17] Remove Wire.begin() from begin() --- src/SparkFunBME280.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index b7085f6..b1136c3 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -71,17 +71,18 @@ uint8_t BME280::begin() case I2C_MODE: - switch(_wireType) - { - case(HARD_WIRE): - _hardPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise it can be hard to debug. - break; - case(SOFT_WIRE): - #ifdef SoftwareWire_h - _softPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise it can be hard to debug. - #endif - break; - } + //Removing port begin from library. This should be done by user otherwise this library will overwrite Wire settings such as clock speed. + // switch(_wireType) + // { + // case(HARD_WIRE): + // _hardPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise it can be hard to debug. + // break; + // case(SOFT_WIRE): + // #ifdef SoftwareWire_h + // _softPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise it can be hard to debug. + // #endif + // break; + // } break; case SPI_MODE: From 0b5eabfe23cf8fb463b2e7c32bfe9152d26dc64d Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 30 Dec 2020 20:44:27 -0700 Subject: [PATCH 11/17] Update library.properties --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 10c1a7e..bb3733d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun BME280 -version=2.0.8 +version=2.0.9 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A library to drive the Bosch BME280 Altimeter and Pressure sensor From 55768beb0cf69166558326e54f5a02249e9fd842 Mon Sep 17 00:00:00 2001 From: Jonas Lauer Date: Sat, 7 May 2022 20:42:46 +0200 Subject: [PATCH 12/17] change byte to uint8_t to avoid naming conflict with ESP8266 toolchain --- src/SparkFunBME280.cpp | 2 +- src/SparkFunBME280.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index b1136c3..dac7ab1 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -366,7 +366,7 @@ void BME280::reset( void ) //Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout //tempScale = 0 for Celsius scale (default setting) //tempScale = 1 for Fahrenheit scale -void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale){ +void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t tempScale){ uint8_t dataBurst[8]; readRegisterRegion(dataBurst, BME280_MEASUREMENTS_REG, 8); diff --git a/src/SparkFunBME280.h b/src/SparkFunBME280.h index f2dc15b..f169b2b 100644 --- a/src/SparkFunBME280.h +++ b/src/SparkFunBME280.h @@ -224,7 +224,7 @@ class BME280 //Software reset routine void reset( void ); - void readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale = 0); + void readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t tempScale = 0); //Returns the values as floats. float readFloatPressure( void ); From 56e7ff4723ff19ba3438eeecf9a6ea39a06cb47c Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 9 May 2022 08:15:59 -0600 Subject: [PATCH 13/17] Update library.properties --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index bb3733d..4601130 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun BME280 -version=2.0.9 +version=2.0.10 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A library to drive the Bosch BME280 Altimeter and Pressure sensor From c42e78089d9cda457d616715b41c970e253c2acf Mon Sep 17 00:00:00 2001 From: SFEMark Date: Tue, 19 Sep 2023 14:53:45 -0600 Subject: [PATCH 14/17] Create add_issue_to_project.yml Adding issue tracking .yml file for issue tracking in GH Projects. --- .github/workflows/add_issue_to_project.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/add_issue_to_project.yml diff --git a/.github/workflows/add_issue_to_project.yml b/.github/workflows/add_issue_to_project.yml new file mode 100644 index 0000000..6b60cc3 --- /dev/null +++ b/.github/workflows/add_issue_to_project.yml @@ -0,0 +1,18 @@ +name: Add new issue to our main project + +on: + issues: + types: + - opened + +jobs: + add-to-project: + name: Add issue to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@main + with: + # You can target a project in a different organization + # to the issue + project-url: https://github.com/orgs/sparkfun/projects/19 + github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }} From 7569e49a4320f84daf3a543c5538140bb0b4bf43 Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sun, 5 Oct 2025 03:34:50 +0200 Subject: [PATCH 15/17] Support for SPIClass --- src/SparkFunBME280.cpp | 23 ++++++++++++----------- src/SparkFunBME280.h | 9 +++++---- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index dac7ab1..eccc076 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -7,7 +7,7 @@ May 20, 2015 Resources: Uses Wire.h for i2c operation -Uses SPI.h for SPI operation +Uses _spiPort->h for SPI operation Development environment specifics: Arduino IDE 1.8.5 @@ -87,7 +87,7 @@ uint8_t BME280::begin() case SPI_MODE: // start the SPI library: - SPI.begin(); + _spiPort->begin(); // initialize the data ready and chip select pins: pinMode(settings.chipSelectPin, OUTPUT); digitalWrite(settings.chipSelectPin, HIGH); @@ -138,8 +138,9 @@ uint8_t BME280::begin() } //Begin comm with BME280 over SPI -bool BME280::beginSPI(uint8_t csPin) +bool BME280::beginSPI(uint8_t csPin, SPIClass &spiPort) { + _spiPort = &spiPort; settings.chipSelectPin = csPin; settings.commInterface = SPI_MODE; @@ -691,21 +692,21 @@ void BME280::readRegisterRegion(uint8_t *outputPointer , uint8_t offset, uint8_t break; case SPI_MODE: - SPI.beginTransaction(settings.spiSettings); + _spiPort->beginTransaction(settings.spiSettings); // take the chip select low to select the device: digitalWrite(settings.chipSelectPin, LOW); // send the device the register you want to read: - SPI.transfer(offset | 0x80); //Ored with "read request" bit + _spiPort->transfer(offset | 0x80); //Ored with "read request" bit while ( i < length ) // slave may send less than requested { - c = SPI.transfer(0x00); // receive a byte as character + c = _spiPort->transfer(0x00); // receive a byte as character *outputPointer = c; outputPointer++; i++; } // take the chip select high to de-select: digitalWrite(settings.chipSelectPin, HIGH); - SPI.endTransaction(); + _spiPort->endTransaction(); break; default: @@ -799,17 +800,17 @@ void BME280::writeRegister(uint8_t offset, uint8_t dataToWrite) break; case SPI_MODE: - SPI.beginTransaction(settings.spiSettings); + _spiPort->beginTransaction(settings.spiSettings); // take the chip select low to select the device: digitalWrite(settings.chipSelectPin, LOW); // send the device the register you want to read: - SPI.transfer(offset & 0x7F); + _spiPort->transfer(offset & 0x7F); // send a value of 0 to read the first byte returned: - SPI.transfer(dataToWrite); + _spiPort->transfer(dataToWrite); // decrement the number of bytes left to read: // take the chip select high to de-select: digitalWrite(settings.chipSelectPin, HIGH); - SPI.endTransaction(); + _spiPort->endTransaction(); break; default: diff --git a/src/SparkFunBME280.h b/src/SparkFunBME280.h index f169b2b..af11c35 100644 --- a/src/SparkFunBME280.h +++ b/src/SparkFunBME280.h @@ -58,7 +58,7 @@ Distributed as-is; no warranty is given. #define BME280_SPI_MODE SPI_MODE0 #endif -#define NO_WIRE 0 +#define NO_WIRE nullptr #define HARD_WIRE 1 #define SOFT_WIRE 2 @@ -199,7 +199,7 @@ class BME280 //Call to apply BME280_SensorSettings. //This also gets the SensorCalibration constants uint8_t begin( void ); - bool beginSPI(uint8_t csPin); //Communicate using SPI + bool beginSPI(uint8_t csPin, SPIClass &spiPort=SPI); //Communicate using SPI bool beginI2C(TwoWire &wirePort = Wire); //Called when user provides Wire port #ifdef SoftwareWire_h @@ -265,10 +265,11 @@ class BME280 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 + TwoWire *_hardPort = nullptr; //The generic connection to user's chosen I2C hardware + SPIClass *_spiPort = &SPI; //The generic connection to user's chosen SPI hardware #ifdef SoftwareWire_h - SoftwareWire *_softPort = NO_WIRE; //Or, the generic connection to software wire port + SoftwareWire *_softPort = nullptr; //Or, the generic connection to software wire port #endif float _referencePressure = 101325.0; //Default but is changeable From d7f0b8c301cc1e2803cb423c2a973fc2a8a40330 Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sun, 5 Oct 2025 03:44:26 +0200 Subject: [PATCH 16/17] Undo changes to TwoWire --- src/SparkFunBME280.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SparkFunBME280.h b/src/SparkFunBME280.h index af11c35..d75ddce 100644 --- a/src/SparkFunBME280.h +++ b/src/SparkFunBME280.h @@ -58,7 +58,7 @@ Distributed as-is; no warranty is given. #define BME280_SPI_MODE SPI_MODE0 #endif -#define NO_WIRE nullptr +#define NO_WIRE 0 #define HARD_WIRE 1 #define SOFT_WIRE 2 @@ -265,11 +265,11 @@ class BME280 void readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); uint8_t _wireType = HARD_WIRE; //Default to Wire.h - TwoWire *_hardPort = nullptr; //The generic connection to user's chosen I2C hardware + TwoWire *_hardPort = NO_WIRE; //The generic connection to user's chosen I2C hardware SPIClass *_spiPort = &SPI; //The generic connection to user's chosen SPI hardware #ifdef SoftwareWire_h - SoftwareWire *_softPort = nullptr; //Or, the generic connection to software wire port + SoftwareWire *_softPort = NO_WIRE; //Or, the generic connection to software wire port #endif float _referencePressure = 101325.0; //Default but is changeable From 870c17da1f4c76561e14b8ffcc7cdffd63136e10 Mon Sep 17 00:00:00 2001 From: Elias Santistevan Date: Mon, 6 Oct 2025 09:29:08 -0600 Subject: [PATCH 17/17] Number of changes along with an accidental format changes, rolls version Fixes some code that didn't fit it's function, though operates simlarly Changes the name of some macros that were too generically named, causing conflicts with other libraries --- library.properties | 4 +- src/SparkFunBME280.cpp | 1192 ++++++++++++++++++++-------------------- src/SparkFunBME280.h | 363 ++++++------ 3 files changed, 792 insertions(+), 767 deletions(-) diff --git a/library.properties b/library.properties index 4601130..6f0f324 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=SparkFun BME280 -version=2.0.10 +version=2.0.11 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A library to drive the Bosch BME280 Altimeter and Pressure sensor paragraph=The SparkFun CCS811/BME280 Environmental Combo Breakout takes care of all your atmospheric-quality sensing needs with the popular CCS811 and BME280 ICs. This unique breakout provides a variety of environmental data, including barometric pressure, humidity, temperature, TVOCs and equivalent CO2 (or eCO2) levels. category=Sensors url=https://github.com/sparkfun/SparkFun_BME280_Arduino_Library -architectures=* \ No newline at end of file +architectures=* diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index eccc076..80e12c1 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -14,14 +14,14 @@ Arduino IDE 1.8.5 Teensy loader 1.23 This code is released under the [MIT License](http://opensource.org/licenses/MIT). -Please review the LICENSE.md file included with this example. If you have any questions +Please review the LICENSE.md file included with this example. If you have any questions or concerns with licensing, please contact techsupport@sparkfun.com. Distributed as-is; no warranty is given. ******************************************************************************/ -//See SparkFunBME280.h for additional topology notes. +// See SparkFunBME280.h for additional topology notes. -#include #include "SparkFunBME280.h" +#include //****************************************************************************// // @@ -29,333 +29,340 @@ Distributed as-is; no warranty is given. // //****************************************************************************// -//Constructor -- Specifies default configuration -BME280::BME280( void ) +// Constructor -- Specifies default configuration +BME280::BME280(void) { - //Construct with these default settings + // Construct with these default settings - settings.commInterface = I2C_MODE; //Default to I2C + settings.commInterface = kSfeI2CMode; // Default to I2C - settings.I2CAddress = 0x77; //Default, jumper open is 0x77 - _hardPort = &Wire; //Default to Wire port + settings.I2CAddress = 0x77; // Default, jumper open is 0x77 + _hardPort = &Wire; // Default to Wire port - settings.chipSelectPin = 10; //Select CS pin for SPI - - //These are deprecated settings - settings.runMode = 3; //Normal/Run - settings.tStandby = 0; //0.5ms - settings.filter = 0; //Filter off - settings.tempOverSample = 1; - settings.pressOverSample = 1; - settings.humidOverSample = 1; - settings.tempCorrection = 0.f; // correction of temperature - added to the result -} + settings.chipSelectPin = 10; // Select CS pin for SPI + // These are deprecated settings + settings.runMode = 3; // Normal/Run + settings.tStandby = 0; // 0.5ms + settings.filter = 0; // Filter off + settings.tempOverSample = 1; + settings.pressOverSample = 1; + settings.humidOverSample = 1; + settings.tempCorrection = 0.f; // correction of temperature - added to the result +} //****************************************************************************// // // Configuration section // // This uses the stored BME280_SensorSettings to start the IMU -// Use statements such as "mySensor.settings.commInterface = SPI_MODE;" to +// Use statements such as "mySensor.settings.commInterface = SPI_MODE;" to // configure before calling .begin(); // //****************************************************************************// uint8_t BME280::begin() { - delay(2); //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up. - - //Check the settings structure values to determine how to setup the device - switch (settings.commInterface) - { - - case I2C_MODE: - - //Removing port begin from library. This should be done by user otherwise this library will overwrite Wire settings such as clock speed. - // switch(_wireType) - // { - // case(HARD_WIRE): - // _hardPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise it can be hard to debug. - // break; - // case(SOFT_WIRE): - // #ifdef SoftwareWire_h - // _softPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise it can be hard to debug. - // #endif - // break; - // } - break; - - case SPI_MODE: - // start the SPI library: - _spiPort->begin(); - // initialize the data ready and chip select pins: - pinMode(settings.chipSelectPin, OUTPUT); - digitalWrite(settings.chipSelectPin, HIGH); - break; - - default: - break; - } - - //Check communication with IC before anything else - uint8_t chipID = readRegister(BME280_CHIP_ID_REG); //Should return 0x60 or 0x58 - if(chipID != 0x58 && chipID != 0x60) // Is this BMP or BME? - return(chipID); //This is not BMP nor BME! - - //Reading all compensation data, range 0x88:A1, 0xE1:E7 - calibration.dig_T1 = ((uint16_t)((readRegister(BME280_DIG_T1_MSB_REG) << 8) + readRegister(BME280_DIG_T1_LSB_REG))); - calibration.dig_T2 = ((int16_t)((readRegister(BME280_DIG_T2_MSB_REG) << 8) + readRegister(BME280_DIG_T2_LSB_REG))); - calibration.dig_T3 = ((int16_t)((readRegister(BME280_DIG_T3_MSB_REG) << 8) + readRegister(BME280_DIG_T3_LSB_REG))); - - calibration.dig_P1 = ((uint16_t)((readRegister(BME280_DIG_P1_MSB_REG) << 8) + readRegister(BME280_DIG_P1_LSB_REG))); - calibration.dig_P2 = ((int16_t)((readRegister(BME280_DIG_P2_MSB_REG) << 8) + readRegister(BME280_DIG_P2_LSB_REG))); - calibration.dig_P3 = ((int16_t)((readRegister(BME280_DIG_P3_MSB_REG) << 8) + readRegister(BME280_DIG_P3_LSB_REG))); - calibration.dig_P4 = ((int16_t)((readRegister(BME280_DIG_P4_MSB_REG) << 8) + readRegister(BME280_DIG_P4_LSB_REG))); - calibration.dig_P5 = ((int16_t)((readRegister(BME280_DIG_P5_MSB_REG) << 8) + readRegister(BME280_DIG_P5_LSB_REG))); - calibration.dig_P6 = ((int16_t)((readRegister(BME280_DIG_P6_MSB_REG) << 8) + readRegister(BME280_DIG_P6_LSB_REG))); - calibration.dig_P7 = ((int16_t)((readRegister(BME280_DIG_P7_MSB_REG) << 8) + readRegister(BME280_DIG_P7_LSB_REG))); - calibration.dig_P8 = ((int16_t)((readRegister(BME280_DIG_P8_MSB_REG) << 8) + readRegister(BME280_DIG_P8_LSB_REG))); - calibration.dig_P9 = ((int16_t)((readRegister(BME280_DIG_P9_MSB_REG) << 8) + readRegister(BME280_DIG_P9_LSB_REG))); - - calibration.dig_H1 = ((uint8_t)(readRegister(BME280_DIG_H1_REG))); - calibration.dig_H2 = ((int16_t)((readRegister(BME280_DIG_H2_MSB_REG) << 8) + readRegister(BME280_DIG_H2_LSB_REG))); - calibration.dig_H3 = ((uint8_t)(readRegister(BME280_DIG_H3_REG))); - calibration.dig_H4 = ((int16_t)((readRegister(BME280_DIG_H4_MSB_REG) << 4) + (readRegister(BME280_DIG_H4_LSB_REG) & 0x0F))); - calibration.dig_H5 = ((int16_t)((readRegister(BME280_DIG_H5_MSB_REG) << 4) + ((readRegister(BME280_DIG_H4_LSB_REG) >> 4) & 0x0F))); - calibration.dig_H6 = ((int8_t)readRegister(BME280_DIG_H6_REG)); - - //Most of the time the sensor will be init with default values - //But in case user has old/deprecated code, use the settings.x values - setStandbyTime(settings.tStandby); - setFilter(settings.filter); - setPressureOverSample(settings.pressOverSample); //Default of 1x oversample - setHumidityOverSample(settings.humidOverSample); //Default of 1x oversample - setTempOverSample(settings.tempOverSample); //Default of 1x oversample - - setMode(MODE_NORMAL); //Go! - - return(readRegister(BME280_CHIP_ID_REG)); //Should return 0x60 -} - -//Begin comm with BME280 over SPI + delay(2); // Make sure sensor had enough time to turn on. BME280 requires 2ms to start up. + + // Check the settings structure values to determine how to setup the device + switch (settings.commInterface) + { + + case kSfeI2CMode: + + // Removing port begin from library. This should be done by user otherwise this library will overwrite Wire + // settings such as clock speed. + // switch(_wireType) + // { + // case(HARD_WIRE): + // _hardPort->begin(); //The caller can begin their port and set the speed. We just confirm it here + // otherwise it can be hard to debug. break; case(SOFT_WIRE): #ifdef SoftwareWire_h + // _softPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise + // it can be hard to debug. #endif break; + // } + break; + + case kSfeSPIMode: + // start the SPI library: + _spiPort->begin(); + // initialize the data ready and chip select pins: + pinMode(settings.chipSelectPin, OUTPUT); + digitalWrite(settings.chipSelectPin, HIGH); + break; + + default: + break; + } + + // Check communication with IC before anything else + uint8_t chipID = readRegister(BME280_CHIP_ID_REG); // Should return 0x60 or 0x58 + if (chipID != 0x58 && chipID != 0x60) // Is this BMP or BME? + return (chipID); // This is not BMP nor BME! + + // Reading all compensation data, range 0x88:A1, 0xE1:E7 + calibration.dig_T1 = ((uint16_t)((readRegister(BME280_DIG_T1_MSB_REG) << 8) + readRegister(BME280_DIG_T1_LSB_REG))); + calibration.dig_T2 = ((int16_t)((readRegister(BME280_DIG_T2_MSB_REG) << 8) + readRegister(BME280_DIG_T2_LSB_REG))); + calibration.dig_T3 = ((int16_t)((readRegister(BME280_DIG_T3_MSB_REG) << 8) + readRegister(BME280_DIG_T3_LSB_REG))); + + calibration.dig_P1 = ((uint16_t)((readRegister(BME280_DIG_P1_MSB_REG) << 8) + readRegister(BME280_DIG_P1_LSB_REG))); + calibration.dig_P2 = ((int16_t)((readRegister(BME280_DIG_P2_MSB_REG) << 8) + readRegister(BME280_DIG_P2_LSB_REG))); + calibration.dig_P3 = ((int16_t)((readRegister(BME280_DIG_P3_MSB_REG) << 8) + readRegister(BME280_DIG_P3_LSB_REG))); + calibration.dig_P4 = ((int16_t)((readRegister(BME280_DIG_P4_MSB_REG) << 8) + readRegister(BME280_DIG_P4_LSB_REG))); + calibration.dig_P5 = ((int16_t)((readRegister(BME280_DIG_P5_MSB_REG) << 8) + readRegister(BME280_DIG_P5_LSB_REG))); + calibration.dig_P6 = ((int16_t)((readRegister(BME280_DIG_P6_MSB_REG) << 8) + readRegister(BME280_DIG_P6_LSB_REG))); + calibration.dig_P7 = ((int16_t)((readRegister(BME280_DIG_P7_MSB_REG) << 8) + readRegister(BME280_DIG_P7_LSB_REG))); + calibration.dig_P8 = ((int16_t)((readRegister(BME280_DIG_P8_MSB_REG) << 8) + readRegister(BME280_DIG_P8_LSB_REG))); + calibration.dig_P9 = ((int16_t)((readRegister(BME280_DIG_P9_MSB_REG) << 8) + readRegister(BME280_DIG_P9_LSB_REG))); + + calibration.dig_H1 = ((uint8_t)(readRegister(BME280_DIG_H1_REG))); + calibration.dig_H2 = ((int16_t)((readRegister(BME280_DIG_H2_MSB_REG) << 8) + readRegister(BME280_DIG_H2_LSB_REG))); + calibration.dig_H3 = ((uint8_t)(readRegister(BME280_DIG_H3_REG))); + calibration.dig_H4 = + ((int16_t)((readRegister(BME280_DIG_H4_MSB_REG) << 4) + (readRegister(BME280_DIG_H4_LSB_REG) & 0x0F))); + calibration.dig_H5 = + ((int16_t)((readRegister(BME280_DIG_H5_MSB_REG) << 4) + ((readRegister(BME280_DIG_H4_LSB_REG) >> 4) & 0x0F))); + calibration.dig_H6 = ((int8_t)readRegister(BME280_DIG_H6_REG)); + + // Most of the time the sensor will be init with default values + // But in case user has old/deprecated code, use the settings.x values + setStandbyTime(settings.tStandby); + setFilter(settings.filter); + setPressureOverSample(settings.pressOverSample); // Default of 1x oversample + setHumidityOverSample(settings.humidOverSample); // Default of 1x oversample + setTempOverSample(settings.tempOverSample); // Default of 1x oversample + + setMode(MODE_NORMAL); // Go! + + return (readRegister(BME280_CHIP_ID_REG)); // Should return 0x60 +} + +// Begin comm with BME280 over SPI bool BME280::beginSPI(uint8_t csPin, SPIClass &spiPort) { - _spiPort = &spiPort; - settings.chipSelectPin = csPin; - settings.commInterface = SPI_MODE; - - uint8_t chipID = begin(); + _spiPort = &spiPort; + settings.chipSelectPin = csPin; + settings.commInterface = kSfeSPIMode; + + uint8_t chipID = begin(); - if(chipID == 0x58) return(true); //Begin normal init with these settings. Should return chip ID of 0x58 for BMP - if(chipID == 0x60) return(true); //Begin normal init with these settings. Should return chip ID of 0x60 for BME - return(false); + if (chipID == 0x58) + return (true); // Begin normal init with these settings. Should return chip ID of 0x58 for BMP + if (chipID == 0x60) + return (true); // Begin normal init with these settings. Should return chip ID of 0x60 for BME + return (false); } -//Begin comm with BME280 over I2C +// Begin comm with BME280 over I2C bool BME280::beginI2C(TwoWire &wirePort) { - _hardPort = &wirePort; - _wireType = HARD_WIRE; + _hardPort = &wirePort; + _wireType = HARD_WIRE; - settings.commInterface = I2C_MODE; - //settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() + settings.commInterface = kSfeI2CMode; + // settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() - uint8_t chipID = begin(); + uint8_t chipID = begin(); - if(chipID == 0x58) return(true); //Begin normal init with these settings. Should return chip ID of 0x58 for BMP - if(chipID == 0x60) return(true); //Begin normal init with these settings. Should return chip ID of 0x60 for BME - return(false); + if (chipID == 0x58) + return (true); // Begin normal init with these settings. Should return chip ID of 0x58 for BMP + if (chipID == 0x60) + return (true); // Begin normal init with these settings. Should return chip ID of 0x60 for BME + return (false); } -//Begin comm with BME280 over software I2C +// Begin comm with BME280 over software I2C #ifdef SoftwareWire_h -bool BME280::beginI2C(SoftwareWire& wirePort) +bool BME280::beginI2C(SoftwareWire &wirePort) { - _softPort = &wirePort; - _wireType = SOFT_WIRE; + _softPort = &wirePort; + _wireType = SOFT_WIRE; - settings.commInterface = I2C_MODE; - //settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() + settings.commInterface = kSfeI2CMode; + // settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() - uint8_t chipID = begin(); + uint8_t chipID = begin(); - if(chipID == 0x58) return(true); //Begin normal init with these settings. Should return chip ID of 0x58 for BMP - if(chipID == 0x60) return(true); //Begin normal init with these settings. Should return chip ID of 0x60 for BME - return(false); + if (chipID == 0x58) + return (true); // Begin normal init with these settings. Should return chip ID of 0x58 for BMP + if (chipID == 0x60) + return (true); // Begin normal init with these settings. Should return chip ID of 0x60 for BME + return (false); } #endif -//Set the mode bits in the ctrl_meas register -// Mode 00 = Sleep -// 01 and 10 = Forced -// 11 = Normal mode +// Set the mode bits in the ctrl_meas register +// Mode 00 = Sleep +// 01 and 10 = Forced +// 11 = Normal mode void BME280::setMode(uint8_t mode) { - if(mode > 0b11) mode = 0; //Error check. Default to sleep mode - - uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); - controlData &= ~( (1<<1) | (1<<0) ); //Clear the mode[1:0] bits - controlData |= mode; //Set - writeRegister(BME280_CTRL_MEAS_REG, controlData); + if (mode > 0b11) + mode = 0; // Error check. Default to sleep mode + + uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); + controlData &= ~((1 << 1) | (1 << 0)); // Clear the mode[1:0] bits + controlData |= mode; // Set + writeRegister(BME280_CTRL_MEAS_REG, controlData); } -//Gets the current mode bits in the ctrl_meas register -//Mode 00 = Sleep -// 01 and 10 = Forced -// 11 = Normal mode +// Gets the current mode bits in the ctrl_meas register +// Mode 00 = Sleep +// 01 and 10 = Forced +// 11 = Normal mode uint8_t BME280::getMode() { - uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); - return(controlData & 0b00000011); //Clear bits 7 through 2 + uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); + return (controlData & 0b00000011); // Clear bits 7 through 2 } -//Set the standby bits in the config register -//tStandby can be: -// 0, 0.5ms -// 1, 62.5ms -// 2, 125ms -// 3, 250ms -// 4, 500ms -// 5, 1000ms -// 6, 10ms -// 7, 20ms +// Set the standby bits in the config register +// tStandby can be: +// 0, 0.5ms +// 1, 62.5ms +// 2, 125ms +// 3, 250ms +// 4, 500ms +// 5, 1000ms +// 6, 10ms +// 7, 20ms void BME280::setStandbyTime(uint8_t timeSetting) { - if(timeSetting > 0b111) timeSetting = 0; //Error check. Default to 0.5ms - - uint8_t controlData = readRegister(BME280_CONFIG_REG); - controlData &= ~( (1<<7) | (1<<6) | (1<<5) ); //Clear the 7/6/5 bits - controlData |= (timeSetting << 5); //Align with bits 7/6/5 - writeRegister(BME280_CONFIG_REG, controlData); -} - -//Set the filter bits in the config register -//filter can be off or number of FIR coefficients to use: -// 0, filter off -// 1, coefficients = 2 -// 2, coefficients = 4 -// 3, coefficients = 8 -// 4, coefficients = 16 + if (timeSetting > 0b111) + timeSetting = 0; // Error check. Default to 0.5ms + + uint8_t controlData = readRegister(BME280_CONFIG_REG); + controlData &= ~((1 << 7) | (1 << 6) | (1 << 5)); // Clear the 7/6/5 bits + controlData |= (timeSetting << 5); // Align with bits 7/6/5 + writeRegister(BME280_CONFIG_REG, controlData); +} + +// Set the filter bits in the config register +// filter can be off or number of FIR coefficients to use: +// 0, filter off +// 1, coefficients = 2 +// 2, coefficients = 4 +// 3, coefficients = 8 +// 4, coefficients = 16 void BME280::setFilter(uint8_t filterSetting) { - if(filterSetting > 0b111) filterSetting = 0; //Error check. Default to filter off - - uint8_t controlData = readRegister(BME280_CONFIG_REG); - controlData &= ~( (1<<4) | (1<<3) | (1<<2) ); //Clear the 4/3/2 bits - controlData |= (filterSetting << 2); //Align with bits 4/3/2 - writeRegister(BME280_CONFIG_REG, controlData); + if (filterSetting > 0b111) + filterSetting = 0; // Error check. Default to filter off + + uint8_t controlData = readRegister(BME280_CONFIG_REG); + controlData &= ~((1 << 4) | (1 << 3) | (1 << 2)); // Clear the 4/3/2 bits + controlData |= (filterSetting << 2); // Align with bits 4/3/2 + writeRegister(BME280_CONFIG_REG, controlData); } -//Set the temperature oversample value -//0 turns off temp sensing -//1 to 16 are valid over sampling values +// Set the temperature oversample value +// 0 turns off temp sensing +// 1 to 16 are valid over sampling values void BME280::setTempOverSample(uint8_t overSampleAmount) { - overSampleAmount = checkSampleValue(overSampleAmount); //Error check - - uint8_t originalMode = getMode(); //Get the current mode so we can go back to it at the end - - setMode(MODE_SLEEP); //Config will only be writeable in sleep mode, so first go to sleep mode + overSampleAmount = checkSampleValue(overSampleAmount); // Error check - //Set the osrs_t bits (7, 6, 5) to overSampleAmount - uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); - controlData &= ~( (1<<7) | (1<<6) | (1<<5) ); //Clear bits 765 - controlData |= overSampleAmount << 5; //Align overSampleAmount to bits 7/6/5 - writeRegister(BME280_CTRL_MEAS_REG, controlData); - - setMode(originalMode); //Return to the original user's choice + uint8_t originalMode = getMode(); // Get the current mode so we can go back to it at the end + + setMode(MODE_SLEEP); // Config will only be writeable in sleep mode, so first go to sleep mode + + // Set the osrs_t bits (7, 6, 5) to overSampleAmount + uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); + controlData &= ~((1 << 7) | (1 << 6) | (1 << 5)); // Clear bits 765 + controlData |= overSampleAmount << 5; // Align overSampleAmount to bits 7/6/5 + writeRegister(BME280_CTRL_MEAS_REG, controlData); + + setMode(originalMode); // Return to the original user's choice } -//Set the pressure oversample value -//0 turns off pressure sensing -//1 to 16 are valid over sampling values +// Set the pressure oversample value +// 0 turns off pressure sensing +// 1 to 16 are valid over sampling values void BME280::setPressureOverSample(uint8_t overSampleAmount) { - overSampleAmount = checkSampleValue(overSampleAmount); //Error check - - uint8_t originalMode = getMode(); //Get the current mode so we can go back to it at the end - - setMode(MODE_SLEEP); //Config will only be writeable in sleep mode, so first go to sleep mode + overSampleAmount = checkSampleValue(overSampleAmount); // Error check + + uint8_t originalMode = getMode(); // Get the current mode so we can go back to it at the end + + setMode(MODE_SLEEP); // Config will only be writeable in sleep mode, so first go to sleep mode + + // Set the osrs_p bits (4, 3, 2) to overSampleAmount + uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); + controlData &= ~((1 << 4) | (1 << 3) | (1 << 2)); // Clear bits 432 + controlData |= overSampleAmount << 2; // Align overSampleAmount to bits 4/3/2 + writeRegister(BME280_CTRL_MEAS_REG, controlData); - //Set the osrs_p bits (4, 3, 2) to overSampleAmount - uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); - controlData &= ~( (1<<4) | (1<<3) | (1<<2) ); //Clear bits 432 - controlData |= overSampleAmount << 2; //Align overSampleAmount to bits 4/3/2 - writeRegister(BME280_CTRL_MEAS_REG, controlData); - - setMode(originalMode); //Return to the original user's choice + setMode(originalMode); // Return to the original user's choice } -//Set the humidity oversample value -//0 turns off humidity sensing -//1 to 16 are valid over sampling values +// Set the humidity oversample value +// 0 turns off humidity sensing +// 1 to 16 are valid over sampling values void BME280::setHumidityOverSample(uint8_t overSampleAmount) { - overSampleAmount = checkSampleValue(overSampleAmount); //Error check - - uint8_t originalMode = getMode(); //Get the current mode so we can go back to it at the end - - setMode(MODE_SLEEP); //Config will only be writeable in sleep mode, so first go to sleep mode + overSampleAmount = checkSampleValue(overSampleAmount); // Error check - //Set the osrs_h bits (2, 1, 0) to overSampleAmount - uint8_t controlData = readRegister(BME280_CTRL_HUMIDITY_REG); - controlData &= ~( (1<<2) | (1<<1) | (1<<0) ); //Clear bits 2/1/0 - controlData |= overSampleAmount << 0; //Align overSampleAmount to bits 2/1/0 - writeRegister(BME280_CTRL_HUMIDITY_REG, controlData); + uint8_t originalMode = getMode(); // Get the current mode so we can go back to it at the end - setMode(originalMode); //Return to the original user's choice + setMode(MODE_SLEEP); // Config will only be writeable in sleep mode, so first go to sleep mode + + // Set the osrs_h bits (2, 1, 0) to overSampleAmount + uint8_t controlData = readRegister(BME280_CTRL_HUMIDITY_REG); + controlData &= ~((1 << 2) | (1 << 1) | (1 << 0)); // Clear bits 2/1/0 + controlData |= overSampleAmount << 0; // Align overSampleAmount to bits 2/1/0 + writeRegister(BME280_CTRL_HUMIDITY_REG, controlData); + + setMode(originalMode); // Return to the original user's choice } -//Validates an over sample value -//Allowed values are 0 to 16 -//These are used in the humidty, pressure, and temp oversample functions +// Validates an over sample value +// Allowed values are 0 to 16 +// These are used in the humidty, pressure, and temp oversample functions uint8_t BME280::checkSampleValue(uint8_t userValue) { - switch(userValue) - { - case(0): - return 0; - break; //Valid - case(1): - return 1; - break; //Valid - case(2): - return 2; - break; //Valid - case(4): - return 3; - break; //Valid - case(8): - return 4; - break; //Valid - case(16): - return 5; - break; //Valid - default: - return 1; //Default to 1x - break; //Good - } -} - -//Set the global setting for the I2C address we want to communicate with -//Default is 0x77 + switch (userValue) + { + case (0): + return 0; + break; // Valid + case (1): + return 1; + break; // Valid + case (2): + return 2; + break; // Valid + case (4): + return 3; + break; // Valid + case (8): + return 4; + break; // Valid + case (16): + return 5; + break; // Valid + default: + return 1; // Default to 1x + break; // Good + } +} + +// Set the global setting for the I2C address we want to communicate with +// Default is 0x77 void BME280::setI2CAddress(uint8_t address) { - settings.I2CAddress = address; //Set the I2C address for this device + settings.I2CAddress = address; // Set the I2C address for this device } -//Check the measuring bit and return true while device is taking measurement +// Check the measuring bit and return true while device is taking measurement bool BME280::isMeasuring(void) { - uint8_t stat = readRegister(BME280_STAT_REG); - return(stat & (1<<3)); //If the measuring bit (3) is set, return true + uint8_t stat = readRegister(BME280_STAT_REG); + return (stat & (1 << 3)); // If the measuring bit (3) is set, return true } -//Strictly resets. Run .begin() afterwards -void BME280::reset( void ) +// Strictly resets. Run .begin() afterwards +void BME280::reset(void) { - writeRegister(BME280_RST_REG, 0xB6); - + writeRegister(BME280_RST_REG, 0xB6); } //****************************************************************************// @@ -364,21 +371,25 @@ void BME280::reset( void ) // //****************************************************************************// -//Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout -//tempScale = 0 for Celsius scale (default setting) -//tempScale = 1 for Fahrenheit scale -void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t 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); +// Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout +// tempScale = 0 for Celsius scale (default setting) +// tempScale = 1 for Fahrenheit scale +void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t 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); } //****************************************************************************// @@ -386,65 +397,64 @@ void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_ // Pressure Section // //****************************************************************************// -float BME280::readFloatPressure( void ) +float BME280::readFloatPressure(void) { - // Returns 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 + // Returns 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 uint8_t buffer[3]; - readRegisterRegion(buffer, BME280_PRESSURE_MSB_REG, 3); + readRegisterRegion(buffer, BME280_PRESSURE_MSB_REG, 3); 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) - { - return 0; // avoid exception caused by division by zero - } - 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); - - return (float)p_acc / 256.0; - + + 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) + { + return 0; // avoid exception caused by division by zero + } + 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); + + return (float)p_acc / 256.0; } 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; - } + // 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. @@ -456,38 +466,37 @@ void BME280::readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasureme // "sea level pressure"value from a trusted source like NOAA. void BME280::setReferencePressure(float refPressure) { - _referencePressure = refPressure; + _referencePressure = refPressure; } -//Return the local reference pressure +// Return the local reference pressure float BME280::getReferencePressure() { - return(_referencePressure); + return (_referencePressure); } -float BME280::readFloatAltitudeMeters( void ) +float BME280::readFloatAltitudeMeters(void) { - float heightOutput = 0; - - // Getting height from a pressure reading is called the "international barometric height formula". - // The magic value of 44330.77 was adjusted in issue #30. - // There's also some discussion of it here: https://www.sparkfun.com/tutorials/253 - // This calculation is NOT designed to work on non-Earthlike planets such as Mars or Venus; - // see NRLMSISE-00. That's why it is the "international" formula, not "interplanetary". - // Sparkfun is not liable for incorrect altitude calculations from this - // code on those planets. Interplanetary selfies are welcome, however. - heightOutput = ((float)-44330.77)*(pow(((float)readFloatPressure()/(float)_referencePressure), 0.190263) - (float)1); //Corrected, see issue 30 - return heightOutput; - + float heightOutput = 0; + + // Getting height from a pressure reading is called the "international barometric height formula". + // The magic value of 44330.77 was adjusted in issue #30. + // There's also some discussion of it here: https://www.sparkfun.com/tutorials/253 + // This calculation is NOT designed to work on non-Earthlike planets such as Mars or Venus; + // see NRLMSISE-00. That's why it is the "international" formula, not "interplanetary". + // Sparkfun is not liable for incorrect altitude calculations from this + // code on those planets. Interplanetary selfies are welcome, however. + heightOutput = ((float)-44330.77) * (pow(((float)readFloatPressure() / (float)_referencePressure), 0.190263) - + (float)1); // Corrected, see issue 30 + return heightOutput; } -float BME280::readFloatAltitudeFeet( void ) +float BME280::readFloatAltitudeFeet(void) { - float heightOutput = 0; - - heightOutput = readFloatAltitudeMeters() * 3.28084; - return heightOutput; - + float heightOutput = 0; + + heightOutput = readFloatAltitudeMeters() * 3.28084; + return heightOutput; } //****************************************************************************// @@ -495,44 +504,58 @@ float BME280::readFloatAltitudeFeet( void ) // Humidity Section // //****************************************************************************// -float BME280::readFloatHumidity( void ) +float BME280::readFloatHumidity(void) { - - // Returns 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 + + // Returns 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 uint8_t buffer[2]; - readRegisterRegion(buffer, BME280_HUMIDITY_MSB_REG, 2); + readRegisterRegion(buffer, BME280_HUMIDITY_MSB_REG, 2); int32_t adc_H = ((uint32_t)buffer[0] << 8) | ((uint32_t)buffer[1]); - - 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); - return (float)(var1>>12) / 1024.0; + 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); + + 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; + // 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; } //****************************************************************************// @@ -543,70 +566,72 @@ void BME280::readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasureme void BME280::setTemperatureCorrection(float corr) { - settings.tempCorrection = corr; + settings.tempCorrection = corr; } -float BME280::readTempC( void ) +float BME280::readTempC(void) { - // Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. - // t_fine carries fine temperature as global value + // Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. + // t_fine carries fine temperature as global value - //get the reading (adc_T); + // get the reading (adc_T); uint8_t buffer[3]; - readRegisterRegion(buffer, BME280_TEMPERATURE_MSB_REG, 3); + readRegisterRegion(buffer, BME280_TEMPERATURE_MSB_REG, 3); int32_t adc_T = ((uint32_t)buffer[0] << 12) | ((uint32_t)buffer[1] << 4) | ((buffer[2] >> 4) & 0x0F); - //By datasheet, calibrate - int64_t var1, var2; + // 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; - 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; - output = output / 100 + settings.tempCorrection; - - return output; + 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); + 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; + // 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; + 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; + output = output / 100 + settings.tempCorrection; + + return output; } void BME280::readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) { - measurements->temperature = readTempFromBurst(buffer); + measurements->temperature = readTempFromBurst(buffer); } -float BME280::readTempF( void ) +float BME280::readTempF(void) { - float output = readTempC(); - output = (output * 9) / 5 + 32; + float output = readTempC(); + output = (output * 9) / 5 + 32; - return output; + return output; } void BME280::readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) { - float output = readTempFromBurst(buffer); - output = (output * 9) / 5 + 32; + float output = readTempFromBurst(buffer); + output = (output * 9) / 5 + 32; - measurements->temperature = output; + measurements->temperature = output; } //****************************************************************************// @@ -617,26 +642,26 @@ void BME280::readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *mea // Returns Dew point in DegC double BME280::dewPointC(void) { - double celsius = readTempC(); - double humidity = readFloatHumidity(); - // (1) Saturation Vapor Pressure = ESGG(T) - double RATIO = 373.15 / (273.15 + celsius); - double RHS = -7.90298 * (RATIO - 1); - RHS += 5.02808 * log10(RATIO); - RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO ))) - 1) ; - RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ; - RHS += log10(1013.246); - // factor -3 is to adjust units - Vapor Pressure SVP * humidity - double VP = pow(10, RHS - 3) * humidity; - // (2) DEWPOINT = F(Vapor Pressure) - double T = log(VP/0.61078); // temp var - return (241.88 * T) / (17.558 - T); + double celsius = readTempC(); + double humidity = readFloatHumidity(); + // (1) Saturation Vapor Pressure = ESGG(T) + double RATIO = 373.15 / (273.15 + celsius); + double RHS = -7.90298 * (RATIO - 1); + RHS += 5.02808 * log10(RATIO); + RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1 / RATIO))) - 1); + RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1); + RHS += log10(1013.246); + // factor -3 is to adjust units - Vapor Pressure SVP * humidity + double VP = pow(10, RHS - 3) * humidity; + // (2) DEWPOINT = F(Vapor Pressure) + double T = log(VP / 0.61078); // temp var + return (241.88 * T) / (17.558 - T); } // Returns Dew point in DegF double BME280::dewPointF(void) { - return(dewPointC() * 1.8 + 32); //Convert C to F + return (dewPointC() * 1.8 + 32); // Convert C to F } //****************************************************************************// @@ -644,176 +669,177 @@ double BME280::dewPointF(void) // Utility // //****************************************************************************// -void BME280::readRegisterRegion(uint8_t *outputPointer , uint8_t offset, uint8_t length) -{ - //define pointer that will point to the external space - uint8_t i = 0; - char c = 0; - - switch (settings.commInterface) - { - - case I2C_MODE: - switch(_wireType) - { - case(HARD_WIRE): - _hardPort->beginTransmission(settings.I2CAddress); - _hardPort->write(offset); - _hardPort->endTransmission(); - - // request bytes from slave device - _hardPort->requestFrom(settings.I2CAddress, length); - while ( (_hardPort->available()) && (i < length)) // slave may send less than requested - { - c = _hardPort->read(); // receive a byte as character - *outputPointer = c; - outputPointer++; - i++; - } - break; - case(SOFT_WIRE): - #ifdef SoftwareWire_h - _softPort->beginTransmission(settings.I2CAddress); - _softPort->write(offset); - _softPort->endTransmission(); - - // request bytes from slave device - _softPort->requestFrom(settings.I2CAddress, length); - while ( (_softPort->available()) && (i < length)) // slave may send less than requested - { - c = _softPort->read(); // receive a byte as character - *outputPointer = c; - outputPointer++; - i++; - } - #endif - break; - } - break; - - case SPI_MODE: - _spiPort->beginTransaction(settings.spiSettings); - // take the chip select low to select the device: - digitalWrite(settings.chipSelectPin, LOW); - // send the device the register you want to read: - _spiPort->transfer(offset | 0x80); //Ored with "read request" bit - while ( i < length ) // slave may send less than requested - { - c = _spiPort->transfer(0x00); // receive a byte as character - *outputPointer = c; - outputPointer++; - i++; - } - // take the chip select high to de-select: - digitalWrite(settings.chipSelectPin, HIGH); - _spiPort->endTransaction(); - break; - - default: - break; - } - +void BME280::readRegisterRegion(uint8_t *outputPointer, uint8_t offset, uint8_t length) +{ + // define pointer that will point to the external space + uint8_t i = 0; + char c = 0; + + switch (settings.commInterface) + { + + case kSfeI2CMode: + switch (_wireType) + { + case (HARD_WIRE): + _hardPort->beginTransmission(settings.I2CAddress); + _hardPort->write(offset); + _hardPort->endTransmission(); + + // request bytes from slave device + _hardPort->requestFrom(settings.I2CAddress, length); + while ((_hardPort->available()) && (i < length)) // slave may send less than requested + { + c = _hardPort->read(); // receive a byte as character + *outputPointer = c; + outputPointer++; + i++; + } + break; + case (SOFT_WIRE): +#ifdef SoftwareWire_h + _softPort->beginTransmission(settings.I2CAddress); + _softPort->write(offset); + _softPort->endTransmission(); + + // request bytes from slave device + _softPort->requestFrom(settings.I2CAddress, length); + while ((_softPort->available()) && (i < length)) // slave may send less than requested + { + c = _softPort->read(); // receive a byte as character + *outputPointer = c; + outputPointer++; + i++; + } +#endif + break; + } + break; + + case kSfeSPIMode: + _spiPort->beginTransaction(settings.spiSettings); + // take the chip select low to select the device: + digitalWrite(settings.chipSelectPin, LOW); + // send the device the register you want to read: + _spiPort->transfer(offset | 0x80); // Ored with "read request" bit + while (i < length) // slave may send less than requested + { + c = _spiPort->transfer(0x00); // receive a byte as character + *outputPointer = c; + outputPointer++; + i++; + } + // take the chip select high to de-select: + digitalWrite(settings.chipSelectPin, HIGH); + _spiPort->endTransaction(); + break; + + default: + break; + } } uint8_t BME280::readRegister(uint8_t offset) { - //Return value - uint8_t result = 0; - uint8_t numBytes = 1; - switch (settings.commInterface) { - - case I2C_MODE: - switch(_wireType) - { - case(HARD_WIRE): - _hardPort->beginTransmission(settings.I2CAddress); - _hardPort->write(offset); - _hardPort->endTransmission(); - - _hardPort->requestFrom(settings.I2CAddress, numBytes); - while ( _hardPort->available() ) // slave may send less than requested - { - result = _hardPort->read(); // receive a byte as a proper uint8_t - } - break; - - case(SOFT_WIRE): - #ifdef SoftwareWire_h - _softPort->beginTransmission(settings.I2CAddress); - _softPort->write(offset); - _softPort->endTransmission(); - - _softPort->requestFrom(settings.I2CAddress, numBytes); - while ( _softPort->available() ) // slave may send less than requested - { - result = _softPort->read(); // receive a byte as a proper uint8_t - } - #endif - break; - } - - break; - - case SPI_MODE: - readRegisterRegion(&result, offset, 1); - break; - - default: - break; - } - return result; -} - -int16_t BME280::readRegisterInt16( uint8_t offset ) -{ - uint8_t myBuffer[2]; - readRegisterRegion(myBuffer, offset, 2); //Does memory transfer - int16_t output = (int16_t)myBuffer[0] | int16_t(myBuffer[1] << 8); - - return output; + // Return value + uint8_t result = 0; + uint8_t numBytes = 1; + uint8_t bytesAvailable; + switch (settings.commInterface) + { + + case kSfeI2CMode: + switch (_wireType) + { + case (HARD_WIRE): + _hardPort->beginTransmission(settings.I2CAddress); + _hardPort->write(offset); + _hardPort->endTransmission(); + + bytesAvailable = _hardPort->requestFrom(settings.I2CAddress, numBytes); + if (bytesAvailable == numBytes) + { + result = _hardPort->read(); + } + break; + + case (SOFT_WIRE): +#ifdef SoftwareWire_h + _softPort->beginTransmission(settings.I2CAddress); + _softPort->write(offset); + _softPort->endTransmission(); + + bytesAvailable = _softPort->requestFrom(settings.I2CAddress, numBytes); + if (bytesAvailable == numBytes) + { + result = _softPort->read(); + } +#endif + break; + } + + break; + + case kSfeSPIMode: + readRegisterRegion(&result, offset, 1); + break; + + default: + break; + } + return result; +} + +int16_t BME280::readRegisterInt16(uint8_t offset) +{ + uint8_t myBuffer[2]; + readRegisterRegion(myBuffer, offset, 2); // Does memory transfer + int16_t output = (int16_t)myBuffer[0] | int16_t(myBuffer[1] << 8); + + return output; } void BME280::writeRegister(uint8_t offset, uint8_t dataToWrite) { - switch (settings.commInterface) - { - case I2C_MODE: - //Write the byte - - switch(_wireType) - { - case(HARD_WIRE): - _hardPort->beginTransmission(settings.I2CAddress); - _hardPort->write(offset); - _hardPort->write(dataToWrite); - _hardPort->endTransmission(); - break; - case(SOFT_WIRE): - #ifdef SoftwareWire_h - _softPort->beginTransmission(settings.I2CAddress); - _softPort->write(offset); - _softPort->write(dataToWrite); - _softPort->endTransmission(); - #endif - break; - } - break; - - case SPI_MODE: - _spiPort->beginTransaction(settings.spiSettings); - // take the chip select low to select the device: - digitalWrite(settings.chipSelectPin, LOW); - // send the device the register you want to read: - _spiPort->transfer(offset & 0x7F); - // send a value of 0 to read the first byte returned: - _spiPort->transfer(dataToWrite); - // decrement the number of bytes left to read: - // take the chip select high to de-select: - digitalWrite(settings.chipSelectPin, HIGH); - _spiPort->endTransaction(); - break; - - default: - break; - } + switch (settings.commInterface) + { + case kSfeI2CMode: + // Write the byte + + switch (_wireType) + { + case (HARD_WIRE): + _hardPort->beginTransmission(settings.I2CAddress); + _hardPort->write(offset); + _hardPort->write(dataToWrite); + _hardPort->endTransmission(); + break; + case (SOFT_WIRE): +#ifdef SoftwareWire_h + _softPort->beginTransmission(settings.I2CAddress); + _softPort->write(offset); + _softPort->write(dataToWrite); + _softPort->endTransmission(); +#endif + break; + } + break; + + case kSfeSPIMode: + _spiPort->beginTransaction(settings.spiSettings); + // take the chip select low to select the device: + digitalWrite(settings.chipSelectPin, LOW); + // send the device the register you want to read: + _spiPort->transfer(offset & 0x7F); + // send a value of 0 to read the first byte returned: + _spiPort->transfer(dataToWrite); + // decrement the number of bytes left to read: + // take the chip select high to de-select: + digitalWrite(settings.chipSelectPin, HIGH); + _spiPort->endTransaction(); + break; + + default: + break; + } } diff --git a/src/SparkFunBME280.h b/src/SparkFunBME280.h index d75ddce..89debc2 100644 --- a/src/SparkFunBME280.h +++ b/src/SparkFunBME280.h @@ -14,14 +14,14 @@ Arduino IDE 1.6.4 Teensy loader 1.23 This code is released under the [MIT License](http://opensource.org/licenses/MIT). -Please review the LICENSE.md file included with this example. If you have any questions +Please review the LICENSE.md file included with this example. If you have any questions or concerns with licensing, please contact techsupport@sparkfun.com. Distributed as-is; no warranty is given. TODO: - roll library ver to 2.0 - remove hard wire. - write escalating examples + roll library ver to 2.0 + remove hard wire. + write escalating examples ******************************************************************************/ @@ -36,15 +36,15 @@ Distributed as-is; no warranty is given. #include "WProgram.h" #endif -#include #include +#include -//Uncomment the following line to enable software I2C -//You will need to have the SoftwareWire library installed -//#include //SoftwareWire by Testato. Installed from library manager. +// Uncomment the following line to enable software I2C +// You will need to have the SoftwareWire library installed +// #include //SoftwareWire by Testato. Installed from library manager. -#define I2C_MODE 0 -#define SPI_MODE 1 +#define kSfeI2CMode 0 +#define kSfeSPIMode 1 #ifndef BME280_SPI_CLOCK #ifdef ARDUINO_ARCH_ESP32 @@ -66,213 +66,212 @@ Distributed as-is; no warranty is given. #define MODE_FORCED 0b01 #define MODE_NORMAL 0b11 -//Register names: -#define BME280_DIG_T1_LSB_REG 0x88 -#define BME280_DIG_T1_MSB_REG 0x89 -#define BME280_DIG_T2_LSB_REG 0x8A -#define BME280_DIG_T2_MSB_REG 0x8B -#define BME280_DIG_T3_LSB_REG 0x8C -#define BME280_DIG_T3_MSB_REG 0x8D -#define BME280_DIG_P1_LSB_REG 0x8E -#define BME280_DIG_P1_MSB_REG 0x8F -#define BME280_DIG_P2_LSB_REG 0x90 -#define BME280_DIG_P2_MSB_REG 0x91 -#define BME280_DIG_P3_LSB_REG 0x92 -#define BME280_DIG_P3_MSB_REG 0x93 -#define BME280_DIG_P4_LSB_REG 0x94 -#define BME280_DIG_P4_MSB_REG 0x95 -#define BME280_DIG_P5_LSB_REG 0x96 -#define BME280_DIG_P5_MSB_REG 0x97 -#define BME280_DIG_P6_LSB_REG 0x98 -#define BME280_DIG_P6_MSB_REG 0x99 -#define BME280_DIG_P7_LSB_REG 0x9A -#define BME280_DIG_P7_MSB_REG 0x9B -#define BME280_DIG_P8_LSB_REG 0x9C -#define BME280_DIG_P8_MSB_REG 0x9D -#define BME280_DIG_P9_LSB_REG 0x9E -#define BME280_DIG_P9_MSB_REG 0x9F -#define BME280_DIG_H1_REG 0xA1 -#define BME280_CHIP_ID_REG 0xD0 //Chip ID -#define BME280_RST_REG 0xE0 //Softreset Reg -#define BME280_DIG_H2_LSB_REG 0xE1 -#define BME280_DIG_H2_MSB_REG 0xE2 -#define BME280_DIG_H3_REG 0xE3 -#define BME280_DIG_H4_MSB_REG 0xE4 -#define BME280_DIG_H4_LSB_REG 0xE5 -#define BME280_DIG_H5_MSB_REG 0xE6 -#define BME280_DIG_H6_REG 0xE7 -#define BME280_CTRL_HUMIDITY_REG 0xF2 //Ctrl Humidity Reg -#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 -#define BME280_TEMPERATURE_MSB_REG 0xFA //Temperature MSB -#define BME280_TEMPERATURE_LSB_REG 0xFB //Temperature LSB -#define BME280_TEMPERATURE_XLSB_REG 0xFC //Temperature XLSB -#define BME280_HUMIDITY_MSB_REG 0xFD //Humidity MSB -#define BME280_HUMIDITY_LSB_REG 0xFE //Humidity LSB - -//Class BME280_SensorSettings. This object is used to hold settings data. The application -//uses this classes' data directly. The settings are adopted and sent to the sensor -//at special times, such as .begin. Some are used for doing math. +// Register names: +#define BME280_DIG_T1_LSB_REG 0x88 +#define BME280_DIG_T1_MSB_REG 0x89 +#define BME280_DIG_T2_LSB_REG 0x8A +#define BME280_DIG_T2_MSB_REG 0x8B +#define BME280_DIG_T3_LSB_REG 0x8C +#define BME280_DIG_T3_MSB_REG 0x8D +#define BME280_DIG_P1_LSB_REG 0x8E +#define BME280_DIG_P1_MSB_REG 0x8F +#define BME280_DIG_P2_LSB_REG 0x90 +#define BME280_DIG_P2_MSB_REG 0x91 +#define BME280_DIG_P3_LSB_REG 0x92 +#define BME280_DIG_P3_MSB_REG 0x93 +#define BME280_DIG_P4_LSB_REG 0x94 +#define BME280_DIG_P4_MSB_REG 0x95 +#define BME280_DIG_P5_LSB_REG 0x96 +#define BME280_DIG_P5_MSB_REG 0x97 +#define BME280_DIG_P6_LSB_REG 0x98 +#define BME280_DIG_P6_MSB_REG 0x99 +#define BME280_DIG_P7_LSB_REG 0x9A +#define BME280_DIG_P7_MSB_REG 0x9B +#define BME280_DIG_P8_LSB_REG 0x9C +#define BME280_DIG_P8_MSB_REG 0x9D +#define BME280_DIG_P9_LSB_REG 0x9E +#define BME280_DIG_P9_MSB_REG 0x9F +#define BME280_DIG_H1_REG 0xA1 +#define BME280_CHIP_ID_REG 0xD0 // Chip ID +#define BME280_RST_REG 0xE0 // Softreset Reg +#define BME280_DIG_H2_LSB_REG 0xE1 +#define BME280_DIG_H2_MSB_REG 0xE2 +#define BME280_DIG_H3_REG 0xE3 +#define BME280_DIG_H4_MSB_REG 0xE4 +#define BME280_DIG_H4_LSB_REG 0xE5 +#define BME280_DIG_H5_MSB_REG 0xE6 +#define BME280_DIG_H6_REG 0xE7 +#define BME280_CTRL_HUMIDITY_REG 0xF2 // Ctrl Humidity Reg +#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 +#define BME280_TEMPERATURE_MSB_REG 0xFA // Temperature MSB +#define BME280_TEMPERATURE_LSB_REG 0xFB // Temperature LSB +#define BME280_TEMPERATURE_XLSB_REG 0xFC // Temperature XLSB +#define BME280_HUMIDITY_MSB_REG 0xFD // Humidity MSB +#define BME280_HUMIDITY_LSB_REG 0xFE // Humidity LSB + +// Class BME280_SensorSettings. This object is used to hold settings data. The application +// uses this classes' data directly. The settings are adopted and sent to the sensor +// at special times, such as .begin. Some are used for doing math. // -//This is a kind of bloated way to do this. The trade-off is that the user doesn't -//need to deal with #defines or enums with bizarre names. +// This is a kind of bloated way to do this. The trade-off is that the user doesn't +// need to deal with #defines or enums with bizarre names. // -//A power user would strip out BME280_SensorSettings entirely, and send specific read and -//write command directly to the IC. (ST #defines below) +// A power user would strip out BME280_SensorSettings entirely, and send specific read and +// write command directly to the IC. (ST #defines below) // struct BME280_SensorSettings { public: - - //Main Interface and mode settings + // Main Interface and mode settings uint8_t commInterface; uint8_t I2CAddress; uint8_t chipSelectPin; - SPISettings spiSettings{BME280_SPI_CLOCK, MSBFIRST, BME280_SPI_MODE}; - - //Deprecated settings - uint8_t runMode; - uint8_t tStandby; - uint8_t filter; - uint8_t tempOverSample; - uint8_t pressOverSample; - uint8_t humidOverSample; + SPISettings spiSettings{BME280_SPI_CLOCK, MSBFIRST, BME280_SPI_MODE}; + + // Deprecated settings + uint8_t runMode; + uint8_t tStandby; + uint8_t filter; + uint8_t tempOverSample; + uint8_t pressOverSample; + uint8_t humidOverSample; float tempCorrection; // correction of temperature - added to the result }; -//Used to hold the calibration constants. These are used -//by the driver as measurements are being taking +// Used to hold the calibration constants. These are used +// by the driver as measurements are being taking struct SensorCalibration { public: - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; - - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; - - uint8_t dig_H1; - int16_t dig_H2; - uint8_t dig_H3; - int16_t dig_H4; - int16_t dig_H5; - int8_t dig_H6; - + uint16_t dig_T1; + int16_t dig_T2; + int16_t dig_T3; + + uint16_t dig_P1; + int16_t dig_P2; + int16_t dig_P3; + int16_t dig_P4; + int16_t dig_P5; + int16_t dig_P6; + int16_t dig_P7; + int16_t dig_P8; + int16_t dig_P9; + + uint8_t dig_H1; + int16_t dig_H2; + uint8_t dig_H3; + int16_t dig_H4; + int16_t dig_H5; + int8_t dig_H6; }; struct BME280_SensorMeasurements { public: - float temperature; - float pressure; - float humidity; + float temperature; + float pressure; + float humidity; }; -//This is the main operational class of the driver. +// This is the main operational class of the driver. class BME280 { public: - //settings + // settings BME280_SensorSettings settings; - SensorCalibration calibration; - int32_t t_fine; - - //Constructor generates default BME280_SensorSettings. - //(over-ride after construction if desired) - BME280( void ); + SensorCalibration calibration; + int32_t t_fine; + + // Constructor generates default BME280_SensorSettings. + //(over-ride after construction if desired) + BME280(void); //~BME280() = default; - - //Call to apply BME280_SensorSettings. - //This also gets the SensorCalibration constants - uint8_t begin( void ); - bool beginSPI(uint8_t csPin, SPIClass &spiPort=SPI); //Communicate using SPI - bool beginI2C(TwoWire &wirePort = Wire); //Called when user provides Wire port - - #ifdef SoftwareWire_h - bool beginI2C(SoftwareWire &wirePort); //Called when user provides a softwareWire port - #endif - - uint8_t getMode(void); //Get the current mode: sleep, forced, or normal - void setMode(uint8_t mode); //Set the current mode - - void setTempOverSample(uint8_t overSampleAmount); //Set the temperature sample mode - void setPressureOverSample(uint8_t overSampleAmount); //Set the pressure sample mode - void setHumidityOverSample(uint8_t overSampleAmount); //Set the humidity sample mode - void setStandbyTime(uint8_t timeSetting); //Set the standby time between measurements - void setFilter(uint8_t filterSetting); //Set the filter - - void setI2CAddress(uint8_t i2caddress); //Set the address the library should use to communicate. Use if address jumper is closed (0x76). - - void setReferencePressure(float refPressure); //Allows user to set local sea level reference pressure - float getReferencePressure(); - - bool isMeasuring(void); //Returns true while the device is taking measurement - - //Software reset routine - void reset( void ); - void readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t 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 + + // Call to apply BME280_SensorSettings. + // This also gets the SensorCalibration constants + uint8_t begin(void); + bool beginSPI(uint8_t csPin, SPIClass &spiPort = SPI); // Communicate using SPI + bool beginI2C(TwoWire &wirePort = Wire); // Called when user provides Wire port + +#ifdef SoftwareWire_h + bool beginI2C(SoftwareWire &wirePort); // Called when user provides a softwareWire port +#endif + + uint8_t getMode(void); // Get the current mode: sleep, forced, or normal + void setMode(uint8_t mode); // Set the current mode + + void setTempOverSample(uint8_t overSampleAmount); // Set the temperature sample mode + void setPressureOverSample(uint8_t overSampleAmount); // Set the pressure sample mode + void setHumidityOverSample(uint8_t overSampleAmount); // Set the humidity sample mode + void setStandbyTime(uint8_t timeSetting); // Set the standby time between measurements + void setFilter(uint8_t filterSetting); // Set the filter + + void setI2CAddress(uint8_t i2caddress); // Set the address the library should use to communicate. Use if address + // jumper is closed (0x76). + + void setReferencePressure(float refPressure); // Allows user to set local sea level reference pressure + float getReferencePressure(); + + bool isMeasuring(void); // Returns true while the device is taking measurement + + // Software reset routine + void reset(void); + void readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t 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[]); + 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 + // Dewpoint related methods + // From Pavel-Sayekat: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/pull/6/files double dewPointC(void); double dewPointF(void); - - //The following utilities read and write - //ReadRegisterRegion takes a uint8 array address as input and reads - //a chunk of memory into that array. - void readRegisterRegion(uint8_t*, uint8_t, uint8_t ); - //readRegister reads one register + // The following utilities read and write + + // ReadRegisterRegion takes a uint8 array address as input and reads + // a chunk of memory into that array. + void readRegisterRegion(uint8_t *, uint8_t, uint8_t); + // readRegister reads one register uint8_t readRegister(uint8_t); - //Reads two regs, LSByte then MSByte order, and concatenates them - //Used for two-byte reads - int16_t readRegisterInt16( uint8_t offset ); - //Writes a byte; + // Reads two regs, LSByte then MSByte order, and concatenates them + // Used for two-byte reads + int16_t readRegisterInt16(uint8_t offset); + // Writes a byte; void writeRegister(uint8_t, uint8_t); -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 - SPIClass *_spiPort = &SPI; //The generic connection to user's chosen SPI hardware - - #ifdef SoftwareWire_h - SoftwareWire *_softPort = NO_WIRE; //Or, the generic connection to software wire port - #endif - - float _referencePressure = 101325.0; //Default but is changeable + 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 + SPIClass *_spiPort = &SPI; // The generic connection to user's chosen SPI hardware + +#ifdef SoftwareWire_h + SoftwareWire *_softPort = NO_WIRE; // Or, the generic connection to software wire port +#endif + + float _referencePressure = 101325.0; // Default but is changeable }; -#endif // End of __BME280_H__ definition check +#endif // End of __BME280_H__ definition check