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 }} diff --git a/README.md b/README.md index d4a523a..3f3fc4b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -SparkFun Arduino Library +SparkFun BME280 Arduino Library ======================================== -![SparkFun BME280 Breakout](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/blob/master/readme_picture.jpg) +![SparkFun BME280 Breakout](https://cdn.sparkfun.com//assets/parts/1/2/3/2/9/14348-01.jpg) -[*SparkFun BME280 (SEN-13676)*](https://www.sparkfun.com/products/13676) +[*SparkFun CCS811/BME280 Combo (SEN-14348)*](https://www.sparkfun.com/products/14348) This library allows the user to: @@ -19,6 +19,12 @@ It also provides the following mathematical functions based from the above. 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 ------------------- @@ -32,12 +38,17 @@ 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. -* **[Hookup Guide](https://learn.sparkfun.com/tutorials/bme280-breakout-hookup-guide)** - Basic hookup guide 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) Version History @@ -46,6 +57,8 @@ Version History * [V_1.0.0](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/tree/V_1.0.0) - Public release. * [V_1.1.0](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/tree/V_1.1.0) - Pulled request to add decimal precision to readFloatPressure() and readFloatHumidity(). * [V_1.2.0](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/tree/V_1.2.0) - Added ESP32 architecture directives to modify begin operation. +* [V_2.0.0](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/tree/V_2.0.0) - Major update. Generalized wire port. Functionalized oversampling, standby time, etc. Added setMode. + License Information ------------------- diff --git a/examples/CSV_Output/CSV_Output.ino b/examples/CSV_Output/CSV_Output.ino deleted file mode 100644 index 1c26c37..0000000 --- a/examples/CSV_Output/CSV_Output.ino +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************************** -CSV_Output.ino -BME280 Arduino and Teensy example -Marshall Taylor @ SparkFun Electronics -May 20, 2015 -https://github.com/sparkfun/SparkFun_BME280_Arduino_Library - -This sketch configures two BME280 to produce comma separated values for use -in generating spreadsheet graphs. -in 10 being used for chip select. - -Resources: -Uses Wire.h for I2C operation -Uses SPI.h for SPI operation - -Development environment specifics: -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 -or concerns with licensing, please contact techsupport@sparkfun.com. -Distributed as-is; no warranty is given. -******************************************************************************/ - -#include -#include "SparkFunBME280.h" - -#include "Wire.h" -#include "SPI.h" - -//Global sensor object -BME280 mySensor; - -unsigned int sampleNumber = 0; //For counting number of CSV rows - -void setup() -{ - //***Driver settings********************************// - //commInterface can be I2C_MODE or SPI_MODE - //specify chipSelectPin using arduino pin names - //specify I2C address. Can be 0x77(default) or 0x76 - - //For I2C, enable the following and disable the SPI section - mySensor.settings.commInterface = I2C_MODE; - mySensor.settings.I2CAddress = 0x77; - - //For SPI enable the following and dissable the I2C section - //mySensor.settings.commInterface = SPI_MODE; - //mySensor.settings.chipSelectPin = 10; - - - //***Operation settings*****************************// - mySensor.settings.runMode = 3; // 3, Normal mode - mySensor.settings.tStandby = 0; // 0, 0.5ms - mySensor.settings.filter = 0; // 0, filter off - //tempOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.tempOverSample = 1; - //pressOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.pressOverSample = 1; - //humidOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.humidOverSample = 1; - - Serial.begin(57600); - Serial.print("Program Started\n"); - Serial.print("Starting BME280... result of .begin(): 0x"); - delay(10); //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up. - //Calling .begin() causes the settings to be loaded - Serial.println(mySensor.begin(), HEX); - - //Build a first-row of column headers - Serial.print("\n\n"); - Serial.print("Sample,"); - Serial.print("T(deg C),"); - Serial.print("T(deg F),"); - Serial.print("P(Pa),"); - Serial.print("Alt(m),"); - Serial.print("Alt(ft),"); - Serial.print("%RH"); - Serial.println(""); - -} - -void loop() -{ - - //Print each row in the loop - //Start with temperature, as that data is needed for accurate compensation. - //Reading the temperature updates the compensators of the other functions - //in the background. - Serial.print(sampleNumber); - Serial.print(","); - Serial.print(mySensor.readTempC(), 2); - Serial.print(","); - Serial.print(mySensor.readTempF(), 3); - Serial.print(","); - Serial.print(mySensor.readFloatPressure(), 0); - Serial.print(","); - Serial.print(mySensor.readFloatAltitudeMeters(), 3); - Serial.print(","); - Serial.print(mySensor.readFloatAltitudeFeet(), 3); - Serial.print(","); - Serial.print(mySensor.readFloatHumidity(), 0); - Serial.println(); - - sampleNumber++; - - delay(50); - -} diff --git a/examples/Example10_DewPoint/Example10_DewPoint.ino b/examples/Example10_DewPoint/Example10_DewPoint.ino new file mode 100644 index 0000000..fa0781b --- /dev/null +++ b/examples/Example10_DewPoint/Example10_DewPoint.ino @@ -0,0 +1,54 @@ +/* + Calculating dewpoint on the BME280 + Nathan Seidle @ SparkFun Electronics + November 3rd, 2018 + + 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 calculate dew point based on humidity and temperature. + Comes from Pavel-Sayekat: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/pull/6 + + Hardware connections: + BME280 -> Arduino + GND -> GND + 3.3 -> 3.3 + SDA -> A4 + SCL -> A5 +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(115200); + Serial.println("Example showing dewpoint calculation"); + + mySensor.setI2CAddress(0x76); //Connect to a second sensor + if (mySensor.beginI2C() == false) Serial.println("Sensor connect failed"); +} + +void loop() +{ + Serial.print("Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.print(" Dewpoint: "); + //Serial.print(mySensor.dewPointC(), 2); + Serial.print(mySensor.dewPointF(), 2); + + Serial.println(); + + delay(50); +} diff --git a/examples/Example11_BurstRead/Example11_BurstRead.ino b/examples/Example11_BurstRead/Example11_BurstRead.ino new file mode 100644 index 0000000..6e94e7f --- /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(115200); + 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/examples/Example1_BasicReadings/Example1_BasicReadings.ino b/examples/Example1_BasicReadings/Example1_BasicReadings.ino new file mode 100644 index 0000000..3fe99c4 --- /dev/null +++ b/examples/Example1_BasicReadings/Example1_BasicReadings.ino @@ -0,0 +1,60 @@ +/* + Get basic environmental readings from the BME280 + By: Nathan Seidle + SparkFun Electronics + Date: March 9th, 2018 + 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. + + Hardware connections: + BME280 -> Arduino + GND -> GND + 3.3 -> 3.3 + SDA -> A4 + SCL -> A5 +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(115200); + Serial.println("Reading basic values from BME280"); + + 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() +{ + Serial.print("Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Alt: "); + //Serial.print(mySensor.readFloatAltitudeMeters(), 1); + Serial.print(mySensor.readFloatAltitudeFeet(), 1); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.println(); + + delay(50); +} diff --git a/examples/Example2_I2CAddress/Example2_I2CAddress.ino b/examples/Example2_I2CAddress/Example2_I2CAddress.ino new file mode 100644 index 0000000..7d97120 --- /dev/null +++ b/examples/Example2_I2CAddress/Example2_I2CAddress.ino @@ -0,0 +1,71 @@ +/* + Communicate with BME280s with different I2C addresses + Nathan Seidle @ SparkFun Electronics + March 23, 2015 + + 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 connect two sensors on the same I2C bus. + + The BME280 has two I2C addresses: 0x77 (jumper open) or 0x76 (jumper closed) + + Hardware connections: + BME280 -> Arduino + GND -> GND + 3.3 -> 3.3 + SDA -> A4 + SCL -> A5 +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensorA; //Uses default I2C address 0x77 +BME280 mySensorB; //Uses I2C address 0x76 (jumper closed) + +void setup() +{ + Serial.begin(115200); + Serial.println("Example showing alternate I2C addresses"); + + Wire.begin(); + + mySensorA.setI2CAddress(0x77); //The default for the SparkFun Environmental Combo board is 0x77 (jumper open). + //If you close the jumper it is 0x76 + //The I2C address must be set before .begin() otherwise the cal values will fail to load. + + if(mySensorA.beginI2C() == false) Serial.println("Sensor A connect failed"); + + mySensorB.setI2CAddress(0x76); //Connect to a second sensor + if(mySensorB.beginI2C() == false) Serial.println("Sensor B connect failed"); +} + +void loop() +{ + Serial.print("HumidityA: "); + Serial.print(mySensorA.readFloatHumidity(), 0); + + Serial.print(" PressureA: "); + Serial.print(mySensorA.readFloatPressure(), 0); + + Serial.print(" TempA: "); + //Serial.print(mySensorA.readTempC(), 2); + Serial.print(mySensorA.readTempF(), 2); + + Serial.print(" HumidityB: "); + Serial.print(mySensorB.readFloatHumidity(), 0); + + Serial.print(" PressureB: "); + Serial.print(mySensorB.readFloatPressure(), 0); + + Serial.print(" TempB: "); + //Serial.print(mySensorB.readTempC(), 2); + Serial.print(mySensorB.readTempF(), 2); + + Serial.println(); + + delay(50); +} + diff --git a/examples/Example3_CSVOutput/Example3_CSVOutput.ino b/examples/Example3_CSVOutput/Example3_CSVOutput.ino new file mode 100644 index 0000000..cb34eff --- /dev/null +++ b/examples/Example3_CSVOutput/Example3_CSVOutput.ino @@ -0,0 +1,72 @@ +/* + Output all readings in CSV format + BME280 Arduino and Teensy example + Marshall Taylor @ SparkFun Electronics + May 20, 2015 + https://github.com/sparkfun/SparkFun_BME280_Arduino_Library + + This sketch outputs BME280 data in comma separated values for generating spreadsheet graphs. + + 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 +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +unsigned long sampleNumber = 0; + +void setup() +{ + Serial.begin(115200); + + Wire.begin(); + + if (mySensor.beginI2C() == false) //Begin communication over I2C + { + Serial.println("The sensor did not respond. Please check wiring."); + while(1); //Freeze + } + + //Build a first-row of column headers + Serial.print("SampleNumber,"); + Serial.print("Time(ms),"); + Serial.print("T(deg C),"); + Serial.print("T(deg F),"); + Serial.print("P(Pa),"); + Serial.print("Alt(m),"); + Serial.print("Alt(ft),"); + Serial.print("%RH"); + Serial.println(""); +} + +void loop() +{ + //Print each row in the loop + //Start with temperature, as that data is needed for accurate compensation. + //Reading the temperature updates the compensators of the other functions + //in the background. + Serial.print(sampleNumber); + Serial.print(","); + Serial.print(millis()); + Serial.print(","); + Serial.print(mySensor.readTempC(), 2); + Serial.print(","); + Serial.print(mySensor.readTempF(), 3); + Serial.print(","); + Serial.print(mySensor.readFloatPressure(), 0); + Serial.print(","); + Serial.print(mySensor.readFloatAltitudeMeters(), 3); + Serial.print(","); + Serial.print(mySensor.readFloatAltitudeFeet(), 3); + Serial.print(","); + Serial.print(mySensor.readFloatHumidity(), 0); + Serial.println(); + + sampleNumber++; + + delay(50); +} diff --git a/examples/Example4_Settings/Example4_Settings.ino b/examples/Example4_Settings/Example4_Settings.ino new file mode 100644 index 0000000..f51b795 --- /dev/null +++ b/examples/Example4_Settings/Example4_Settings.ino @@ -0,0 +1,58 @@ +/* + Control the various settings of the BME280 + Nathan Seidle @ SparkFun Electronics + March 23, 2018 + + 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 set the various filter, and oversample settings of the BME280. +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(115200); + Serial.println("Example showing alternate I2C addresses"); + + Wire.begin(); + Wire.setClock(400000); //Increase to fast I2C speed! + + mySensor.beginI2C(); + + mySensor.setFilter(1); //0 to 4 is valid. Filter coefficient. See 3.4.4 + mySensor.setStandbyTime(0); //0 to 7 valid. Time between readings. See table 27. + + mySensor.setTempOverSample(1); //0 to 16 are valid. 0 disables temp sensing. See table 24. + mySensor.setPressureOverSample(1); //0 to 16 are valid. 0 disables pressure sensing. See table 23. + mySensor.setHumidityOverSample(1); //0 to 16 are valid. 0 disables humidity sensing. See table 19. + + mySensor.setMode(MODE_NORMAL); //MODE_SLEEP, MODE_FORCED, MODE_NORMAL is valid. See 3.3 +} + +void loop() +{ + Serial.print("Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Alt: "); + //Serial.print(mySensor.readFloatAltitudeMeters(), 1); + Serial.print(mySensor.readFloatAltitudeFeet(), 1); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.println(); + + delay(50); +} + diff --git a/examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino b/examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino new file mode 100644 index 0000000..85acc6a --- /dev/null +++ b/examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino @@ -0,0 +1,147 @@ +/* + Read all the regigsters of the BME280 + BME280 Arduino and Teensy example + Marshall Taylor @ SparkFun Electronics + May 20, 2015 + + 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 outputs all the functional registers from the BME280. This can be handy + for troubleshooting. + + This sketch configures the BME280 to read all measurements. The sketch also + displays the BME280's physical memory and what the driver perceives the + calibration words to be. +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(115200); + while(!Serial); //Needed for printing correctly when using a Teensy + Serial.println("Reading all registers from BME280"); + + Wire.begin(); + + if (mySensor.beginI2C() == false) //Begin communication over I2C + { + Serial.println("The sensor did not respond. Please check wiring."); + while (1); //Freeze + } + + Serial.print("ID(0xD0): "); + printyPrintHex(mySensor.readRegister(BME280_CHIP_ID_REG)); + + Serial.print("Reset register(0xE0): "); + printyPrintHex(mySensor.readRegister(BME280_RST_REG)); + + Serial.print("ctrl_meas(0xF4): "); + printyPrintHex(mySensor.readRegister(BME280_CTRL_MEAS_REG)); + + Serial.print("ctrl_hum(0xF2): "); + printyPrintHex(mySensor.readRegister(BME280_CTRL_HUMIDITY_REG)); + + Serial.println(); + + Serial.println("Displaying all regs:"); + byte memCounter = 0x80; + for (byte row = 8 ; row < 16 ; row++) + { + Serial.print("0x"); + Serial.print(row, HEX); + Serial.print("0:"); + + for (byte column = 0 ; column < 16 ; column++) + { + byte tempReadData = mySensor.readRegister(memCounter); + + if(tempReadData < 0x10) Serial.print("0"); + Serial.print(tempReadData, HEX); + Serial.print(" "); + + memCounter++; + } + Serial.println(); + } + + Serial.println(); + + Serial.println("Displaying concatenated calibration words:"); + Serial.print("dig_T1, uint16: "); + Serial.println(mySensor.calibration.dig_T1); + Serial.print("dig_T2, int16: "); + Serial.println(mySensor.calibration.dig_T2); + Serial.print("dig_T3, int16: "); + Serial.println(mySensor.calibration.dig_T3); + + Serial.print("dig_P1, uint16: "); + Serial.println(mySensor.calibration.dig_P1); + Serial.print("dig_P2, int16: "); + Serial.println(mySensor.calibration.dig_P2); + Serial.print("dig_P3, int16: "); + Serial.println(mySensor.calibration.dig_P3); + Serial.print("dig_P4, int16: "); + Serial.println(mySensor.calibration.dig_P4); + Serial.print("dig_P5, int16: "); + Serial.println(mySensor.calibration.dig_P5); + Serial.print("dig_P6, int16: "); + Serial.println(mySensor.calibration.dig_P6); + Serial.print("dig_P7, int16: "); + Serial.println(mySensor.calibration.dig_P7); + Serial.print("dig_P8, int16: "); + Serial.println(mySensor.calibration.dig_P8); + Serial.print("dig_P9, int16: "); + Serial.println(mySensor.calibration.dig_P9); + + Serial.print("dig_H1, uint8: "); + Serial.println(mySensor.calibration.dig_H1); + Serial.print("dig_H2, int16: "); + Serial.println(mySensor.calibration.dig_H2); + Serial.print("dig_H3, uint8: "); + Serial.println(mySensor.calibration.dig_H3); + Serial.print("dig_H4, int16: "); + Serial.println(mySensor.calibration.dig_H4); + Serial.print("dig_H5, int16: "); + Serial.println(mySensor.calibration.dig_H5); + Serial.print("dig_H6, int8: "); + Serial.println(mySensor.calibration.dig_H6); + + Serial.println(); +} + +void loop() +{ + //Each loop, take a reading. + Serial.print("Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Alt: "); + //Serial.print(mySensor.readFloatAltitudeMeters(), 1); + Serial.print(mySensor.readFloatAltitudeFeet(), 1); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.println(); + + delay(1000); +} + +//Given a value, print it in HEX with leading 0x and any leading 0s +void printyPrintHex(byte value) +{ + Serial.print("0x"); + if (value < 0x10) Serial.print("0"); + Serial.println(value, HEX); +} + diff --git a/examples/Example6_LowPower/Example6_LowPower.ino b/examples/Example6_LowPower/Example6_LowPower.ino new file mode 100644 index 0000000..c42abe8 --- /dev/null +++ b/examples/Example6_LowPower/Example6_LowPower.ino @@ -0,0 +1,64 @@ +/* + Put the BME280 into low power mode (aka Forced Read) + Nathan Seidle @ SparkFun Electronics + March 23, 2018 + + 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 used the 'Forced Mode' to obtain a reading then put the + sensor to sleep between readings. +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(115200); + Serial.println("Example showing alternate I2C addresses"); + + Wire.begin(); + Wire.setClock(400000); //Increase to fast I2C speed! + + mySensor.beginI2C(); + + mySensor.setMode(MODE_SLEEP); //Sleep for now +} + +void loop() +{ + mySensor.setMode(MODE_FORCED); //Wake up sensor and take reading + + long startTime = millis(); + while(mySensor.isMeasuring() == false) ; //Wait for sensor to start measurment + while(mySensor.isMeasuring() == true) ; //Hang out while sensor completes the reading + long endTime = millis(); + + //Sensor is now back asleep but we get get the data + + Serial.print(" Measure time(ms): "); + Serial.print(endTime - startTime); + + Serial.print(" Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Alt: "); + //Serial.print(mySensor.readFloatAltitudeMeters(), 1); + Serial.print(mySensor.readFloatAltitudeFeet(), 1); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.println(); + + delay(1000); +} + diff --git a/examples/SketchesWithLCD/LCD_DeltaAltitude/CircularBuffer.cpp b/examples/Example7_RelativeAltitudeChange/CircularBuffer.cpp similarity index 99% rename from examples/SketchesWithLCD/LCD_DeltaAltitude/CircularBuffer.cpp rename to examples/Example7_RelativeAltitudeChange/CircularBuffer.cpp index 13acf55..da528d5 100644 --- a/examples/SketchesWithLCD/LCD_DeltaAltitude/CircularBuffer.cpp +++ b/examples/Example7_RelativeAltitudeChange/CircularBuffer.cpp @@ -101,4 +101,4 @@ float CircularBuffer::averageLast( uint16_t numElements ) uint16_t CircularBuffer::recordLength( void ) { return cBufferElementsUsed; -} \ No newline at end of file +} diff --git a/examples/SketchesWithLCD/LCD_DeltaAltitude/CircularBuffer.h b/examples/Example7_RelativeAltitudeChange/CircularBuffer.h similarity index 96% rename from examples/SketchesWithLCD/LCD_DeltaAltitude/CircularBuffer.h rename to examples/Example7_RelativeAltitudeChange/CircularBuffer.h index bc30840..f6efde0 100644 --- a/examples/SketchesWithLCD/LCD_DeltaAltitude/CircularBuffer.h +++ b/examples/Example7_RelativeAltitudeChange/CircularBuffer.h @@ -30,4 +30,4 @@ class CircularBuffer -#endif // CIRCULARBUFFER_H \ No newline at end of file +#endif // CIRCULARBUFFER_H diff --git a/examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino b/examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino new file mode 100644 index 0000000..586ed2d --- /dev/null +++ b/examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino @@ -0,0 +1,118 @@ +/* + Change the local altitude reference + BME280 Arduino and Teensy example + Marshall Taylor @ SparkFun Electronics + v1.1 by Nathan Seidle @ SparkFun Electronics + May 20, 2015 + https://github.com/sparkfun/SparkFun_BME280_Arduino_Library + + 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 sketch configures a BME280 to measure height changes, with a button + to zero the local relative altitude. + + To use, run the sketch then press a button on the keyboard. The data on the + serial monitor will show zero. Then, move the sensor to a new altitude and watch + how the output changes! + + Note: For most accurate results keep the sensor orientation and temperature the + same between measurements. + + 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 + or concerns with licensing, please contact techsupport@sparkfun.com. + Distributed as-is; no warranty is given. +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +#include "CircularBuffer.h" + +//This is a fixed-size buffer used for averaging data, a software LP filter +//Depending on the settings, the response can be quite slow. +CircularBuffer myBuffer(50); + +float localAltitude = 0; + +void setup() +{ + 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"); + + Wire.begin(); + + if (mySensor.beginI2C() == false) //Begin communication over I2C + { + Serial.println("The sensor did not respond. Please check wiring."); + while (1); //Freeze + } + + //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 + mySensor.setFilter(4); //Lots of HW filter + + //tempOverSample can be: + // 0, skipped + // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively + mySensor.setTempOverSample(5); //Set oversample to 16 + + //pressOverSample can be: + // 0, skipped + // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively + mySensor.setPressureOverSample(5); //Set oversample to 16 + + //humidOverSample can be: + // 0, skipped + // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively + mySensor.setHumidityOverSample(0); //Turn off humidity sensing + + //Assume the current reading is where we should start + localAltitude = mySensor.readFloatAltitudeFeet(); //Set reference altitude + + for(int x = 0 ; x < 50 ; x++) + myBuffer.pushElement(0); //Clear buffer +} + +void loop() +{ + //Get the local temperature! Do this for calibration + mySensor.readTempC(); + + //Check to see if user pressed a button + if (Serial.available() == true) + { + localAltitude = mySensor.readFloatAltitudeFeet(); //Set reference altitude + + for(int x = 0 ; x < 50 ; x++) + myBuffer.pushElement(0); //Clear buffer + + Serial.read(); //Remove keypress from buffer + Serial.println("Local altitude reset"); + } + + float reading = mySensor.readFloatAltitudeFeet(); + myBuffer.pushElement(reading - localAltitude); + + float tempAlt = myBuffer.averageLast(15); //Do an average of the latest samples + + Serial.print("Last sample: "); + Serial.print(reading, 2); + Serial.print(" ft"); + + Serial.print(" Last 15 samples averaged: "); + Serial.print(tempAlt); + Serial.print(" ft"); + Serial.println(); + delay(200); +} diff --git a/examples/Example8_LocalPressure/Example8_LocalPressure.ino b/examples/Example8_LocalPressure/Example8_LocalPressure.ino new file mode 100644 index 0000000..552be86 --- /dev/null +++ b/examples/Example8_LocalPressure/Example8_LocalPressure.ino @@ -0,0 +1,59 @@ +/* + Adjust the local Reference Pressure + Nathan Seidle @ SparkFun Electronics + March 23, 2018 + + 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 + + 'Sea level' pressure changes with high and low pressure weather movement. + This sketch demonstrates how to change sea level 101325Pa to a different value. + See Issue 1: https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/issues/1 + + Google 'sea level pressure map' for more information: + http://weather.unisys.com/surface/sfc_con.php?image=pr&inv=0&t=cur + https://www.atmos.illinois.edu/weather/tree/viewer.pl?launch/sfcslp + + 29.92 inHg = 1.0 atm = 101325 Pa = 1013.25 mb +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(115200); + Serial.println("Example showing alternate I2C addresses"); + + Wire.begin(); + Wire.setClock(400000); //Increase to fast I2C speed! + + mySensor.beginI2C(); + + mySensor.setReferencePressure(101200); //Adjust the sea level pressure used for altitude calculations +} + +void loop() +{ + Serial.print("Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Locally Adjusted Altitude: "); + //Serial.print(mySensor.readFloatAltitudeMeters(), 1); + Serial.print(mySensor.readFloatAltitudeFeet(), 1); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.println(); + + delay(50); +} + diff --git a/examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino b/examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino new file mode 100644 index 0000000..f47d0b1 --- /dev/null +++ b/examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino @@ -0,0 +1,57 @@ +/* + Communicate with BME280s using Software I2C + Nathan Seidle @ SparkFun Electronics + March 23, 2015 + + 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 connect to sensors using the SoftwareWire library. + + This is an advanced example. You'll need to edit the SparkFunBME280.h file + and uncomment the #include line to enable Software I2C. + + Since we're using software I2C we can use almost any pins. For this example the + hardware connections: + BME280 -> Arduino + GND -> GND + 3.3 -> 3.3 + SDA -> 6 + SCL -> 7 +*/ + +#include //SoftwareWire by Testato. Installed from library manager. + +//We use pins 6 and 7 in this example but others can be used +SoftwareWire myWire(6, 7); //SDA, SCL + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(115200); + Serial.println("Example showing alternate I2C addresses"); + + myWire.begin(); + if(mySensor.beginI2C(myWire) == false) Serial.println("Sensor A connect failed"); +} + +void loop() +{ + Serial.print("Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.println(); + + delay(50); +} + diff --git a/examples/I2C_DeltaAltitude/I2C_DeltaAltitude.ino b/examples/I2C_DeltaAltitude/I2C_DeltaAltitude.ino deleted file mode 100644 index 43c1b5e..0000000 --- a/examples/I2C_DeltaAltitude/I2C_DeltaAltitude.ino +++ /dev/null @@ -1,170 +0,0 @@ -/****************************************************************************** -I2C_DeltaAltitude.ino -BME280 Arduino and Teensy example -Marshall Taylor @ SparkFun Electronics -May 20, 2015 -https://github.com/sparkfun/SparkFun_BME280_Arduino_Library - -This sketch configures a BME280 to measure height changes, with a button -to zero relative altitude. - -Hardware connections: -BME280 -> Arduino -GND -> GND -3.3 -> 3.3 -SDA -> A4 -SCL -> A5 - -Button (Normally open) between A4 and A5. - -To use, run the sketch then press and hold the button until the data on the -serial monitor shows zero. Then, move the sensor to a new altitude and watch -how the output changes! - -Note: For most accurate results keep the sensor orientation and temperature the -same between measurements. - -Resources: -Uses Wire.h for I2C operation -Uses SPI.h for SPI operation -Included CircularBuffer class for averaging - -Development environment specifics: -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 -or concerns with licensing, please contact techsupport@sparkfun.com. -Distributed as-is; no warranty is given. -******************************************************************************/ - -#include -#include "SparkFunBME280.h" -#include "CircularBuffer.h" - -#include "Wire.h" -#include "SPI.h" - -//Global sensor object -BME280 mySensor; -uint8_t buttonGroundPin = A0; -uint8_t buttonSensePin = A2; - -//This is a fixed-size buffer used for averaging data, a software LP filter -//Depending on the settings, the response can be quite slow. -CircularBuffer myBuffer(50); - -float reference = 0; - -void setup() -{ - //Configure the button IO - pinMode( buttonSensePin, INPUT_PULLUP ); - pinMode( buttonGroundPin, OUTPUT ); - digitalWrite( buttonGroundPin, 0 ); - - //***Driver settings********************************// - //commInterface can be I2C_MODE or SPI_MODE - //specify chipSelectPin using arduino pin names - //specify I2C address. Can be 0x77(default) or 0x76 - - //For I2C, enable the following and disable the SPI section - mySensor.settings.commInterface = I2C_MODE; - mySensor.settings.I2CAddress = 0x77; - - //For SPI enable the following and dissable the I2C section - //mySensor.settings.commInterface = SPI_MODE; - //mySensor.settings.chipSelectPin = 10; - - - //***Operation settings*****************************// - - //renMode can be: - // 0, Sleep mode - // 1 or 2, Forced mode - // 3, Normal mode - mySensor.settings.runMode = 3; //Normal mode - - //tStandby can be: - // 0, 0.5ms - // 1, 62.5ms - // 2, 125ms - // 3, 250ms - // 4, 500ms - // 5, 1000ms - // 6, 10ms - // 7, 20ms - mySensor.settings.tStandby = 0; - - //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 - mySensor.settings.filter = 4; //Lots of HW filter - - //tempOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.tempOverSample = 5; - - //pressOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.pressOverSample = 5; - - //humidOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.humidOverSample = 1; - - Serial.begin(57600); - Serial.print("Program Started\n"); - Serial.print("Starting BME280... result of .begin(): 0x"); - delay(10); //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up. - //Calling .begin() causes the settings to be loaded - Serial.println(mySensor.begin(), HEX); - - Serial.println(); - -} - -void loop() -{ - //Get the local temperature! Do this for calibration - mySensor.readTempC(); - - //Check button. No debounce, so hold for operation - if( digitalRead( buttonSensePin ) == 0 ) - { - //Set reference altitude. - reference = mySensor.readFloatAltitudeFeet(); - } - - float lastAlt = mySensor.readFloatAltitudeFeet() - reference; - myBuffer.pushElement(lastAlt); - float tempAlt = myBuffer.averageLast(15); //Do an average of the latest samples - - Serial.println(); - Serial.print("Temperature: "); - Serial.print(mySensor.readTempC(), 2); - Serial.println(" degrees C"); - Serial.print("Last sample: "); - if(lastAlt >= 0) - { - Serial.print(" "); - } - Serial.print(lastAlt, 2); - Serial.println(" ft"); - Serial.print("Last 15 samples averaged: "); - if(tempAlt >= 0) - { - Serial.print(" "); - } - Serial.print(tempAlt); - Serial.println(" ft"); - delay(200); - -} diff --git a/examples/I2C_ReadAllData/I2C_ReadAllData.ino b/examples/I2C_ReadAllData/I2C_ReadAllData.ino deleted file mode 100644 index 64624da..0000000 --- a/examples/I2C_ReadAllData/I2C_ReadAllData.ino +++ /dev/null @@ -1,214 +0,0 @@ -/****************************************************************************** -I2C_ReadAllData.ino -BME280 Arduino and Teensy example -Marshall Taylor @ SparkFun Electronics -May 20, 2015 -https://github.com/sparkfun/SparkFun_BME280_Arduino_Library - -This sketch configures the BME280 to read all measurements. The sketch also -displays the BME280's physical memory and what the driver perceives the -calibration words to be. - -Resources: -Uses Wire.h for I2C operation -Uses SPI.h for SPI operation - -Development environment specifics: -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 -or concerns with licensing, please contact techsupport@sparkfun.com. -Distributed as-is; no warranty is given. -******************************************************************************/ - -#include -#include "SparkFunBME280.h" -//Library allows either I2C or SPI, so include both. -#include "Wire.h" -#include "SPI.h" - -//Global sensor object -BME280 mySensor; - -void setup() -{ - //***Driver settings********************************// - //commInterface can be I2C_MODE or SPI_MODE - //specify chipSelectPin using arduino pin names - //specify I2C address. Can be 0x77(default) or 0x76 - - //For I2C, enable the following and disable the SPI section - mySensor.settings.commInterface = I2C_MODE; - mySensor.settings.I2CAddress = 0x77; - - //For SPI enable the following and dissable the I2C section - //mySensor.settings.commInterface = SPI_MODE; - //mySensor.settings.chipSelectPin = 10; - - - //***Operation settings*****************************// - - //renMode can be: - // 0, Sleep mode - // 1 or 2, Forced mode - // 3, Normal mode - mySensor.settings.runMode = 3; //Normal mode - - //tStandby can be: - // 0, 0.5ms - // 1, 62.5ms - // 2, 125ms - // 3, 250ms - // 4, 500ms - // 5, 1000ms - // 6, 10ms - // 7, 20ms - mySensor.settings.tStandby = 0; - - //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 - mySensor.settings.filter = 0; - - //tempOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.tempOverSample = 1; - - //pressOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.pressOverSample = 1; - - //humidOverSample can be: - // 0, skipped - // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively - mySensor.settings.humidOverSample = 1; - - Serial.begin(57600); - Serial.print("Program Started\n"); - Serial.print("Starting BME280... result of .begin(): 0x"); - - //Calling .begin() causes the settings to be loaded - delay(10); //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up. - Serial.println(mySensor.begin(), HEX); - - Serial.print("Displaying ID, reset and ctrl regs\n"); - - Serial.print("ID(0xD0): 0x"); - Serial.println(mySensor.readRegister(BME280_CHIP_ID_REG), HEX); - Serial.print("Reset register(0xE0): 0x"); - Serial.println(mySensor.readRegister(BME280_RST_REG), HEX); - Serial.print("ctrl_meas(0xF4): 0x"); - Serial.println(mySensor.readRegister(BME280_CTRL_MEAS_REG), HEX); - Serial.print("ctrl_hum(0xF2): 0x"); - Serial.println(mySensor.readRegister(BME280_CTRL_HUMIDITY_REG), HEX); - - Serial.print("\n\n"); - - Serial.print("Displaying all regs\n"); - uint8_t memCounter = 0x80; - uint8_t tempReadData; - for(int rowi = 8; rowi < 16; rowi++ ) - { - Serial.print("0x"); - Serial.print(rowi, HEX); - Serial.print("0:"); - for(int coli = 0; coli < 16; coli++ ) - { - tempReadData = mySensor.readRegister(memCounter); - Serial.print((tempReadData >> 4) & 0x0F, HEX);//Print first hex nibble - Serial.print(tempReadData & 0x0F, HEX);//Print second hex nibble - Serial.print(" "); - memCounter++; - } - Serial.print("\n"); - } - - - Serial.print("\n\n"); - - Serial.print("Displaying concatenated calibration words\n"); - Serial.print("dig_T1, uint16: "); - Serial.println(mySensor.calibration.dig_T1); - Serial.print("dig_T2, int16: "); - Serial.println(mySensor.calibration.dig_T2); - Serial.print("dig_T3, int16: "); - Serial.println(mySensor.calibration.dig_T3); - - Serial.print("dig_P1, uint16: "); - Serial.println(mySensor.calibration.dig_P1); - Serial.print("dig_P2, int16: "); - Serial.println(mySensor.calibration.dig_P2); - Serial.print("dig_P3, int16: "); - Serial.println(mySensor.calibration.dig_P3); - Serial.print("dig_P4, int16: "); - Serial.println(mySensor.calibration.dig_P4); - Serial.print("dig_P5, int16: "); - Serial.println(mySensor.calibration.dig_P5); - Serial.print("dig_P6, int16: "); - Serial.println(mySensor.calibration.dig_P6); - Serial.print("dig_P7, int16: "); - Serial.println(mySensor.calibration.dig_P7); - Serial.print("dig_P8, int16: "); - Serial.println(mySensor.calibration.dig_P8); - Serial.print("dig_P9, int16: "); - Serial.println(mySensor.calibration.dig_P9); - - Serial.print("dig_H1, uint8: "); - Serial.println(mySensor.calibration.dig_H1); - Serial.print("dig_H2, int16: "); - Serial.println(mySensor.calibration.dig_H2); - Serial.print("dig_H3, uint8: "); - Serial.println(mySensor.calibration.dig_H3); - Serial.print("dig_H4, int16: "); - Serial.println(mySensor.calibration.dig_H4); - Serial.print("dig_H5, int16: "); - Serial.println(mySensor.calibration.dig_H5); - Serial.print("dig_H6, int8: "); - Serial.println(mySensor.calibration.dig_H6); - - Serial.println(); -} - -void loop() -{ - //Each loop, take a reading. - //Start with temperature, as that data is needed for accurate compensation. - //Reading the temperature updates the compensators of the other functions - //in the background. - - Serial.print("Temperature: "); - Serial.print(mySensor.readTempC(), 2); - Serial.println(" degrees C"); - - Serial.print("Temperature: "); - Serial.print(mySensor.readTempF(), 2); - Serial.println(" degrees F"); - - Serial.print("Pressure: "); - Serial.print(mySensor.readFloatPressure(), 2); - Serial.println(" Pa"); - - Serial.print("Altitude: "); - Serial.print(mySensor.readFloatAltitudeMeters(), 2); - Serial.println("m"); - - Serial.print("Altitude: "); - Serial.print(mySensor.readFloatAltitudeFeet(), 2); - Serial.println("ft"); - - Serial.print("%RH: "); - Serial.print(mySensor.readFloatHumidity(), 2); - Serial.println(" %"); - - Serial.println(); - - delay(1000); - -} diff --git a/examples/I2C_and_SPI_Multisensor/I2C_and_SPI_Multisensor.ino b/examples/More_Advanced/I2C_and_SPI_Multisensor/I2C_and_SPI_Multisensor.ino similarity index 100% rename from examples/I2C_and_SPI_Multisensor/I2C_and_SPI_Multisensor.ino rename to examples/More_Advanced/I2C_and_SPI_Multisensor/I2C_and_SPI_Multisensor.ino diff --git a/examples/I2C_DeltaAltitude/CircularBuffer.cpp b/examples/More_Advanced/LCD_DeltaAltitude/CircularBuffer.cpp similarity index 100% rename from examples/I2C_DeltaAltitude/CircularBuffer.cpp rename to examples/More_Advanced/LCD_DeltaAltitude/CircularBuffer.cpp diff --git a/examples/I2C_DeltaAltitude/CircularBuffer.h b/examples/More_Advanced/LCD_DeltaAltitude/CircularBuffer.h similarity index 100% rename from examples/I2C_DeltaAltitude/CircularBuffer.h rename to examples/More_Advanced/LCD_DeltaAltitude/CircularBuffer.h diff --git a/examples/SketchesWithLCD/LCD_DeltaAltitude/LCD_DeltaAltitude.ino b/examples/More_Advanced/LCD_DeltaAltitude/LCD_DeltaAltitude.ino similarity index 100% rename from examples/SketchesWithLCD/LCD_DeltaAltitude/LCD_DeltaAltitude.ino rename to examples/More_Advanced/LCD_DeltaAltitude/LCD_DeltaAltitude.ino diff --git a/examples/SketchesWithLCD/LCD_PressureTemperature/LCD_PressureTemperature.ino b/examples/More_Advanced/LCD_PressureTemperature/LCD_PressureTemperature.ino similarity index 100% rename from examples/SketchesWithLCD/LCD_PressureTemperature/LCD_PressureTemperature.ino rename to examples/More_Advanced/LCD_PressureTemperature/LCD_PressureTemperature.ino diff --git a/examples/SPI/Example1_BasicReadings/Example1_BasicReadings.ino b/examples/SPI/Example1_BasicReadings/Example1_BasicReadings.ino new file mode 100644 index 0000000..f5a79ee --- /dev/null +++ b/examples/SPI/Example1_BasicReadings/Example1_BasicReadings.ino @@ -0,0 +1,60 @@ +/* + Get basic environmental readings from the BME280 + By: Nathan Seidle + SparkFun Electronics + Date: March 9th, 2018 + 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 SPI. + + Hardware connections: + BME280 -> Arduino + GND -> GND + 3.3 -> 3.3 + CS -> 10 + MOSI -> 11 + MISO -> 12 + SCK -> 13 +*/ + +#include + +#include "SparkFunBME280.h" +BME280 mySensor; + +void setup() +{ + Serial.begin(9600); + Serial.println("Reading basic values from BME280"); + + if (mySensor.beginSPI(10) == false) //Begin communication over SPI. Use pin 10 as CS. + { + Serial.println("The sensor did not respond. Please check wiring."); + while(1); //Freeze + } +} + +void loop() +{ + Serial.print("Humidity: "); + Serial.print(mySensor.readFloatHumidity(), 0); + + Serial.print(" Pressure: "); + Serial.print(mySensor.readFloatPressure(), 0); + + Serial.print(" Alt: "); + //Serial.print(mySensor.readFloatAltitudeMeters(), 1); + Serial.print(mySensor.readFloatAltitudeFeet(), 1); + + Serial.print(" Temp: "); + //Serial.print(mySensor.readTempC(), 2); + Serial.print(mySensor.readTempF(), 2); + + Serial.println(); + + delay(50); +} diff --git a/keywords.txt b/keywords.txt index 881dc6e..c7f1a30 100644 --- a/keywords.txt +++ b/keywords.txt @@ -12,6 +12,7 @@ BME280 KEYWORD1 begin KEYWORD2 reset KEYWORD2 + readFloatPressure KEYWORD2 readFloatAltitudeMeters KEYWORD2 readFloatAltitudeFeet KEYWORD2 @@ -23,6 +24,18 @@ readRegister KEYWORD2 readRegisterInt16 KEYWORD2 writeRegister KEYWORD2 +beginI2C KEYWORD2 +setFilter KEYWORD2 +setStandbyTime KEYWORD2 +setMode KEYWORD2 +getMode KEYWORD2 +setTempOverSample KEYWORD2 +setPressureOverSample KEYWORD2 +setHumidityOverSample KEYWORD2 +setI2CAddress KEYWORD2 +isMeasuring KEYWORD2 +setReferencePressure KEYWORD2 + ################################################################### # Constants ################################################################### diff --git a/library.properties b/library.properties index 1251662..4601130 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=SparkFun BME280 -version=1.2.0 -author=Marshall Taylor +version=2.0.10 +author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A library to drive the Bosch BME280 Altimeter and Pressure sensor -paragraph=See code for comments. +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 diff --git a/readme_picture.jpg b/readme_picture.jpg deleted file mode 100644 index 451faaa..0000000 Binary files a/readme_picture.jpg and /dev/null differ diff --git a/src/SparkFunBME280.cpp b/src/SparkFunBME280.cpp index 2b17919..dac7ab1 100644 --- a/src/SparkFunBME280.cpp +++ b/src/SparkFunBME280.cpp @@ -10,7 +10,7 @@ Uses Wire.h for i2c operation Uses SPI.h for SPI operation Development environment specifics: -Arduino IDE 1.6.4 +Arduino IDE 1.8.5 Teensy loader 1.23 This code is released under the [MIT License](http://opensource.org/licenses/MIT). @@ -20,12 +20,8 @@ Distributed as-is; no warranty is given. ******************************************************************************/ //See SparkFunBME280.h for additional topology notes. -#include "SparkFunBME280.h" -#include "stdint.h" #include - -#include "Wire.h" -#include "SPI.h" +#include "SparkFunBME280.h" //****************************************************************************// // @@ -36,19 +32,23 @@ Distributed as-is; no warranty is given. //Constructor -- Specifies default configuration BME280::BME280( void ) { - //Construct with these default settings if nothing is specified + //Construct with these default settings - //Select interface mode - settings.commInterface = I2C_MODE; //Can be I2C_MODE, SPI_MODE - //Select address for I2C. Does nothing for SPI - settings.I2CAddress = 0x77; //Ignored for SPI_MODE - //Select CS pin for SPI. Does nothing for I2C - settings.chipSelectPin = 10; - settings.runMode = 0; - settings.tempOverSample = 0; - settings.pressOverSample = 0; - settings.humidOverSample = 0; + settings.commInterface = I2C_MODE; //Default to I2C + 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 } @@ -56,44 +56,39 @@ BME280::BME280( void ) // // Configuration section // -// This uses the stored SensorSettings to start the IMU +// This uses the stored BME280_SensorSettings to start the IMU // 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 - uint8_t dataToWrite = 0; //Temporary variable switch (settings.commInterface) { case I2C_MODE: - Wire.begin(); + + //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: SPI.begin(); - #ifdef ARDUINO_ARCH_ESP32 - SPI.setFrequency(1000000); - // Data is read and written MSb first. - SPI.setBitOrder(SPI_MSBFIRST); - // Like the standard arduino/teensy comment below, mode0 seems wrong according to standards - // but conforms to the timing diagrams when used for the ESP32 - SPI.setDataMode(SPI_MODE0); - #else - // Maximum SPI frequency is 10MHz, could divide by 2 here: - SPI.setClockDivider(SPI_CLOCK_DIV32); - // Data is read and written MSb first. - SPI.setBitOrder(MSBFIRST); - // Data is captured on rising edge of clock (CPHA = 0) - // Base value of the clock is HIGH (CPOL = 1) - // This was SPI_MODE3 for RedBoard, but I had to change to - // MODE0 for Teensy 3.1 operation - SPI.setDataMode(SPI_MODE3); - #endif - // initalize the data ready and chip select pins: + // initialize the data ready and chip select pins: pinMode(settings.chipSelectPin, OUTPUT); digitalWrite(settings.chipSelectPin, HIGH); break; @@ -102,8 +97,12 @@ uint8_t BME280::begin() 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))); @@ -125,30 +124,230 @@ uint8_t BME280::begin() 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)); - //Set the oversampling control words. - //config will only be writeable in sleep mode, so first insure that. - writeRegister(BME280_CTRL_MEAS_REG, 0x00); + //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 - //Set the config word - dataToWrite = (settings.tStandby << 0x5) & 0xE0; - dataToWrite |= (settings.filter << 0x02) & 0x1C; - writeRegister(BME280_CONFIG_REG, dataToWrite); + setMode(MODE_NORMAL); //Go! - //Set ctrl_hum first, then ctrl_meas to activate ctrl_hum - dataToWrite = settings.humidOverSample & 0x07; //all other bits can be ignored - writeRegister(BME280_CTRL_HUMIDITY_REG, dataToWrite); + return(readRegister(BME280_CHIP_ID_REG)); //Should return 0x60 +} + +//Begin comm with BME280 over SPI +bool BME280::beginSPI(uint8_t csPin) +{ + settings.chipSelectPin = csPin; + settings.commInterface = SPI_MODE; - //set ctrl_meas - //First, set temp oversampling - dataToWrite = (settings.tempOverSample << 0x5) & 0xE0; - //Next, pressure oversampling - dataToWrite |= (settings.pressOverSample << 0x02) & 0x1C; - //Last, set mode - dataToWrite |= (settings.runMode) & 0x03; - //Load the byte - writeRegister(BME280_CTRL_MEAS_REG, dataToWrite); + 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); +} + +//Begin comm with BME280 over I2C +bool BME280::beginI2C(TwoWire &wirePort) +{ + _hardPort = &wirePort; + _wireType = HARD_WIRE; + + settings.commInterface = I2C_MODE; + //settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() + + 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); +} + +//Begin comm with BME280 over software I2C +#ifdef SoftwareWire_h +bool BME280::beginI2C(SoftwareWire& wirePort) +{ + _softPort = &wirePort; + _wireType = SOFT_WIRE; + + settings.commInterface = I2C_MODE; + //settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() + + 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); +} +#endif + +//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 - return readRegister(0xD0); + 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 +uint8_t BME280::getMode() +{ + 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 +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 +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); +} + +//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 + + //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 +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 + + //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 +} + +//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 + + //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 +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 +void BME280::setI2CAddress(uint8_t address) +{ + settings.I2CAddress = address; //Set the I2C address for this device +} + +//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 } //Strictly resets. Run .begin() afterwards @@ -158,6 +357,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 (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); +} + //****************************************************************************// // // Pressure Section @@ -168,7 +390,9 @@ 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 - int32_t adc_P = ((uint32_t)readRegister(BME280_PRESSURE_MSB_REG) << 12) | ((uint32_t)readRegister(BME280_PRESSURE_LSB_REG) << 4) | ((readRegister(BME280_PRESSURE_XLSB_REG) >> 4) & 0x0F); + uint8_t buffer[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; @@ -191,11 +415,67 @@ 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: +// 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; +} + +//Return the local reference pressure +float BME280::getReferencePressure() +{ + return(_referencePressure); +} + float BME280::readFloatAltitudeMeters( void ) { float heightOutput = 0; - heightOutput = ((float)-45846.2)*(pow(((float)readFloatPressure()/(float)101325), 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; } @@ -219,7 +499,9 @@ 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 - int32_t adc_H = ((uint32_t)readRegister(BME280_HUMIDITY_MSB_REG) << 8) | ((uint32_t)readRegister(BME280_HUMIDITY_LSB_REG)); + uint8_t buffer[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)); @@ -231,10 +513,26 @@ float BME280::readFloatHumidity( void ) 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; +} //****************************************************************************// // @@ -242,13 +540,20 @@ 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. // t_fine carries fine temperature as global value //get the reading (adc_T); - int32_t adc_T = ((uint32_t)readRegister(BME280_TEMPERATURE_MSB_REG) << 12) | ((uint32_t)readRegister(BME280_TEMPERATURE_LSB_REG) << 4) | ((readRegister(BME280_TEMPERATURE_XLSB_REG) >> 4) & 0x0F); + uint8_t buffer[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; @@ -259,11 +564,34 @@ float BME280::readTempC( void ) t_fine = var1 + var2; float output = (t_fine * 5 + 128) >> 8; - output = output / 100; + output = output / 100 + settings.tempCorrection; 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(); @@ -272,6 +600,44 @@ 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 +// +//****************************************************************************// +// 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); +} + +// Returns Dew point in DegF +double BME280::dewPointF(void) +{ + return(dewPointC() * 1.8 + 32); //Convert C to F +} + //****************************************************************************// // // Utility @@ -287,22 +653,45 @@ void BME280::readRegisterRegion(uint8_t *outputPointer , uint8_t offset, uint8_t { case I2C_MODE: - Wire.beginTransmission(settings.I2CAddress); - Wire.write(offset); - Wire.endTransmission(); - - // request bytes from slave device - Wire.requestFrom(settings.I2CAddress, length); - while ( (Wire.available()) && (i < length)) // slave may send less than requested + switch(_wireType) { - c = Wire.read(); // receive a byte as character - *outputPointer = c; - outputPointer++; - i++; + 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: + SPI.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: @@ -316,6 +705,7 @@ void BME280::readRegisterRegion(uint8_t *outputPointer , uint8_t offset, uint8_t } // take the chip select high to de-select: digitalWrite(settings.chipSelectPin, HIGH); + SPI.endTransaction(); break; default: @@ -327,31 +717,44 @@ void BME280::readRegisterRegion(uint8_t *outputPointer , uint8_t offset, uint8_t uint8_t BME280::readRegister(uint8_t offset) { //Return value - uint8_t result; + uint8_t result = 0; uint8_t numBytes = 1; switch (settings.commInterface) { case I2C_MODE: - Wire.beginTransmission(settings.I2CAddress); - Wire.write(offset); - Wire.endTransmission(); - - Wire.requestFrom(settings.I2CAddress, numBytes); - while ( Wire.available() ) // slave may send less than requested + switch(_wireType) { - result = Wire.read(); // receive a byte as a proper uint8_t + 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: - // 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 - // send a value of 0 to read the first byte returned: - result = SPI.transfer(0x00); - // take the chip select high to de-select: - digitalWrite(settings.chipSelectPin, HIGH); + readRegisterRegion(&result, offset, 1); break; default: @@ -375,13 +778,28 @@ void BME280::writeRegister(uint8_t offset, uint8_t dataToWrite) { case I2C_MODE: //Write the byte - Wire.beginTransmission(settings.I2CAddress); - Wire.write(offset); - Wire.write(dataToWrite); - Wire.endTransmission(); - break; + 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: + SPI.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: @@ -391,6 +809,7 @@ void BME280::writeRegister(uint8_t offset, uint8_t dataToWrite) // decrement the number of bytes left to read: // take the chip select high to de-select: digitalWrite(settings.chipSelectPin, HIGH); + SPI.endTransaction(); break; default: diff --git a/src/SparkFunBME280.h b/src/SparkFunBME280.h index 2c2c3ce..f169b2b 100644 --- a/src/SparkFunBME280.h +++ b/src/SparkFunBME280.h @@ -17,17 +17,55 @@ 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 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 + + ******************************************************************************/ // Test derived class for base class SparkFunIMU #ifndef __BME280_H__ #define __BME280_H__ -#include "stdint.h" +#if (ARDUINO >= 100) +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#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. #define I2C_MODE 0 #define SPI_MODE 1 +#ifndef BME280_SPI_CLOCK +#ifdef ARDUINO_ARCH_ESP32 +#define BME280_SPI_CLOCK 1000000 +#else +#define BME280_SPI_CLOCK 500000 +#endif +#endif + +#ifndef BME280_SPI_MODE +#define BME280_SPI_MODE SPI_MODE0 +#endif + +#define NO_WIRE 0 +#define HARD_WIRE 1 +#define SOFT_WIRE 2 + +#define MODE_SLEEP 0b00 +#define MODE_FORCED 0b01 +#define MODE_NORMAL 0b11 + //Register names: #define BME280_DIG_T1_LSB_REG 0x88 #define BME280_DIG_T1_MSB_REG 0x89 @@ -67,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 @@ -76,33 +115,34 @@ Distributed as-is; no warranty is given. #define BME280_HUMIDITY_MSB_REG 0xFD //Humidity MSB #define BME280_HUMIDITY_LSB_REG 0xFE //Humidity LSB - -//Class SensorSettings. This object is used to hold settings data. The application +//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. // -//A power user would strip out SensorSettings entirely, and send specific read and +//A power user would strip out BME280_SensorSettings entirely, and send specific read and //write command directly to the IC. (ST #defines below) // -struct SensorSettings +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; - + float tempCorrection; // correction of temperature - added to the result }; //Used to hold the calibration constants. These are used @@ -133,39 +173,79 @@ struct SensorCalibration }; -//This is the man operational class of the driver. +struct BME280_SensorMeasurements +{ + public: + float temperature; + float pressure; + float humidity; +}; + +//This is the main operational class of the driver. class BME280 { public: //settings - SensorSettings settings; + BME280_SensorSettings settings; SensorCalibration calibration; int32_t t_fine; - //Constructor generates default SensorSettings. + //Constructor generates default BME280_SensorSettings. //(over-ride after construction if desired) BME280( void ); //~BME280() = default; - //Call to apply SensorSettings. + //Call to apply BME280_SensorSettings. //This also gets the SensorCalibration constants uint8_t begin( void ); + bool beginSPI(uint8_t csPin); //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 + //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 + double dewPointC(void); + double dewPointF(void); + //The following utilities read and write //ReadRegisterRegion takes a uint8 array address as input and reads @@ -178,9 +258,20 @@ class BME280 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 + + #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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy