├── .github └── workflows │ └── add_issue_to_project.yml ├── library.properties ├── examples ├── More_Advanced │ ├── LCD_DeltaAltitude │ │ ├── CircularBuffer.h │ │ ├── CircularBuffer.cpp │ │ └── LCD_DeltaAltitude.ino │ ├── I2C_and_SPI_Multisensor │ │ └── I2C_and_SPI_Multisensor.ino │ └── LCD_PressureTemperature │ │ └── LCD_PressureTemperature.ino ├── Example7_RelativeAltitudeChange │ ├── CircularBuffer.h │ ├── CircularBuffer.cpp │ └── Example7_RelativeAltitudeChange.ino ├── Example10_DewPoint │ └── Example10_DewPoint.ino ├── Example1_BasicReadings │ └── Example1_BasicReadings.ino ├── Example9_SoftwareI2C │ └── Example9_SoftwareI2C.ino ├── SPI │ └── Example1_BasicReadings │ │ └── Example1_BasicReadings.ino ├── Example8_LocalPressure │ └── Example8_LocalPressure.ino ├── Example4_Settings │ └── Example4_Settings.ino ├── Example6_LowPower │ └── Example6_LowPower.ino ├── Example11_BurstRead │ └── Example11_BurstRead.ino ├── Example3_CSVOutput │ └── Example3_CSVOutput.ino ├── Example2_I2CAddress │ └── Example2_I2CAddress.ino └── Example5_ReadAllRegisters │ └── Example5_ReadAllRegisters.ino ├── keywords.txt ├── LICENSE.md ├── README.md └── src ├── SparkFunBME280.h └── SparkFunBME280.cpp /.github/workflows/add_issue_to_project.yml: -------------------------------------------------------------------------------- 1 | name: Add new issue to our main project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@main 14 | with: 15 | # You can target a project in a different organization 16 | # to the issue 17 | project-url: https://github.com/orgs/sparkfun/projects/19 18 | github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }} 19 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun BME280 2 | version=2.0.11 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=A library to drive the Bosch BME280 Altimeter and Pressure sensor 6 | 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. 7 | category=Sensors 8 | url=https://github.com/sparkfun/SparkFun_BME280_Arduino_Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /examples/More_Advanced/LCD_DeltaAltitude/CircularBuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef CIRCULARBUFFER_H 2 | #define CIRCULARBUFFER_H 3 | #include 4 | 5 | //****************************************************************************// 6 | // 7 | // Circular Buffer 8 | // 9 | //****************************************************************************// 10 | 11 | //Class CircularBuffer is int16_t 12 | //Does not care about over-running real data ( if request is outside length's bounds ). 13 | //For example, the underlying machine writes [48], [49], [0], [1] ... 14 | 15 | class CircularBuffer 16 | { 17 | public: 18 | CircularBuffer( uint16_t inputSize ); 19 | ~CircularBuffer(); 20 | float getElement( uint16_t ); //zero is the push location 21 | void pushElement( float ); 22 | float averageLast( uint16_t ); 23 | uint16_t recordLength( void ); 24 | private: 25 | uint16_t cBufferSize; 26 | float *cBufferData; 27 | int16_t cBufferLastPtr; 28 | uint8_t cBufferElementsUsed; 29 | }; 30 | 31 | 32 | 33 | #endif // CIRCULARBUFFER_H -------------------------------------------------------------------------------- /examples/Example7_RelativeAltitudeChange/CircularBuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef CIRCULARBUFFER_H 2 | #define CIRCULARBUFFER_H 3 | #include 4 | 5 | //****************************************************************************// 6 | // 7 | // Circular Buffer 8 | // 9 | //****************************************************************************// 10 | 11 | //Class CircularBuffer is int16_t 12 | //Does not care about over-running real data ( if request is outside length's bounds ). 13 | //For example, the underlying machine writes [48], [49], [0], [1] ... 14 | 15 | class CircularBuffer 16 | { 17 | public: 18 | CircularBuffer( uint16_t inputSize ); 19 | ~CircularBuffer(); 20 | float getElement( uint16_t ); //zero is the push location 21 | void pushElement( float ); 22 | float averageLast( uint16_t ); 23 | uint16_t recordLength( void ); 24 | private: 25 | uint16_t cBufferSize; 26 | float *cBufferData; 27 | int16_t cBufferLastPtr; 28 | uint8_t cBufferElementsUsed; 29 | }; 30 | 31 | 32 | 33 | #endif // CIRCULARBUFFER_H 34 | -------------------------------------------------------------------------------- /examples/Example10_DewPoint/Example10_DewPoint.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Calculating dewpoint on the BME280 3 | Nathan Seidle @ SparkFun Electronics 4 | November 3rd, 2018 5 | 6 | Feel like supporting our work? Buy a board from SparkFun! 7 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 8 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 9 | 10 | This example shows how to calculate dew point based on humidity and temperature. 11 | Comes from Pavel-Sayekat: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/pull/6 12 | 13 | Hardware connections: 14 | BME280 -> Arduino 15 | GND -> GND 16 | 3.3 -> 3.3 17 | SDA -> A4 18 | SCL -> A5 19 | */ 20 | 21 | #include 22 | 23 | #include "SparkFunBME280.h" 24 | BME280 mySensor; 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | Serial.println("Example showing dewpoint calculation"); 30 | 31 | mySensor.setI2CAddress(0x76); //Connect to a second sensor 32 | if (mySensor.beginI2C() == false) Serial.println("Sensor connect failed"); 33 | } 34 | 35 | void loop() 36 | { 37 | Serial.print("Humidity: "); 38 | Serial.print(mySensor.readFloatHumidity(), 0); 39 | 40 | Serial.print(" Pressure: "); 41 | Serial.print(mySensor.readFloatPressure(), 0); 42 | 43 | Serial.print(" Temp: "); 44 | //Serial.print(mySensor.readTempC(), 2); 45 | Serial.print(mySensor.readTempF(), 2); 46 | 47 | Serial.print(" Dewpoint: "); 48 | //Serial.print(mySensor.dewPointC(), 2); 49 | Serial.print(mySensor.dewPointF(), 2); 50 | 51 | Serial.println(); 52 | 53 | delay(50); 54 | } 55 | -------------------------------------------------------------------------------- /examples/Example1_BasicReadings/Example1_BasicReadings.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Get basic environmental readings from the BME280 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: March 9th, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | Feel like supporting our work? Buy a board from SparkFun! 9 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 10 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 11 | 12 | This example shows how to read humidity, pressure, and current temperature from the BME280 over I2C. 13 | 14 | Hardware connections: 15 | BME280 -> Arduino 16 | GND -> GND 17 | 3.3 -> 3.3 18 | SDA -> A4 19 | SCL -> A5 20 | */ 21 | 22 | #include 23 | 24 | #include "SparkFunBME280.h" 25 | BME280 mySensor; 26 | 27 | void setup() 28 | { 29 | Serial.begin(115200); 30 | Serial.println("Reading basic values from BME280"); 31 | 32 | Wire.begin(); 33 | 34 | if (mySensor.beginI2C() == false) //Begin communication over I2C 35 | { 36 | Serial.println("The sensor did not respond. Please check wiring."); 37 | while(1); //Freeze 38 | } 39 | } 40 | 41 | void loop() 42 | { 43 | Serial.print("Humidity: "); 44 | Serial.print(mySensor.readFloatHumidity(), 0); 45 | 46 | Serial.print(" Pressure: "); 47 | Serial.print(mySensor.readFloatPressure(), 0); 48 | 49 | Serial.print(" Alt: "); 50 | //Serial.print(mySensor.readFloatAltitudeMeters(), 1); 51 | Serial.print(mySensor.readFloatAltitudeFeet(), 1); 52 | 53 | Serial.print(" Temp: "); 54 | //Serial.print(mySensor.readTempC(), 2); 55 | Serial.print(mySensor.readTempF(), 2); 56 | 57 | Serial.println(); 58 | 59 | delay(50); 60 | } 61 | -------------------------------------------------------------------------------- /examples/Example9_SoftwareI2C/Example9_SoftwareI2C.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Communicate with BME280s using Software I2C 3 | Nathan Seidle @ SparkFun Electronics 4 | March 23, 2015 5 | 6 | Feel like supporting our work? Buy a board from SparkFun! 7 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 8 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 9 | 10 | This example shows how to connect to sensors using the SoftwareWire library. 11 | 12 | This is an advanced example. You'll need to edit the SparkFunBME280.h file 13 | and uncomment the #include line to enable Software I2C. 14 | 15 | Since we're using software I2C we can use almost any pins. For this example the 16 | hardware connections: 17 | BME280 -> Arduino 18 | GND -> GND 19 | 3.3 -> 3.3 20 | SDA -> 6 21 | SCL -> 7 22 | */ 23 | 24 | #include //SoftwareWire by Testato. Installed from library manager. 25 | 26 | //We use pins 6 and 7 in this example but others can be used 27 | SoftwareWire myWire(6, 7); //SDA, SCL 28 | 29 | #include "SparkFunBME280.h" 30 | BME280 mySensor; 31 | 32 | void setup() 33 | { 34 | Serial.begin(115200); 35 | Serial.println("Example showing alternate I2C addresses"); 36 | 37 | myWire.begin(); 38 | if(mySensor.beginI2C(myWire) == false) Serial.println("Sensor A connect failed"); 39 | } 40 | 41 | void loop() 42 | { 43 | Serial.print("Humidity: "); 44 | Serial.print(mySensor.readFloatHumidity(), 0); 45 | 46 | Serial.print(" Pressure: "); 47 | Serial.print(mySensor.readFloatPressure(), 0); 48 | 49 | Serial.print(" Temp: "); 50 | //Serial.print(mySensor.readTempC(), 2); 51 | Serial.print(mySensor.readTempF(), 2); 52 | 53 | Serial.println(); 54 | 55 | delay(50); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /examples/SPI/Example1_BasicReadings/Example1_BasicReadings.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Get basic environmental readings from the BME280 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: March 9th, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | Feel like supporting our work? Buy a board from SparkFun! 9 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 10 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 11 | 12 | This example shows how to read humidity, pressure, and current temperature from the BME280 over SPI. 13 | 14 | Hardware connections: 15 | BME280 -> Arduino 16 | GND -> GND 17 | 3.3 -> 3.3 18 | CS -> 10 19 | MOSI -> 11 20 | MISO -> 12 21 | SCK -> 13 22 | */ 23 | 24 | #include 25 | 26 | #include "SparkFunBME280.h" 27 | BME280 mySensor; 28 | 29 | void setup() 30 | { 31 | Serial.begin(9600); 32 | Serial.println("Reading basic values from BME280"); 33 | 34 | if (mySensor.beginSPI(10) == false) //Begin communication over SPI. Use pin 10 as CS. 35 | { 36 | Serial.println("The sensor did not respond. Please check wiring."); 37 | while(1); //Freeze 38 | } 39 | } 40 | 41 | void loop() 42 | { 43 | Serial.print("Humidity: "); 44 | Serial.print(mySensor.readFloatHumidity(), 0); 45 | 46 | Serial.print(" Pressure: "); 47 | Serial.print(mySensor.readFloatPressure(), 0); 48 | 49 | Serial.print(" Alt: "); 50 | //Serial.print(mySensor.readFloatAltitudeMeters(), 1); 51 | Serial.print(mySensor.readFloatAltitudeFeet(), 1); 52 | 53 | Serial.print(" Temp: "); 54 | //Serial.print(mySensor.readTempC(), 2); 55 | Serial.print(mySensor.readTempF(), 2); 56 | 57 | Serial.println(); 58 | 59 | delay(50); 60 | } 61 | -------------------------------------------------------------------------------- /examples/Example8_LocalPressure/Example8_LocalPressure.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Adjust the local Reference Pressure 3 | Nathan Seidle @ SparkFun Electronics 4 | March 23, 2018 5 | 6 | Feel like supporting our work? Buy a board from SparkFun! 7 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 8 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 9 | 10 | 'Sea level' pressure changes with high and low pressure weather movement. 11 | This sketch demonstrates how to change sea level 101325Pa to a different value. 12 | See Issue 1: https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/issues/1 13 | 14 | Google 'sea level pressure map' for more information: 15 | http://weather.unisys.com/surface/sfc_con.php?image=pr&inv=0&t=cur 16 | https://www.atmos.illinois.edu/weather/tree/viewer.pl?launch/sfcslp 17 | 18 | 29.92 inHg = 1.0 atm = 101325 Pa = 1013.25 mb 19 | */ 20 | 21 | #include 22 | 23 | #include "SparkFunBME280.h" 24 | BME280 mySensor; 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | Serial.println("Example showing alternate I2C addresses"); 30 | 31 | Wire.begin(); 32 | Wire.setClock(400000); //Increase to fast I2C speed! 33 | 34 | mySensor.beginI2C(); 35 | 36 | mySensor.setReferencePressure(101200); //Adjust the sea level pressure used for altitude calculations 37 | } 38 | 39 | void loop() 40 | { 41 | Serial.print("Humidity: "); 42 | Serial.print(mySensor.readFloatHumidity(), 0); 43 | 44 | Serial.print(" Pressure: "); 45 | Serial.print(mySensor.readFloatPressure(), 0); 46 | 47 | Serial.print(" Locally Adjusted Altitude: "); 48 | //Serial.print(mySensor.readFloatAltitudeMeters(), 1); 49 | Serial.print(mySensor.readFloatAltitudeFeet(), 1); 50 | 51 | Serial.print(" Temp: "); 52 | //Serial.print(mySensor.readTempC(), 2); 53 | Serial.print(mySensor.readTempF(), 2); 54 | 55 | Serial.println(); 56 | 57 | delay(50); 58 | } 59 | 60 | -------------------------------------------------------------------------------- /examples/Example4_Settings/Example4_Settings.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Control the various settings of the BME280 3 | Nathan Seidle @ SparkFun Electronics 4 | March 23, 2018 5 | 6 | Feel like supporting our work? Buy a board from SparkFun! 7 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 8 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 9 | 10 | This example shows how to set the various filter, and oversample settings of the BME280. 11 | */ 12 | 13 | #include 14 | 15 | #include "SparkFunBME280.h" 16 | BME280 mySensor; 17 | 18 | void setup() 19 | { 20 | Serial.begin(115200); 21 | Serial.println("Example showing alternate I2C addresses"); 22 | 23 | Wire.begin(); 24 | Wire.setClock(400000); //Increase to fast I2C speed! 25 | 26 | mySensor.beginI2C(); 27 | 28 | mySensor.setFilter(1); //0 to 4 is valid. Filter coefficient. See 3.4.4 29 | mySensor.setStandbyTime(0); //0 to 7 valid. Time between readings. See table 27. 30 | 31 | mySensor.setTempOverSample(1); //0 to 16 are valid. 0 disables temp sensing. See table 24. 32 | mySensor.setPressureOverSample(1); //0 to 16 are valid. 0 disables pressure sensing. See table 23. 33 | mySensor.setHumidityOverSample(1); //0 to 16 are valid. 0 disables humidity sensing. See table 19. 34 | 35 | mySensor.setMode(MODE_NORMAL); //MODE_SLEEP, MODE_FORCED, MODE_NORMAL is valid. See 3.3 36 | } 37 | 38 | void loop() 39 | { 40 | Serial.print("Humidity: "); 41 | Serial.print(mySensor.readFloatHumidity(), 0); 42 | 43 | Serial.print(" Pressure: "); 44 | Serial.print(mySensor.readFloatPressure(), 0); 45 | 46 | Serial.print(" Alt: "); 47 | //Serial.print(mySensor.readFloatAltitudeMeters(), 1); 48 | Serial.print(mySensor.readFloatAltitudeFeet(), 1); 49 | 50 | Serial.print(" Temp: "); 51 | //Serial.print(mySensor.readTempC(), 2); 52 | Serial.print(mySensor.readTempF(), 2); 53 | 54 | Serial.println(); 55 | 56 | delay(50); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /examples/Example6_LowPower/Example6_LowPower.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Put the BME280 into low power mode (aka Forced Read) 3 | Nathan Seidle @ SparkFun Electronics 4 | March 23, 2018 5 | 6 | Feel like supporting our work? Buy a board from SparkFun! 7 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 8 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 9 | 10 | This example shows how used the 'Forced Mode' to obtain a reading then put the 11 | sensor to sleep between readings. 12 | */ 13 | 14 | #include 15 | 16 | #include "SparkFunBME280.h" 17 | BME280 mySensor; 18 | 19 | void setup() 20 | { 21 | Serial.begin(115200); 22 | Serial.println("Example showing alternate I2C addresses"); 23 | 24 | Wire.begin(); 25 | Wire.setClock(400000); //Increase to fast I2C speed! 26 | 27 | mySensor.beginI2C(); 28 | 29 | mySensor.setMode(MODE_SLEEP); //Sleep for now 30 | } 31 | 32 | void loop() 33 | { 34 | mySensor.setMode(MODE_FORCED); //Wake up sensor and take reading 35 | 36 | long startTime = millis(); 37 | while(mySensor.isMeasuring() == false) ; //Wait for sensor to start measurment 38 | while(mySensor.isMeasuring() == true) ; //Hang out while sensor completes the reading 39 | long endTime = millis(); 40 | 41 | //Sensor is now back asleep but we get get the data 42 | 43 | Serial.print(" Measure time(ms): "); 44 | Serial.print(endTime - startTime); 45 | 46 | Serial.print(" Humidity: "); 47 | Serial.print(mySensor.readFloatHumidity(), 0); 48 | 49 | Serial.print(" Pressure: "); 50 | Serial.print(mySensor.readFloatPressure(), 0); 51 | 52 | Serial.print(" Alt: "); 53 | //Serial.print(mySensor.readFloatAltitudeMeters(), 1); 54 | Serial.print(mySensor.readFloatAltitudeFeet(), 1); 55 | 56 | Serial.print(" Temp: "); 57 | //Serial.print(mySensor.readTempC(), 2); 58 | Serial.print(mySensor.readTempF(), 2); 59 | 60 | Serial.println(); 61 | 62 | delay(1000); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /examples/Example11_BurstRead/Example11_BurstRead.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Get environmental readings as a burst from the BME280 3 | By: Claudio Donaté 4 | Date: December 30th, 2020 5 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 6 | 7 | Feel like supporting our work? Buy a board from SparkFun! 8 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 9 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 10 | 11 | This example shows how to read humidity, pressure, and current temperature from the BME280 over I2C reading all registers at once. 12 | Please check BME280 Datasheet, section 4, Data readout for detail explanations on why. 13 | 14 | Hardware connections: 15 | BME280 -> Arduino 16 | GND -> GND 17 | 3.3 -> 3.3 18 | SDA -> A4 19 | SCL -> A5 20 | */ 21 | 22 | #include 23 | 24 | #include "SparkFunBME280.h" 25 | 26 | #define CELSIUS_SCALE 0 //Default 27 | #define FAHRENHEIT_SCALE 1 28 | 29 | BME280 mySensor; 30 | BME280_SensorMeasurements measurements; 31 | 32 | void setup() 33 | { 34 | Serial.begin(115200); 35 | Serial.println("Reading basic values from BME280 as a Burst"); 36 | 37 | Wire.begin(); 38 | 39 | if (mySensor.beginI2C() == false) //Begin communication over I2C 40 | { 41 | Serial.println("The sensor did not respond. Please check wiring."); 42 | while(1); //Freeze 43 | } 44 | } 45 | 46 | void loop() 47 | { 48 | while (mySensor.isMeasuring()) // Wait for sensor to finish measuring 49 | { 50 | Serial.print("."); 51 | }; 52 | 53 | mySensor.readAllMeasurements(&measurements); // Return temperature in Celsius 54 | // mySensor.readAllMeasurements(&measurements, FAHRENHEIT_SCALE); 55 | 56 | Serial.print("\nHumidity: "); 57 | Serial.print(measurements.humidity, 0); 58 | 59 | Serial.print(" Pressure: "); 60 | Serial.print(measurements.pressure, 0); 61 | 62 | Serial.print(" Temp: "); 63 | Serial.print(measurements.temperature, 2); 64 | 65 | Serial.println(); 66 | 67 | delay(50); 68 | } 69 | -------------------------------------------------------------------------------- /examples/Example3_CSVOutput/Example3_CSVOutput.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Output all readings in CSV format 3 | BME280 Arduino and Teensy example 4 | Marshall Taylor @ SparkFun Electronics 5 | May 20, 2015 6 | https://github.com/sparkfun/SparkFun_BME280_Arduino_Library 7 | 8 | This sketch outputs BME280 data in comma separated values for generating spreadsheet graphs. 9 | 10 | Feel like supporting our work? Buy a board from SparkFun! 11 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 12 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 13 | */ 14 | 15 | #include 16 | 17 | #include "SparkFunBME280.h" 18 | BME280 mySensor; 19 | 20 | unsigned long sampleNumber = 0; 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | 26 | Wire.begin(); 27 | 28 | if (mySensor.beginI2C() == false) //Begin communication over I2C 29 | { 30 | Serial.println("The sensor did not respond. Please check wiring."); 31 | while(1); //Freeze 32 | } 33 | 34 | //Build a first-row of column headers 35 | Serial.print("SampleNumber,"); 36 | Serial.print("Time(ms),"); 37 | Serial.print("T(deg C),"); 38 | Serial.print("T(deg F),"); 39 | Serial.print("P(Pa),"); 40 | Serial.print("Alt(m),"); 41 | Serial.print("Alt(ft),"); 42 | Serial.print("%RH"); 43 | Serial.println(""); 44 | } 45 | 46 | void loop() 47 | { 48 | //Print each row in the loop 49 | //Start with temperature, as that data is needed for accurate compensation. 50 | //Reading the temperature updates the compensators of the other functions 51 | //in the background. 52 | Serial.print(sampleNumber); 53 | Serial.print(","); 54 | Serial.print(millis()); 55 | Serial.print(","); 56 | Serial.print(mySensor.readTempC(), 2); 57 | Serial.print(","); 58 | Serial.print(mySensor.readTempF(), 3); 59 | Serial.print(","); 60 | Serial.print(mySensor.readFloatPressure(), 0); 61 | Serial.print(","); 62 | Serial.print(mySensor.readFloatAltitudeMeters(), 3); 63 | Serial.print(","); 64 | Serial.print(mySensor.readFloatAltitudeFeet(), 3); 65 | Serial.print(","); 66 | Serial.print(mySensor.readFloatHumidity(), 0); 67 | Serial.println(); 68 | 69 | sampleNumber++; 70 | 71 | delay(50); 72 | } 73 | -------------------------------------------------------------------------------- /examples/Example2_I2CAddress/Example2_I2CAddress.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Communicate with BME280s with different I2C addresses 3 | Nathan Seidle @ SparkFun Electronics 4 | March 23, 2015 5 | 6 | Feel like supporting our work? Buy a board from SparkFun! 7 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 8 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 9 | 10 | This example shows how to connect two sensors on the same I2C bus. 11 | 12 | The BME280 has two I2C addresses: 0x77 (jumper open) or 0x76 (jumper closed) 13 | 14 | Hardware connections: 15 | BME280 -> Arduino 16 | GND -> GND 17 | 3.3 -> 3.3 18 | SDA -> A4 19 | SCL -> A5 20 | */ 21 | 22 | #include 23 | 24 | #include "SparkFunBME280.h" 25 | BME280 mySensorA; //Uses default I2C address 0x77 26 | BME280 mySensorB; //Uses I2C address 0x76 (jumper closed) 27 | 28 | void setup() 29 | { 30 | Serial.begin(115200); 31 | Serial.println("Example showing alternate I2C addresses"); 32 | 33 | Wire.begin(); 34 | 35 | mySensorA.setI2CAddress(0x77); //The default for the SparkFun Environmental Combo board is 0x77 (jumper open). 36 | //If you close the jumper it is 0x76 37 | //The I2C address must be set before .begin() otherwise the cal values will fail to load. 38 | 39 | if(mySensorA.beginI2C() == false) Serial.println("Sensor A connect failed"); 40 | 41 | mySensorB.setI2CAddress(0x76); //Connect to a second sensor 42 | if(mySensorB.beginI2C() == false) Serial.println("Sensor B connect failed"); 43 | } 44 | 45 | void loop() 46 | { 47 | Serial.print("HumidityA: "); 48 | Serial.print(mySensorA.readFloatHumidity(), 0); 49 | 50 | Serial.print(" PressureA: "); 51 | Serial.print(mySensorA.readFloatPressure(), 0); 52 | 53 | Serial.print(" TempA: "); 54 | //Serial.print(mySensorA.readTempC(), 2); 55 | Serial.print(mySensorA.readTempF(), 2); 56 | 57 | Serial.print(" HumidityB: "); 58 | Serial.print(mySensorB.readFloatHumidity(), 0); 59 | 60 | Serial.print(" PressureB: "); 61 | Serial.print(mySensorB.readFloatPressure(), 0); 62 | 63 | Serial.print(" TempB: "); 64 | //Serial.print(mySensorB.readTempC(), 2); 65 | Serial.print(mySensorB.readTempF(), 2); 66 | 67 | Serial.println(); 68 | 69 | delay(50); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /examples/More_Advanced/LCD_DeltaAltitude/CircularBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "CircularBuffer.h" 2 | #include 3 | 4 | //****************************************************************************// 5 | // 6 | // Circular buffer 7 | // 8 | //****************************************************************************// 9 | 10 | //Construct a CircularBuffer type with arguments 11 | // uint16_t inputSize: number of elements 12 | CircularBuffer::CircularBuffer(uint16_t inputSize) 13 | { 14 | cBufferData = new float[inputSize]; 15 | cBufferLastPtr = 0; 16 | cBufferElementsUsed = 0; 17 | cBufferSize = inputSize; 18 | 19 | } 20 | 21 | CircularBuffer::~CircularBuffer() 22 | { 23 | delete[] cBufferData; 24 | 25 | } 26 | 27 | //Get an element at some depth into the circular buffer 28 | //zero is the push location. Max is cBufferSize - 1 29 | // 30 | //Arguments: 31 | // uint16_t elementNum: number of element in 32 | // 33 | float CircularBuffer::getElement( uint16_t elementNum ) 34 | { 35 | //Translate elementNum into terms of cBufferLastPtr. 36 | int16_t virtualElementNum; 37 | virtualElementNum = cBufferLastPtr - elementNum; 38 | if( virtualElementNum < 0 ) 39 | { 40 | virtualElementNum += cBufferSize; 41 | } 42 | 43 | //Output the value 44 | return cBufferData[virtualElementNum]; 45 | } 46 | 47 | //Put a new element into the buffer. 48 | //This also expands the size up to the max size 49 | //Arguments: 50 | // 51 | // int16_t elementVal: value of new element 52 | // 53 | void CircularBuffer::pushElement( float elementVal ) 54 | { 55 | //inc. the pointer 56 | cBufferLastPtr++; 57 | 58 | //deal with roll 59 | if( cBufferLastPtr >= cBufferSize ) 60 | { 61 | cBufferLastPtr = 0; 62 | } 63 | 64 | //write data 65 | cBufferData[cBufferLastPtr] = elementVal; 66 | 67 | //increase length up to cBufferSize 68 | if( cBufferElementsUsed < cBufferSize ) 69 | { 70 | cBufferElementsUsed++; 71 | } 72 | } 73 | 74 | //Averages the last n numbers and provides that. Discards fractions 75 | float CircularBuffer::averageLast( uint16_t numElements ) 76 | { 77 | if( numElements < recordLength() ) 78 | { 79 | numElements = recordLength(); 80 | } 81 | //Add up all the elements 82 | float accumulator = 0; 83 | int8_t i; 84 | for( i = 0; i < numElements; i++ ) 85 | { 86 | accumulator += getElement( i ); 87 | } 88 | //Divide by number of elements 89 | if( numElements != 0 ) 90 | { 91 | accumulator /= numElements; 92 | } 93 | else 94 | { 95 | accumulator = 0; 96 | } 97 | return accumulator; 98 | } 99 | 100 | //Returns the current size of the buffer 101 | uint16_t CircularBuffer::recordLength( void ) 102 | { 103 | return cBufferElementsUsed; 104 | } -------------------------------------------------------------------------------- /examples/Example7_RelativeAltitudeChange/CircularBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "CircularBuffer.h" 2 | #include 3 | 4 | //****************************************************************************// 5 | // 6 | // Circular buffer 7 | // 8 | //****************************************************************************// 9 | 10 | //Construct a CircularBuffer type with arguments 11 | // uint16_t inputSize: number of elements 12 | CircularBuffer::CircularBuffer(uint16_t inputSize) 13 | { 14 | cBufferData = new float[inputSize]; 15 | cBufferLastPtr = 0; 16 | cBufferElementsUsed = 0; 17 | cBufferSize = inputSize; 18 | 19 | } 20 | 21 | CircularBuffer::~CircularBuffer() 22 | { 23 | delete[] cBufferData; 24 | 25 | } 26 | 27 | //Get an element at some depth into the circular buffer 28 | //zero is the push location. Max is cBufferSize - 1 29 | // 30 | //Arguments: 31 | // uint16_t elementNum: number of element in 32 | // 33 | float CircularBuffer::getElement( uint16_t elementNum ) 34 | { 35 | //Translate elementNum into terms of cBufferLastPtr. 36 | int16_t virtualElementNum; 37 | virtualElementNum = cBufferLastPtr - elementNum; 38 | if( virtualElementNum < 0 ) 39 | { 40 | virtualElementNum += cBufferSize; 41 | } 42 | 43 | //Output the value 44 | return cBufferData[virtualElementNum]; 45 | } 46 | 47 | //Put a new element into the buffer. 48 | //This also expands the size up to the max size 49 | //Arguments: 50 | // 51 | // int16_t elementVal: value of new element 52 | // 53 | void CircularBuffer::pushElement( float elementVal ) 54 | { 55 | //inc. the pointer 56 | cBufferLastPtr++; 57 | 58 | //deal with roll 59 | if( cBufferLastPtr >= cBufferSize ) 60 | { 61 | cBufferLastPtr = 0; 62 | } 63 | 64 | //write data 65 | cBufferData[cBufferLastPtr] = elementVal; 66 | 67 | //increase length up to cBufferSize 68 | if( cBufferElementsUsed < cBufferSize ) 69 | { 70 | cBufferElementsUsed++; 71 | } 72 | } 73 | 74 | //Averages the last n numbers and provides that. Discards fractions 75 | float CircularBuffer::averageLast( uint16_t numElements ) 76 | { 77 | if( numElements < recordLength() ) 78 | { 79 | numElements = recordLength(); 80 | } 81 | //Add up all the elements 82 | float accumulator = 0; 83 | int8_t i; 84 | for( i = 0; i < numElements; i++ ) 85 | { 86 | accumulator += getElement( i ); 87 | } 88 | //Divide by number of elements 89 | if( numElements != 0 ) 90 | { 91 | accumulator /= numElements; 92 | } 93 | else 94 | { 95 | accumulator = 0; 96 | } 97 | return accumulator; 98 | } 99 | 100 | //Returns the current size of the buffer 101 | uint16_t CircularBuffer::recordLength( void ) 102 | { 103 | return cBufferElementsUsed; 104 | } 105 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ######################################################## 2 | # Syntax Coloring Map for SparkFun LSM6DS3 IMU Library # 3 | ######################################################## 4 | # Class 5 | ################################################################### 6 | 7 | BME280 KEYWORD1 8 | 9 | ################################################################### 10 | # Methods and Functions 11 | ################################################################### 12 | 13 | begin KEYWORD2 14 | reset KEYWORD2 15 | 16 | readFloatPressure KEYWORD2 17 | readFloatAltitudeMeters KEYWORD2 18 | readFloatAltitudeFeet KEYWORD2 19 | readFloatHumidity KEYWORD2 20 | readTempC KEYWORD2 21 | readTempF KEYWORD2 22 | readRegisterRegion KEYWORD2 23 | readRegister KEYWORD2 24 | readRegisterInt16 KEYWORD2 25 | writeRegister KEYWORD2 26 | 27 | beginI2C KEYWORD2 28 | setFilter KEYWORD2 29 | setStandbyTime KEYWORD2 30 | setMode KEYWORD2 31 | getMode KEYWORD2 32 | setTempOverSample KEYWORD2 33 | setPressureOverSample KEYWORD2 34 | setHumidityOverSample KEYWORD2 35 | setI2CAddress KEYWORD2 36 | isMeasuring KEYWORD2 37 | setReferencePressure KEYWORD2 38 | 39 | ################################################################### 40 | # Constants 41 | ################################################################### 42 | 43 | I2C_MODE LITERAL1 44 | SPI_MODE LITERAL1 45 | BME280_DIG_T1_LSB_REG LITERAL1 46 | BME280_DIG_T1_MSB_REG LITERAL1 47 | BME280_DIG_T2_LSB_REG LITERAL1 48 | BME280_DIG_T2_MSB_REG LITERAL1 49 | BME280_DIG_T3_LSB_REG LITERAL1 50 | BME280_DIG_T3_MSB_REG LITERAL1 51 | BME280_DIG_P1_LSB_REG LITERAL1 52 | BME280_DIG_P1_MSB_REG LITERAL1 53 | BME280_DIG_P2_LSB_REG LITERAL1 54 | BME280_DIG_P2_MSB_REG LITERAL1 55 | BME280_DIG_P3_LSB_REG LITERAL1 56 | BME280_DIG_P3_MSB_REG LITERAL1 57 | BME280_DIG_P4_LSB_REG LITERAL1 58 | BME280_DIG_P4_MSB_REG LITERAL1 59 | BME280_DIG_P5_LSB_REG LITERAL1 60 | BME280_DIG_P5_MSB_REG LITERAL1 61 | BME280_DIG_P6_LSB_REG LITERAL1 62 | BME280_DIG_P6_MSB_REG LITERAL1 63 | BME280_DIG_P7_LSB_REG LITERAL1 64 | BME280_DIG_P7_MSB_REG LITERAL1 65 | BME280_DIG_P8_LSB_REG LITERAL1 66 | BME280_DIG_P8_MSB_REG LITERAL1 67 | BME280_DIG_P9_LSB_REG LITERAL1 68 | BME280_DIG_P9_MSB_REG LITERAL1 69 | BME280_DIG_H1_REG LITERAL1 70 | BME280_CHIP_ID_REG LITERAL1 71 | BME280_RST_REG LITERAL1 72 | BME280_DIG_H2_LSB_REG LITERAL1 73 | BME280_DIG_H2_MSB_REG LITERAL1 74 | BME280_DIG_H3_REG LITERAL1 75 | BME280_DIG_H4_MSB_REG LITERAL1 76 | BME280_DIG_H4_LSB_REG LITERAL1 77 | BME280_DIG_H5_MSB_REG LITERAL1 78 | BME280_DIG_H6_REG LITERAL1 79 | BME280_CTRL_HUMIDITY_REG LITERAL1 80 | BME280_STAT_REG LITERAL1 81 | BME280_CTRL_MEAS_REG LITERAL1 82 | BME280_CONFIG_REG LITERAL1 83 | BME280_PRESSURE_MSB_REG LITERAL1 84 | BME280_PRESSURE_LSB_REG LITERAL1 85 | BME280_PRESSURE_XLSB_REG LITERAL1 86 | BME280_TEMPERATURE_MSB_REG LITERAL1 87 | BME280_TEMPERATURE_LSB_REG LITERAL1 88 | BME280_TEMPERATURE_XLSB_REG LITERAL1 89 | BME280_HUMIDITY_MSB_REG LITERAL1 90 | BME280_HUMIDITY_LSB_REG LITERAL1 91 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | SparkFun License Information 2 | ============================ 3 | 4 | SparkFun uses two different licenses for our files - one for hardware and one for code. 5 | 6 | Hardware 7 | --------- 8 | 9 | **SparkFun hardware is released under [Creative Commons Share-alike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/).** 10 | 11 | Note: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-sa/4.0/legalcode). 12 | 13 | You are free to: 14 | 15 | Share — copy and redistribute the material in any medium or format 16 | Adapt — remix, transform, and build upon the material 17 | for any purpose, even commercially. 18 | The licensor cannot revoke these freedoms as long as you follow the license terms. 19 | Under the following terms: 20 | 21 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 22 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 23 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | Notices: 25 | 26 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 27 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 28 | 29 | 30 | Code 31 | -------- 32 | 33 | **SparkFun code, firmware, and software is released under the [MIT License](http://opensource.org/licenses/MIT).** 34 | 35 | The MIT License (MIT) 36 | 37 | Copyright (c) 2015 SparkFun Electronics 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy 40 | of this software and associated documentation files (the "Software"), to deal 41 | in the Software without restriction, including without limitation the rights 42 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | copies of the Software, and to permit persons to whom the Software is 44 | furnished to do so, subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun BME280 Arduino Library 2 | ======================================== 3 | 4 | ![SparkFun BME280 Breakout](https://cdn.sparkfun.com//assets/parts/1/2/3/2/9/14348-01.jpg) 5 | 6 | [*SparkFun CCS811/BME280 Combo (SEN-14348)*](https://www.sparkfun.com/products/14348) 7 | 8 | This library allows the user to: 9 | 10 | * Read pressure in Pa 11 | * Read temperature in C 12 | * Read humidity in %RH 13 | 14 | It also provides the following mathematical functions based from the above. 15 | 16 | * Read temperature in F 17 | * Read altitude in meters 18 | * Read altitude in feet 19 | 20 | Some examples include a circular buffer class for averaging. 21 | 22 | Thanks to: 23 | * calvin1564 for [fixing a name collision](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/34) 24 | * LukaHitH for adding [BMP280 support](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/23) 25 | * cdonate for adding [burst read](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/50) 26 | * jdavid for integrating [math.h](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/pull/49) 27 | 28 | Repository Contents 29 | ------------------- 30 | 31 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 32 | * **/extras** - Additional documentation for the user. These files are ignored by the IDE. 33 | * **/src** - Source files for the library (.cpp, .h). 34 | * **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 35 | * **library.properties** - General library properties for the Arduino package manager. 36 | 37 | Documentation 38 | -------------- 39 | 40 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 41 | * **Product Repositories:** (including hardware files) 42 | * [SparkFun BME280 Breakout](https://github.com/sparkfun/BME280-Breakout-Board) - Original product repository 43 | * [SparkFun Environmental Combo Breakout - CCS811/BME280 (Qwiic)](https://www.sparkfun.com/products/14348) 44 | * [SparkFun Atmospheric Sensor Breakout - BME280 (Qwiic)](https://github.com/sparkfun/Qwiic_Atmospheric_Sensor_Breakout_BME280) 45 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/sparkfun-bme280-breakout-hookup-guide)** - Basic hookup guide for the SparkFun BME280 Breakout. 46 | 47 | Products that use this Library 48 | --------------------------------- 49 | 50 | * [*SEN-15440*](https://www.sparkfun.com/products/15440) 51 | * [*SEN-14348*](https://www.sparkfun.com/products/14348) 52 | * [*SEN-13676*](https://www.sparkfun.com/products/13676) 53 | 54 | Version History 55 | --------------- 56 | 57 | * [V_1.0.0](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/tree/V_1.0.0) - Public release. 58 | * [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(). 59 | * [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. 60 | * [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. 61 | 62 | 63 | License Information 64 | ------------------- 65 | 66 | This product is _**open source**_! 67 | 68 | Please review the LICENSE.md file for license information. 69 | 70 | If you have any questions or concerns on licensing, please contact techsupport@sparkfun.com. 71 | 72 | Distributed as-is; no warranty is given. 73 | 74 | - Your friends at SparkFun. 75 | -------------------------------------------------------------------------------- /examples/Example7_RelativeAltitudeChange/Example7_RelativeAltitudeChange.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Change the local altitude reference 3 | BME280 Arduino and Teensy example 4 | Marshall Taylor @ SparkFun Electronics 5 | v1.1 by Nathan Seidle @ SparkFun Electronics 6 | May 20, 2015 7 | https://github.com/sparkfun/SparkFun_BME280_Arduino_Library 8 | 9 | Feel like supporting our work? Buy a board from SparkFun! 10 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 11 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 12 | 13 | This sketch configures a BME280 to measure height changes, with a button 14 | to zero the local relative altitude. 15 | 16 | To use, run the sketch then press a button on the keyboard. The data on the 17 | serial monitor will show zero. Then, move the sensor to a new altitude and watch 18 | how the output changes! 19 | 20 | Note: For most accurate results keep the sensor orientation and temperature the 21 | same between measurements. 22 | 23 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 24 | Please review the LICENSE.md file included with this example. If you have any questions 25 | or concerns with licensing, please contact techsupport@sparkfun.com. 26 | Distributed as-is; no warranty is given. 27 | */ 28 | 29 | #include 30 | 31 | #include "SparkFunBME280.h" 32 | BME280 mySensor; 33 | 34 | #include "CircularBuffer.h" 35 | 36 | //This is a fixed-size buffer used for averaging data, a software LP filter 37 | //Depending on the settings, the response can be quite slow. 38 | CircularBuffer myBuffer(50); 39 | 40 | float localAltitude = 0; 41 | 42 | void setup() 43 | { 44 | Serial.begin(115200); 45 | while(!Serial); //Wait for user to get terminal open 46 | Serial.println("Output a local changing altitude"); 47 | Serial.println("Press any key to zero local altitude"); 48 | 49 | Wire.begin(); 50 | 51 | if (mySensor.beginI2C() == false) //Begin communication over I2C 52 | { 53 | Serial.println("The sensor did not respond. Please check wiring."); 54 | while (1); //Freeze 55 | } 56 | 57 | //filter can be off or number of FIR coefficients to use: 58 | // 0, filter off 59 | // 1, coefficients = 2 60 | // 2, coefficients = 4 61 | // 3, coefficients = 8 62 | // 4, coefficients = 16 63 | mySensor.setFilter(4); //Lots of HW filter 64 | 65 | //tempOverSample can be: 66 | // 0, skipped 67 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 68 | mySensor.setTempOverSample(5); //Set oversample to 16 69 | 70 | //pressOverSample can be: 71 | // 0, skipped 72 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 73 | mySensor.setPressureOverSample(5); //Set oversample to 16 74 | 75 | //humidOverSample can be: 76 | // 0, skipped 77 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 78 | mySensor.setHumidityOverSample(0); //Turn off humidity sensing 79 | 80 | //Assume the current reading is where we should start 81 | localAltitude = mySensor.readFloatAltitudeFeet(); //Set reference altitude 82 | 83 | for(int x = 0 ; x < 50 ; x++) 84 | myBuffer.pushElement(0); //Clear buffer 85 | } 86 | 87 | void loop() 88 | { 89 | //Get the local temperature! Do this for calibration 90 | mySensor.readTempC(); 91 | 92 | //Check to see if user pressed a button 93 | if (Serial.available() == true) 94 | { 95 | localAltitude = mySensor.readFloatAltitudeFeet(); //Set reference altitude 96 | 97 | for(int x = 0 ; x < 50 ; x++) 98 | myBuffer.pushElement(0); //Clear buffer 99 | 100 | Serial.read(); //Remove keypress from buffer 101 | Serial.println("Local altitude reset"); 102 | } 103 | 104 | float reading = mySensor.readFloatAltitudeFeet(); 105 | myBuffer.pushElement(reading - localAltitude); 106 | 107 | float tempAlt = myBuffer.averageLast(15); //Do an average of the latest samples 108 | 109 | Serial.print("Last sample: "); 110 | Serial.print(reading, 2); 111 | Serial.print(" ft"); 112 | 113 | Serial.print(" Last 15 samples averaged: "); 114 | Serial.print(tempAlt); 115 | Serial.print(" ft"); 116 | Serial.println(); 117 | delay(200); 118 | } 119 | -------------------------------------------------------------------------------- /examples/Example5_ReadAllRegisters/Example5_ReadAllRegisters.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Read all the regigsters of the BME280 3 | BME280 Arduino and Teensy example 4 | Marshall Taylor @ SparkFun Electronics 5 | May 20, 2015 6 | 7 | Feel like supporting our work? Buy a board from SparkFun! 8 | https://www.sparkfun.com/products/14348 - Qwiic Combo Board 9 | https://www.sparkfun.com/products/13676 - BME280 Breakout Board 10 | 11 | This example outputs all the functional registers from the BME280. This can be handy 12 | for troubleshooting. 13 | 14 | This sketch configures the BME280 to read all measurements. The sketch also 15 | displays the BME280's physical memory and what the driver perceives the 16 | calibration words to be. 17 | */ 18 | 19 | #include 20 | 21 | #include "SparkFunBME280.h" 22 | BME280 mySensor; 23 | 24 | void setup() 25 | { 26 | Serial.begin(115200); 27 | while(!Serial); //Needed for printing correctly when using a Teensy 28 | Serial.println("Reading all registers from BME280"); 29 | 30 | Wire.begin(); 31 | 32 | if (mySensor.beginI2C() == false) //Begin communication over I2C 33 | { 34 | Serial.println("The sensor did not respond. Please check wiring."); 35 | while (1); //Freeze 36 | } 37 | 38 | Serial.print("ID(0xD0): "); 39 | printyPrintHex(mySensor.readRegister(BME280_CHIP_ID_REG)); 40 | 41 | Serial.print("Reset register(0xE0): "); 42 | printyPrintHex(mySensor.readRegister(BME280_RST_REG)); 43 | 44 | Serial.print("ctrl_meas(0xF4): "); 45 | printyPrintHex(mySensor.readRegister(BME280_CTRL_MEAS_REG)); 46 | 47 | Serial.print("ctrl_hum(0xF2): "); 48 | printyPrintHex(mySensor.readRegister(BME280_CTRL_HUMIDITY_REG)); 49 | 50 | Serial.println(); 51 | 52 | Serial.println("Displaying all regs:"); 53 | byte memCounter = 0x80; 54 | for (byte row = 8 ; row < 16 ; row++) 55 | { 56 | Serial.print("0x"); 57 | Serial.print(row, HEX); 58 | Serial.print("0:"); 59 | 60 | for (byte column = 0 ; column < 16 ; column++) 61 | { 62 | byte tempReadData = mySensor.readRegister(memCounter); 63 | 64 | if(tempReadData < 0x10) Serial.print("0"); 65 | Serial.print(tempReadData, HEX); 66 | Serial.print(" "); 67 | 68 | memCounter++; 69 | } 70 | Serial.println(); 71 | } 72 | 73 | Serial.println(); 74 | 75 | Serial.println("Displaying concatenated calibration words:"); 76 | Serial.print("dig_T1, uint16: "); 77 | Serial.println(mySensor.calibration.dig_T1); 78 | Serial.print("dig_T2, int16: "); 79 | Serial.println(mySensor.calibration.dig_T2); 80 | Serial.print("dig_T3, int16: "); 81 | Serial.println(mySensor.calibration.dig_T3); 82 | 83 | Serial.print("dig_P1, uint16: "); 84 | Serial.println(mySensor.calibration.dig_P1); 85 | Serial.print("dig_P2, int16: "); 86 | Serial.println(mySensor.calibration.dig_P2); 87 | Serial.print("dig_P3, int16: "); 88 | Serial.println(mySensor.calibration.dig_P3); 89 | Serial.print("dig_P4, int16: "); 90 | Serial.println(mySensor.calibration.dig_P4); 91 | Serial.print("dig_P5, int16: "); 92 | Serial.println(mySensor.calibration.dig_P5); 93 | Serial.print("dig_P6, int16: "); 94 | Serial.println(mySensor.calibration.dig_P6); 95 | Serial.print("dig_P7, int16: "); 96 | Serial.println(mySensor.calibration.dig_P7); 97 | Serial.print("dig_P8, int16: "); 98 | Serial.println(mySensor.calibration.dig_P8); 99 | Serial.print("dig_P9, int16: "); 100 | Serial.println(mySensor.calibration.dig_P9); 101 | 102 | Serial.print("dig_H1, uint8: "); 103 | Serial.println(mySensor.calibration.dig_H1); 104 | Serial.print("dig_H2, int16: "); 105 | Serial.println(mySensor.calibration.dig_H2); 106 | Serial.print("dig_H3, uint8: "); 107 | Serial.println(mySensor.calibration.dig_H3); 108 | Serial.print("dig_H4, int16: "); 109 | Serial.println(mySensor.calibration.dig_H4); 110 | Serial.print("dig_H5, int16: "); 111 | Serial.println(mySensor.calibration.dig_H5); 112 | Serial.print("dig_H6, int8: "); 113 | Serial.println(mySensor.calibration.dig_H6); 114 | 115 | Serial.println(); 116 | } 117 | 118 | void loop() 119 | { 120 | //Each loop, take a reading. 121 | Serial.print("Humidity: "); 122 | Serial.print(mySensor.readFloatHumidity(), 0); 123 | 124 | Serial.print(" Pressure: "); 125 | Serial.print(mySensor.readFloatPressure(), 0); 126 | 127 | Serial.print(" Alt: "); 128 | //Serial.print(mySensor.readFloatAltitudeMeters(), 1); 129 | Serial.print(mySensor.readFloatAltitudeFeet(), 1); 130 | 131 | Serial.print(" Temp: "); 132 | //Serial.print(mySensor.readTempC(), 2); 133 | Serial.print(mySensor.readTempF(), 2); 134 | 135 | Serial.println(); 136 | 137 | delay(1000); 138 | } 139 | 140 | //Given a value, print it in HEX with leading 0x and any leading 0s 141 | void printyPrintHex(byte value) 142 | { 143 | Serial.print("0x"); 144 | if (value < 0x10) Serial.print("0"); 145 | Serial.println(value, HEX); 146 | } 147 | 148 | -------------------------------------------------------------------------------- /examples/More_Advanced/I2C_and_SPI_Multisensor/I2C_and_SPI_Multisensor.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | I2C_and_SPI_Multisensor.ino 3 | BME280 Arduino and Teensy example 4 | Marshall Taylor @ SparkFun Electronics 5 | May 20, 2015 6 | https://github.com/sparkfun/SparkFun_BME280_Arduino_Library 7 | 8 | This sketch configures two BME280 breakouts. One is configured as I2C and 9 | the other as SPI. Data from both are displayed. 10 | 11 | Sensor A is I2C and connected through A4 and A5 (SDA/SCL) 12 | Sensor B is SPI and connected through pins 10, 11, 12, and 13 through a 13 | level shifter, with pin 10 being used for chip select. 14 | 15 | Resources: 16 | Uses Wire.h for I2C operation 17 | Uses SPI.h for SPI operation 18 | 19 | Development environment specifics: 20 | Arduino IDE 1.6.4 21 | Teensy loader 1.23 22 | 23 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 24 | Please review the LICENSE.md file included with this example. If you have any questions 25 | or concerns with licensing, please contact techsupport@sparkfun.com. 26 | Distributed as-is; no warranty is given. 27 | ******************************************************************************/ 28 | 29 | #include 30 | #include "SparkFunBME280.h" 31 | 32 | #include "Wire.h" 33 | #include "SPI.h" 34 | 35 | //Global sensor object 36 | BME280 mySensorA; 37 | BME280 mySensorB; 38 | 39 | void setup() 40 | { 41 | //***Set up sensor 'A'******************************// 42 | //commInterface can be I2C_MODE or SPI_MODE 43 | mySensorA.settings.commInterface = I2C_MODE; 44 | mySensorA.settings.I2CAddress = 0x77; 45 | mySensorA.settings.runMode = 3; // 3, Normal mode 46 | mySensorA.settings.tStandby = 0; // 0, 0.5ms 47 | mySensorA.settings.filter = 0; // 0, filter off 48 | //tempOverSample can be: 49 | // 0, skipped 50 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 51 | mySensorA.settings.tempOverSample = 1; 52 | //pressOverSample can be: 53 | // 0, skipped 54 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 55 | mySensorA.settings.pressOverSample = 1; 56 | //humidOverSample can be: 57 | // 0, skipped 58 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 59 | mySensorA.settings.humidOverSample = 1; 60 | 61 | 62 | 63 | 64 | //***Set up sensor 'B'******************************// 65 | //commInterface can be I2C_MODE or SPI_MODE 66 | //specify chipSelectPin using arduino pin names 67 | //specify I2C address. Can be 0x77(default) or 0x76 68 | mySensorB.settings.commInterface = SPI_MODE; 69 | mySensorB.settings.chipSelectPin = 10; 70 | mySensorB.settings.runMode = 3; // 3, Normal mode 71 | mySensorB.settings.tStandby = 0; // 0, 0.5ms 72 | mySensorB.settings.filter = 0; // 0, filter off 73 | //tempOverSample can be: 74 | // 0, skipped 75 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 76 | mySensorB.settings.tempOverSample = 1; 77 | //pressOverSample can be: 78 | // 0, skipped 79 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 80 | mySensorB.settings.pressOverSample = 1; 81 | //humidOverSample can be: 82 | // 0, skipped 83 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 84 | mySensorB.settings.humidOverSample = 1; 85 | 86 | 87 | 88 | //***Initialize the things**************************// 89 | Serial.begin(57600); 90 | Serial.print("Program Started\n"); 91 | Serial.println("Starting BME280s... result of .begin():"); 92 | delay(10); //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up. 93 | //Calling .begin() causes the settings to be loaded 94 | Serial.print("Sensor A: 0x"); 95 | Serial.println(mySensorA.begin(), HEX); 96 | Serial.print("Sensor B: 0x"); 97 | Serial.println(mySensorB.begin(), HEX); 98 | 99 | 100 | } 101 | 102 | void loop() 103 | { 104 | //Start with temperature, as that data is needed for accurate compensation. 105 | //Reading the temperature updates the compensators of the other functions 106 | //in the background. 107 | Serial.print("Temperature: "); 108 | Serial.print(mySensorA.readTempC(), 2); 109 | Serial.print(", "); 110 | Serial.print(mySensorB.readTempC(), 2); 111 | Serial.println(" degrees C"); 112 | 113 | Serial.print("Temperature: "); 114 | Serial.print(mySensorA.readTempF(), 2); 115 | Serial.print(", "); 116 | Serial.print(mySensorB.readTempF(), 2); 117 | Serial.println(" degrees F"); 118 | 119 | Serial.print("Pressure: "); 120 | Serial.print(mySensorA.readFloatPressure(), 2); 121 | Serial.print(", "); 122 | Serial.print(mySensorB.readFloatPressure(), 2); 123 | Serial.println(" Pa"); 124 | 125 | Serial.print("Altitude: "); 126 | Serial.print(mySensorA.readFloatAltitudeMeters(), 2); 127 | Serial.print(", "); 128 | Serial.print(mySensorB.readFloatAltitudeMeters(), 2); 129 | Serial.println("m"); 130 | 131 | Serial.print("Altitude: "); 132 | Serial.print(mySensorA.readFloatAltitudeFeet(), 2); 133 | Serial.print(", "); 134 | Serial.print(mySensorB.readFloatAltitudeFeet(), 2); 135 | Serial.println("ft"); 136 | 137 | Serial.print("%RH: "); 138 | Serial.print(mySensorA.readFloatHumidity(), 2); 139 | Serial.print(", "); 140 | Serial.print(mySensorB.readFloatHumidity(), 2); 141 | Serial.println(" %"); 142 | 143 | Serial.println(); 144 | 145 | delay(1000); 146 | 147 | } 148 | -------------------------------------------------------------------------------- /examples/More_Advanced/LCD_DeltaAltitude/LCD_DeltaAltitude.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | LCD_DeltaAltitude.ino 3 | BME280 Arduino and Teensy example 4 | Marshall Taylor @ SparkFun Electronics 5 | Oct 19, 2015 6 | https://github.com/sparkfun/SparkFun_BME280_Arduino_Library 7 | 8 | This sketch configures a BME280 to measure height changes, with a button 9 | to zero. 10 | 11 | Hardware connections: 12 | BME280 -> Arduino 13 | GND -> GND 14 | 3.3 -> 3.3 15 | SDA -> A4 16 | SCL -> A5 17 | 18 | Button (Normally open) between A4 and A5. 19 | 20 | LCD: 21 | * LCD RS pin to digital pin 7 22 | * LCD Enable pin to digital 6 23 | * LCD D4 pin to digital pin 5 24 | * LCD D5 pin to digital pin 4 25 | * LCD D6 pin to digital pin 3 26 | * LCD D7 pin to digital pin 2 27 | * LCD R/W pin to ground 28 | * 10K resistor: 29 | * ends to +5V and ground 30 | * wiper to LCD VO pin (pin 3) 31 | 32 | To use, run the sketch, then press and hold the button until the data on the 33 | serial monitor shows zero. Then, move the sensor to a new altitude and watch 34 | how the output changes! 35 | 36 | Note: For most accurate results keep the sensor orientation and temperature the 37 | same between measurements. 38 | 39 | Resources: 40 | Uses Wire.h for I2C operation 41 | Uses SPI.h for SPI operation 42 | Included CircularBuffer class for averaging 43 | 44 | Development environment specifics: 45 | Arduino IDE 1.6.4 46 | Teensy loader 1.23 47 | 48 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 49 | Please review the LICENSE.md file included with this example. If you have any questions 50 | or concerns with licensing, please contact techsupport@sparkfun.com. 51 | Distributed as-is; no warranty is given. 52 | ******************************************************************************/ 53 | 54 | #include 55 | #include "SparkFunBME280.h" 56 | #include "CircularBuffer.h" 57 | 58 | #include "Wire.h" 59 | #include "SPI.h" 60 | #include 61 | 62 | //Global sensor object 63 | BME280 mySensor; 64 | uint8_t buttonGroundPin = A0; 65 | uint8_t buttonSensePin = A2; 66 | 67 | CircularBuffer myBuffer(50); 68 | //int icounter = 0; 69 | float reference = 0; 70 | 71 | LiquidCrystal lcd(7,6,5,4,3,2); 72 | 73 | void setup() 74 | { 75 | //Configure the button IO 76 | pinMode( buttonSensePin, INPUT_PULLUP ); 77 | pinMode( buttonGroundPin, OUTPUT ); 78 | digitalWrite( buttonGroundPin, 0 ); 79 | 80 | //***Driver settings********************************// 81 | //commInterface can be I2C_MODE or SPI_MODE 82 | //specify chipSelectPin using arduino pin names 83 | //specify I2C address. Can be 0x77(default) or 0x76 84 | 85 | //For I2C, enable the following and disable the SPI section 86 | mySensor.settings.commInterface = I2C_MODE; 87 | mySensor.settings.I2CAddress = 0x77; 88 | 89 | //For SPI enable the following and dissable the I2C section 90 | //mySensor.settings.commInterface = SPI_MODE; 91 | //mySensor.settings.chipSelectPin = 10; 92 | 93 | 94 | //***Operation settings*****************************// 95 | 96 | //renMode can be: 97 | // 0, Sleep mode 98 | // 1 or 2, Forced mode 99 | // 3, Normal mode 100 | mySensor.settings.runMode = 3; //Forced mode 101 | 102 | //tStandby can be: 103 | // 0, 0.5ms 104 | // 1, 62.5ms 105 | // 2, 125ms 106 | // 3, 250ms 107 | // 4, 500ms 108 | // 5, 1000ms 109 | // 6, 10ms 110 | // 7, 20ms 111 | mySensor.settings.tStandby = 0; 112 | 113 | //filter can be off or number of FIR coefficients to use: 114 | // 0, filter off 115 | // 1, coefficients = 2 116 | // 2, coefficients = 4 117 | // 3, coefficients = 8 118 | // 4, coefficients = 16 119 | mySensor.settings.filter = 4; 120 | 121 | //tempOverSample can be: 122 | // 0, skipped 123 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 124 | mySensor.settings.tempOverSample = 5; 125 | 126 | //pressOverSample can be: 127 | // 0, skipped 128 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 129 | mySensor.settings.pressOverSample = 5; 130 | 131 | //humidOverSample can be: 132 | // 0, skipped 133 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 134 | mySensor.settings.humidOverSample = 0; 135 | 136 | Serial.begin(57600); 137 | Serial.print("Program Started\n"); 138 | Serial.print("Starting BME280... result of .begin(): 0x"); 139 | //Calling .begin() causes the settings to be loaded 140 | delay(10);//Needs > 2 ms to start up 141 | Serial.println(mySensor.begin(), HEX); 142 | 143 | Serial.println(); 144 | 145 | lcd.begin(16, 2); 146 | 147 | lcd.clear(); 148 | 149 | } 150 | 151 | void loop() 152 | { 153 | //Get the local temperature! Do this for calibration 154 | mySensor.readTempC(); 155 | 156 | //Check button. No debounce, so hold for operation 157 | if( digitalRead( buttonSensePin ) == 0 ) 158 | { 159 | //Set reference altitude. 160 | reference = mySensor.readFloatAltitudeFeet(); 161 | } 162 | 163 | float lastAlt = mySensor.readFloatAltitudeFeet() - reference; 164 | myBuffer.pushElement(lastAlt); 165 | float tempAlt = myBuffer.averageLast(8); //Do an average of the latest samples 166 | 167 | lcd.setCursor(0,0); 168 | lcd.print("Altitude: "); 169 | 170 | myBuffer.pushElement(lastAlt); 171 | 172 | lcd.setCursor(0,1); 173 | if(tempAlt >= 0) 174 | { 175 | lcd.print(" "); 176 | } 177 | lcd.print(tempAlt); 178 | lcd.print(" ft "); 179 | delay(200); 180 | 181 | } 182 | -------------------------------------------------------------------------------- /examples/More_Advanced/LCD_PressureTemperature/LCD_PressureTemperature.ino: -------------------------------------------------------------------------------- 1 | /*BME280 Arduino and Teensy example 2 | Marshall Taylor @ SparkFun Electronics 3 | Oct 19, 2015 4 | https://github.com/sparkfun/SparkFun_BME280_Arduino_Library 5 | 6 | This sketch displays the pressure in pascals and temperature 7 | in fahrenheit. 8 | 9 | Resources: 10 | Uses Wire.h for I2C operation 11 | Uses SPI.h for SPI operation 12 | 13 | Hardware connections: 14 | BME280 -> Arduino 15 | GND -> GND 16 | 3.3 -> 3.3 17 | SDA -> A4 18 | SCL -> A5 19 | 20 | LCD: 21 | * LCD RS pin to digital pin 7 22 | * LCD Enable pin to digital 6 23 | * LCD D4 pin to digital pin 5 24 | * LCD D5 pin to digital pin 4 25 | * LCD D6 pin to digital pin 3 26 | * LCD D7 pin to digital pin 2 27 | * LCD R/W pin to ground 28 | * 10K resistor: 29 | * ends to +5V and ground 30 | * wiper to LCD VO pin (pin 3) 31 | 32 | Development environment specifics: 33 | Arduino IDE 1.6.4 34 | Teensy loader 1.23 35 | 36 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 37 | Please review the LICENSE.md file included with this example. If you have any questions 38 | or concerns with licensing, please contact techsupport@sparkfun.com. 39 | Distributed as-is; no warranty is given. 40 | ******************************************************************************/ 41 | 42 | 43 | // Load the LiquidCrystal library, which will give us 44 | // commands to interface to the LCD: 45 | 46 | #include 47 | 48 | // Initialize the library with the pins we're using. 49 | // (Note that you can use different pins if needed.) 50 | // See http://arduino.cc/en/Reference/LiquidCrystal 51 | // for more information: 52 | 53 | 54 | #include 55 | #include "SparkFunBME280.h" 56 | //Library allows either I2C or SPI, so include both. 57 | #include "Wire.h" 58 | #include "SPI.h" 59 | 60 | //Global sensor object 61 | BME280 mySensor; 62 | 63 | LiquidCrystal lcd(7,6,5,4,3,2); 64 | 65 | void setup() 66 | { 67 | lcd.begin(16, 2); 68 | lcd.clear(); 69 | 70 | //***Driver settings********************************// 71 | //commInterface can be I2C_MODE or SPI_MODE 72 | //specify chipSelectPin using arduino pin names 73 | //specify I2C address. Can be 0x77(default) or 0x76 74 | 75 | //For I2C, enable the following and disable the SPI section 76 | mySensor.settings.commInterface = I2C_MODE; 77 | mySensor.settings.I2CAddress = 0x77; 78 | 79 | //For SPI enable the following and dissable the I2C section 80 | //mySensor.settings.commInterface = SPI_MODE; 81 | //mySensor.settings.chipSelectPin = 10; 82 | 83 | 84 | //***Operation settings*****************************// 85 | 86 | //renMode can be: 87 | // 0, Sleep mode 88 | // 1 or 2, Forced mode 89 | // 3, Normal mode 90 | mySensor.settings.runMode = 3; //Forced mode 91 | 92 | //tStandby can be: 93 | // 0, 0.5ms 94 | // 1, 62.5ms 95 | // 2, 125ms 96 | // 3, 250ms 97 | // 4, 500ms 98 | // 5, 1000ms 99 | // 6, 10ms 100 | // 7, 20ms 101 | mySensor.settings.tStandby = 0; 102 | 103 | //filter can be off or number of FIR coefficients to use: 104 | // 0, filter off 105 | // 1, coefficients = 2 106 | // 2, coefficients = 4 107 | // 3, coefficients = 8 108 | // 4, coefficients = 16 109 | mySensor.settings.filter = 0; 110 | 111 | //tempOverSample can be: 112 | // 0, skipped 113 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 114 | mySensor.settings.tempOverSample = 1; 115 | 116 | //pressOverSample can be: 117 | // 0, skipped 118 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 119 | mySensor.settings.pressOverSample = 1; 120 | 121 | //humidOverSample can be: 122 | // 0, skipped 123 | // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively 124 | mySensor.settings.humidOverSample = 1; 125 | 126 | Serial.begin(57600); 127 | Serial.print("Program Started\n"); 128 | Serial.print("Starting BME280... result of .begin(): 0x"); 129 | 130 | //Calling .begin() causes the settings to be loaded 131 | Serial.println(mySensor.begin(), HEX); 132 | delay(10); //Use delay if reading directly after .begin is called. BME280 requires 2ms to start up. 133 | 134 | Serial.print("Displaying ID, reset and ctrl regs\n"); 135 | 136 | Serial.print("ID(0xD0): 0x"); 137 | Serial.println(mySensor.readRegister(BME280_CHIP_ID_REG), HEX); 138 | Serial.print("Reset register(0xE0): 0x"); 139 | Serial.println(mySensor.readRegister(BME280_RST_REG), HEX); 140 | Serial.print("ctrl_meas(0xF4): 0x"); 141 | Serial.println(mySensor.readRegister(BME280_CTRL_MEAS_REG), HEX); 142 | Serial.print("ctrl_hum(0xF2): 0x"); 143 | Serial.println(mySensor.readRegister(BME280_CTRL_HUMIDITY_REG), HEX); 144 | 145 | Serial.print("\n\n"); 146 | 147 | Serial.print("Displaying all regs\n"); 148 | uint8_t memCounter = 0x80; 149 | uint8_t tempReadData; 150 | for(int rowi = 8; rowi < 16; rowi++ ) 151 | { 152 | Serial.print("0x"); 153 | Serial.print(rowi, HEX); 154 | Serial.print("0:"); 155 | for(int coli = 0; coli < 16; coli++ ) 156 | { 157 | tempReadData = mySensor.readRegister(memCounter); 158 | Serial.print((tempReadData >> 4) & 0x0F, HEX);//Print first hex nibble 159 | Serial.print(tempReadData & 0x0F, HEX);//Print second hex nibble 160 | Serial.print(" "); 161 | memCounter++; 162 | } 163 | Serial.print("\n"); 164 | } 165 | 166 | 167 | Serial.print("\n\n"); 168 | 169 | Serial.print("Displaying concatenated calibration words\n"); 170 | Serial.print("dig_T1, uint16: "); 171 | Serial.println(mySensor.calibration.dig_T1); 172 | Serial.print("dig_T2, int16: "); 173 | Serial.println(mySensor.calibration.dig_T2); 174 | Serial.print("dig_T3, int16: "); 175 | Serial.println(mySensor.calibration.dig_T3); 176 | 177 | Serial.print("dig_P1, uint16: "); 178 | Serial.println(mySensor.calibration.dig_P1); 179 | Serial.print("dig_P2, int16: "); 180 | Serial.println(mySensor.calibration.dig_P2); 181 | Serial.print("dig_P3, int16: "); 182 | Serial.println(mySensor.calibration.dig_P3); 183 | Serial.print("dig_P4, int16: "); 184 | Serial.println(mySensor.calibration.dig_P4); 185 | Serial.print("dig_P5, int16: "); 186 | Serial.println(mySensor.calibration.dig_P5); 187 | Serial.print("dig_P6, int16: "); 188 | Serial.println(mySensor.calibration.dig_P6); 189 | Serial.print("dig_P7, int16: "); 190 | Serial.println(mySensor.calibration.dig_P7); 191 | Serial.print("dig_P8, int16: "); 192 | Serial.println(mySensor.calibration.dig_P8); 193 | Serial.print("dig_P9, int16: "); 194 | Serial.println(mySensor.calibration.dig_P9); 195 | 196 | Serial.print("dig_H1, uint8: "); 197 | Serial.println(mySensor.calibration.dig_H1); 198 | Serial.print("dig_H2, int16: "); 199 | Serial.println(mySensor.calibration.dig_H2); 200 | Serial.print("dig_H3, uint8: "); 201 | Serial.println(mySensor.calibration.dig_H3); 202 | Serial.print("dig_H4, int16: "); 203 | Serial.println(mySensor.calibration.dig_H4); 204 | Serial.print("dig_H5, int16: "); 205 | Serial.println(mySensor.calibration.dig_H5); 206 | Serial.print("dig_H6, int8: "); 207 | Serial.println(mySensor.calibration.dig_H6); 208 | 209 | Serial.println(); 210 | } 211 | 212 | void loop() 213 | { 214 | //Get the local temperature! Do this for calibration 215 | mySensor.readTempC(); 216 | 217 | lcd.setCursor(0,0); 218 | lcd.print("Press: "); 219 | lcd.print((uint32_t)mySensor.readFloatPressure()); 220 | lcd.print(" Pa"); 221 | 222 | lcd.setCursor(0,1); 223 | lcd.print("Humid: "); 224 | lcd.print((uint8_t)mySensor.readFloatHumidity()); 225 | lcd.print(" %"); 226 | 227 | 228 | delay(1000); 229 | 230 | } 231 | -------------------------------------------------------------------------------- /src/SparkFunBME280.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | SparkFunBME280.h 3 | BME280 Arduino and Teensy Driver 4 | Marshall Taylor @ SparkFun Electronics 5 | May 20, 2015 6 | https://github.com/sparkfun/BME280_Breakout 7 | 8 | Resources: 9 | Uses Wire.h for i2c operation 10 | Uses SPI.h for SPI operation 11 | 12 | Development environment specifics: 13 | Arduino IDE 1.6.4 14 | Teensy loader 1.23 15 | 16 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 17 | Please review the LICENSE.md file included with this example. If you have any questions 18 | or concerns with licensing, please contact techsupport@sparkfun.com. 19 | Distributed as-is; no warranty is given. 20 | 21 | TODO: 22 | roll library ver to 2.0 23 | remove hard wire. 24 | write escalating examples 25 | 26 | 27 | ******************************************************************************/ 28 | 29 | // Test derived class for base class SparkFunIMU 30 | #ifndef __BME280_H__ 31 | #define __BME280_H__ 32 | 33 | #if (ARDUINO >= 100) 34 | #include "Arduino.h" 35 | #else 36 | #include "WProgram.h" 37 | #endif 38 | 39 | #include 40 | #include 41 | 42 | // Uncomment the following line to enable software I2C 43 | // You will need to have the SoftwareWire library installed 44 | // #include //SoftwareWire by Testato. Installed from library manager. 45 | 46 | #define kSfeI2CMode 0 47 | #define kSfeSPIMode 1 48 | 49 | #ifndef BME280_SPI_CLOCK 50 | #ifdef ARDUINO_ARCH_ESP32 51 | #define BME280_SPI_CLOCK 1000000 52 | #else 53 | #define BME280_SPI_CLOCK 500000 54 | #endif 55 | #endif 56 | 57 | #ifndef BME280_SPI_MODE 58 | #define BME280_SPI_MODE SPI_MODE0 59 | #endif 60 | 61 | #define NO_WIRE 0 62 | #define HARD_WIRE 1 63 | #define SOFT_WIRE 2 64 | 65 | #define MODE_SLEEP 0b00 66 | #define MODE_FORCED 0b01 67 | #define MODE_NORMAL 0b11 68 | 69 | // Register names: 70 | #define BME280_DIG_T1_LSB_REG 0x88 71 | #define BME280_DIG_T1_MSB_REG 0x89 72 | #define BME280_DIG_T2_LSB_REG 0x8A 73 | #define BME280_DIG_T2_MSB_REG 0x8B 74 | #define BME280_DIG_T3_LSB_REG 0x8C 75 | #define BME280_DIG_T3_MSB_REG 0x8D 76 | #define BME280_DIG_P1_LSB_REG 0x8E 77 | #define BME280_DIG_P1_MSB_REG 0x8F 78 | #define BME280_DIG_P2_LSB_REG 0x90 79 | #define BME280_DIG_P2_MSB_REG 0x91 80 | #define BME280_DIG_P3_LSB_REG 0x92 81 | #define BME280_DIG_P3_MSB_REG 0x93 82 | #define BME280_DIG_P4_LSB_REG 0x94 83 | #define BME280_DIG_P4_MSB_REG 0x95 84 | #define BME280_DIG_P5_LSB_REG 0x96 85 | #define BME280_DIG_P5_MSB_REG 0x97 86 | #define BME280_DIG_P6_LSB_REG 0x98 87 | #define BME280_DIG_P6_MSB_REG 0x99 88 | #define BME280_DIG_P7_LSB_REG 0x9A 89 | #define BME280_DIG_P7_MSB_REG 0x9B 90 | #define BME280_DIG_P8_LSB_REG 0x9C 91 | #define BME280_DIG_P8_MSB_REG 0x9D 92 | #define BME280_DIG_P9_LSB_REG 0x9E 93 | #define BME280_DIG_P9_MSB_REG 0x9F 94 | #define BME280_DIG_H1_REG 0xA1 95 | #define BME280_CHIP_ID_REG 0xD0 // Chip ID 96 | #define BME280_RST_REG 0xE0 // Softreset Reg 97 | #define BME280_DIG_H2_LSB_REG 0xE1 98 | #define BME280_DIG_H2_MSB_REG 0xE2 99 | #define BME280_DIG_H3_REG 0xE3 100 | #define BME280_DIG_H4_MSB_REG 0xE4 101 | #define BME280_DIG_H4_LSB_REG 0xE5 102 | #define BME280_DIG_H5_MSB_REG 0xE6 103 | #define BME280_DIG_H6_REG 0xE7 104 | #define BME280_CTRL_HUMIDITY_REG 0xF2 // Ctrl Humidity Reg 105 | #define BME280_STAT_REG 0xF3 // Status Reg 106 | #define BME280_CTRL_MEAS_REG 0xF4 // Ctrl Measure Reg 107 | #define BME280_CONFIG_REG 0xF5 // Configuration Reg 108 | #define BME280_MEASUREMENTS_REG 0xF7 // Measurements register start 109 | #define BME280_PRESSURE_MSB_REG 0xF7 // Pressure MSB 110 | #define BME280_PRESSURE_LSB_REG 0xF8 // Pressure LSB 111 | #define BME280_PRESSURE_XLSB_REG 0xF9 // Pressure XLSB 112 | #define BME280_TEMPERATURE_MSB_REG 0xFA // Temperature MSB 113 | #define BME280_TEMPERATURE_LSB_REG 0xFB // Temperature LSB 114 | #define BME280_TEMPERATURE_XLSB_REG 0xFC // Temperature XLSB 115 | #define BME280_HUMIDITY_MSB_REG 0xFD // Humidity MSB 116 | #define BME280_HUMIDITY_LSB_REG 0xFE // Humidity LSB 117 | 118 | // Class BME280_SensorSettings. This object is used to hold settings data. The application 119 | // uses this classes' data directly. The settings are adopted and sent to the sensor 120 | // at special times, such as .begin. Some are used for doing math. 121 | // 122 | // This is a kind of bloated way to do this. The trade-off is that the user doesn't 123 | // need to deal with #defines or enums with bizarre names. 124 | // 125 | // A power user would strip out BME280_SensorSettings entirely, and send specific read and 126 | // write command directly to the IC. (ST #defines below) 127 | // 128 | struct BME280_SensorSettings 129 | { 130 | public: 131 | // Main Interface and mode settings 132 | uint8_t commInterface; 133 | uint8_t I2CAddress; 134 | uint8_t chipSelectPin; 135 | SPISettings spiSettings{BME280_SPI_CLOCK, MSBFIRST, BME280_SPI_MODE}; 136 | 137 | // Deprecated settings 138 | uint8_t runMode; 139 | uint8_t tStandby; 140 | uint8_t filter; 141 | uint8_t tempOverSample; 142 | uint8_t pressOverSample; 143 | uint8_t humidOverSample; 144 | float tempCorrection; // correction of temperature - added to the result 145 | }; 146 | 147 | // Used to hold the calibration constants. These are used 148 | // by the driver as measurements are being taking 149 | struct SensorCalibration 150 | { 151 | public: 152 | uint16_t dig_T1; 153 | int16_t dig_T2; 154 | int16_t dig_T3; 155 | 156 | uint16_t dig_P1; 157 | int16_t dig_P2; 158 | int16_t dig_P3; 159 | int16_t dig_P4; 160 | int16_t dig_P5; 161 | int16_t dig_P6; 162 | int16_t dig_P7; 163 | int16_t dig_P8; 164 | int16_t dig_P9; 165 | 166 | uint8_t dig_H1; 167 | int16_t dig_H2; 168 | uint8_t dig_H3; 169 | int16_t dig_H4; 170 | int16_t dig_H5; 171 | int8_t dig_H6; 172 | }; 173 | 174 | struct BME280_SensorMeasurements 175 | { 176 | public: 177 | float temperature; 178 | float pressure; 179 | float humidity; 180 | }; 181 | 182 | // This is the main operational class of the driver. 183 | 184 | class BME280 185 | { 186 | public: 187 | // settings 188 | BME280_SensorSettings settings; 189 | SensorCalibration calibration; 190 | int32_t t_fine; 191 | 192 | // Constructor generates default BME280_SensorSettings. 193 | //(over-ride after construction if desired) 194 | BME280(void); 195 | //~BME280() = default; 196 | 197 | // Call to apply BME280_SensorSettings. 198 | // This also gets the SensorCalibration constants 199 | uint8_t begin(void); 200 | bool beginSPI(uint8_t csPin, SPIClass &spiPort = SPI); // Communicate using SPI 201 | bool beginI2C(TwoWire &wirePort = Wire); // Called when user provides Wire port 202 | 203 | #ifdef SoftwareWire_h 204 | bool beginI2C(SoftwareWire &wirePort); // Called when user provides a softwareWire port 205 | #endif 206 | 207 | uint8_t getMode(void); // Get the current mode: sleep, forced, or normal 208 | void setMode(uint8_t mode); // Set the current mode 209 | 210 | void setTempOverSample(uint8_t overSampleAmount); // Set the temperature sample mode 211 | void setPressureOverSample(uint8_t overSampleAmount); // Set the pressure sample mode 212 | void setHumidityOverSample(uint8_t overSampleAmount); // Set the humidity sample mode 213 | void setStandbyTime(uint8_t timeSetting); // Set the standby time between measurements 214 | void setFilter(uint8_t filterSetting); // Set the filter 215 | 216 | void setI2CAddress(uint8_t i2caddress); // Set the address the library should use to communicate. Use if address 217 | // jumper is closed (0x76). 218 | 219 | void setReferencePressure(float refPressure); // Allows user to set local sea level reference pressure 220 | float getReferencePressure(); 221 | 222 | bool isMeasuring(void); // Returns true while the device is taking measurement 223 | 224 | // Software reset routine 225 | void reset(void); 226 | void readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t tempScale = 0); 227 | 228 | // Returns the values as floats. 229 | float readFloatPressure(void); 230 | float readFloatAltitudeMeters(void); 231 | float readFloatAltitudeFeet(void); 232 | void readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); 233 | 234 | float readFloatHumidity(void); 235 | void readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); 236 | 237 | // Temperature related methods 238 | void setTemperatureCorrection(float corr); 239 | float readTempC(void); 240 | float readTempF(void); 241 | float readTempFromBurst(uint8_t buffer[]); 242 | 243 | // Dewpoint related methods 244 | // From Pavel-Sayekat: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/pull/6/files 245 | double dewPointC(void); 246 | double dewPointF(void); 247 | 248 | // The following utilities read and write 249 | 250 | // ReadRegisterRegion takes a uint8 array address as input and reads 251 | // a chunk of memory into that array. 252 | void readRegisterRegion(uint8_t *, uint8_t, uint8_t); 253 | // readRegister reads one register 254 | uint8_t readRegister(uint8_t); 255 | // Reads two regs, LSByte then MSByte order, and concatenates them 256 | // Used for two-byte reads 257 | int16_t readRegisterInt16(uint8_t offset); 258 | // Writes a byte; 259 | void writeRegister(uint8_t, uint8_t); 260 | 261 | private: 262 | uint8_t checkSampleValue(uint8_t userValue); // Checks for valid over sample values 263 | void readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); 264 | void readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements); 265 | 266 | uint8_t _wireType = HARD_WIRE; // Default to Wire.h 267 | TwoWire *_hardPort = NO_WIRE; // The generic connection to user's chosen I2C hardware 268 | SPIClass *_spiPort = &SPI; // The generic connection to user's chosen SPI hardware 269 | 270 | #ifdef SoftwareWire_h 271 | SoftwareWire *_softPort = NO_WIRE; // Or, the generic connection to software wire port 272 | #endif 273 | 274 | float _referencePressure = 101325.0; // Default but is changeable 275 | }; 276 | 277 | #endif // End of __BME280_H__ definition check 278 | -------------------------------------------------------------------------------- /src/SparkFunBME280.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | SparkFunBME280.cpp 3 | BME280 Arduino and Teensy Driver 4 | Marshall Taylor @ SparkFun Electronics 5 | May 20, 2015 6 | https://github.com/sparkfun/BME280_Breakout 7 | 8 | Resources: 9 | Uses Wire.h for i2c operation 10 | Uses _spiPort->h for SPI operation 11 | 12 | Development environment specifics: 13 | Arduino IDE 1.8.5 14 | Teensy loader 1.23 15 | 16 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 17 | Please review the LICENSE.md file included with this example. If you have any questions 18 | or concerns with licensing, please contact techsupport@sparkfun.com. 19 | Distributed as-is; no warranty is given. 20 | ******************************************************************************/ 21 | // See SparkFunBME280.h for additional topology notes. 22 | 23 | #include "SparkFunBME280.h" 24 | #include 25 | 26 | //****************************************************************************// 27 | // 28 | // Settings and configuration 29 | // 30 | //****************************************************************************// 31 | 32 | // Constructor -- Specifies default configuration 33 | BME280::BME280(void) 34 | { 35 | // Construct with these default settings 36 | 37 | settings.commInterface = kSfeI2CMode; // Default to I2C 38 | 39 | settings.I2CAddress = 0x77; // Default, jumper open is 0x77 40 | _hardPort = &Wire; // Default to Wire port 41 | 42 | settings.chipSelectPin = 10; // Select CS pin for SPI 43 | 44 | // These are deprecated settings 45 | settings.runMode = 3; // Normal/Run 46 | settings.tStandby = 0; // 0.5ms 47 | settings.filter = 0; // Filter off 48 | settings.tempOverSample = 1; 49 | settings.pressOverSample = 1; 50 | settings.humidOverSample = 1; 51 | settings.tempCorrection = 0.f; // correction of temperature - added to the result 52 | } 53 | 54 | //****************************************************************************// 55 | // 56 | // Configuration section 57 | // 58 | // This uses the stored BME280_SensorSettings to start the IMU 59 | // Use statements such as "mySensor.settings.commInterface = SPI_MODE;" to 60 | // configure before calling .begin(); 61 | // 62 | //****************************************************************************// 63 | uint8_t BME280::begin() 64 | { 65 | delay(2); // Make sure sensor had enough time to turn on. BME280 requires 2ms to start up. 66 | 67 | // Check the settings structure values to determine how to setup the device 68 | switch (settings.commInterface) 69 | { 70 | 71 | case kSfeI2CMode: 72 | 73 | // Removing port begin from library. This should be done by user otherwise this library will overwrite Wire 74 | // settings such as clock speed. 75 | // switch(_wireType) 76 | // { 77 | // case(HARD_WIRE): 78 | // _hardPort->begin(); //The caller can begin their port and set the speed. We just confirm it here 79 | // otherwise it can be hard to debug. break; case(SOFT_WIRE): #ifdef SoftwareWire_h 80 | // _softPort->begin(); //The caller can begin their port and set the speed. We just confirm it here otherwise 81 | // it can be hard to debug. #endif break; 82 | // } 83 | break; 84 | 85 | case kSfeSPIMode: 86 | // start the SPI library: 87 | _spiPort->begin(); 88 | // initialize the data ready and chip select pins: 89 | pinMode(settings.chipSelectPin, OUTPUT); 90 | digitalWrite(settings.chipSelectPin, HIGH); 91 | break; 92 | 93 | default: 94 | break; 95 | } 96 | 97 | // Check communication with IC before anything else 98 | uint8_t chipID = readRegister(BME280_CHIP_ID_REG); // Should return 0x60 or 0x58 99 | if (chipID != 0x58 && chipID != 0x60) // Is this BMP or BME? 100 | return (chipID); // This is not BMP nor BME! 101 | 102 | // Reading all compensation data, range 0x88:A1, 0xE1:E7 103 | calibration.dig_T1 = ((uint16_t)((readRegister(BME280_DIG_T1_MSB_REG) << 8) + readRegister(BME280_DIG_T1_LSB_REG))); 104 | calibration.dig_T2 = ((int16_t)((readRegister(BME280_DIG_T2_MSB_REG) << 8) + readRegister(BME280_DIG_T2_LSB_REG))); 105 | calibration.dig_T3 = ((int16_t)((readRegister(BME280_DIG_T3_MSB_REG) << 8) + readRegister(BME280_DIG_T3_LSB_REG))); 106 | 107 | calibration.dig_P1 = ((uint16_t)((readRegister(BME280_DIG_P1_MSB_REG) << 8) + readRegister(BME280_DIG_P1_LSB_REG))); 108 | calibration.dig_P2 = ((int16_t)((readRegister(BME280_DIG_P2_MSB_REG) << 8) + readRegister(BME280_DIG_P2_LSB_REG))); 109 | calibration.dig_P3 = ((int16_t)((readRegister(BME280_DIG_P3_MSB_REG) << 8) + readRegister(BME280_DIG_P3_LSB_REG))); 110 | calibration.dig_P4 = ((int16_t)((readRegister(BME280_DIG_P4_MSB_REG) << 8) + readRegister(BME280_DIG_P4_LSB_REG))); 111 | calibration.dig_P5 = ((int16_t)((readRegister(BME280_DIG_P5_MSB_REG) << 8) + readRegister(BME280_DIG_P5_LSB_REG))); 112 | calibration.dig_P6 = ((int16_t)((readRegister(BME280_DIG_P6_MSB_REG) << 8) + readRegister(BME280_DIG_P6_LSB_REG))); 113 | calibration.dig_P7 = ((int16_t)((readRegister(BME280_DIG_P7_MSB_REG) << 8) + readRegister(BME280_DIG_P7_LSB_REG))); 114 | calibration.dig_P8 = ((int16_t)((readRegister(BME280_DIG_P8_MSB_REG) << 8) + readRegister(BME280_DIG_P8_LSB_REG))); 115 | calibration.dig_P9 = ((int16_t)((readRegister(BME280_DIG_P9_MSB_REG) << 8) + readRegister(BME280_DIG_P9_LSB_REG))); 116 | 117 | calibration.dig_H1 = ((uint8_t)(readRegister(BME280_DIG_H1_REG))); 118 | calibration.dig_H2 = ((int16_t)((readRegister(BME280_DIG_H2_MSB_REG) << 8) + readRegister(BME280_DIG_H2_LSB_REG))); 119 | calibration.dig_H3 = ((uint8_t)(readRegister(BME280_DIG_H3_REG))); 120 | calibration.dig_H4 = 121 | ((int16_t)((readRegister(BME280_DIG_H4_MSB_REG) << 4) + (readRegister(BME280_DIG_H4_LSB_REG) & 0x0F))); 122 | calibration.dig_H5 = 123 | ((int16_t)((readRegister(BME280_DIG_H5_MSB_REG) << 4) + ((readRegister(BME280_DIG_H4_LSB_REG) >> 4) & 0x0F))); 124 | calibration.dig_H6 = ((int8_t)readRegister(BME280_DIG_H6_REG)); 125 | 126 | // Most of the time the sensor will be init with default values 127 | // But in case user has old/deprecated code, use the settings.x values 128 | setStandbyTime(settings.tStandby); 129 | setFilter(settings.filter); 130 | setPressureOverSample(settings.pressOverSample); // Default of 1x oversample 131 | setHumidityOverSample(settings.humidOverSample); // Default of 1x oversample 132 | setTempOverSample(settings.tempOverSample); // Default of 1x oversample 133 | 134 | setMode(MODE_NORMAL); // Go! 135 | 136 | return (readRegister(BME280_CHIP_ID_REG)); // Should return 0x60 137 | } 138 | 139 | // Begin comm with BME280 over SPI 140 | bool BME280::beginSPI(uint8_t csPin, SPIClass &spiPort) 141 | { 142 | _spiPort = &spiPort; 143 | settings.chipSelectPin = csPin; 144 | settings.commInterface = kSfeSPIMode; 145 | 146 | uint8_t chipID = begin(); 147 | 148 | if (chipID == 0x58) 149 | return (true); // Begin normal init with these settings. Should return chip ID of 0x58 for BMP 150 | if (chipID == 0x60) 151 | return (true); // Begin normal init with these settings. Should return chip ID of 0x60 for BME 152 | return (false); 153 | } 154 | 155 | // Begin comm with BME280 over I2C 156 | bool BME280::beginI2C(TwoWire &wirePort) 157 | { 158 | _hardPort = &wirePort; 159 | _wireType = HARD_WIRE; 160 | 161 | settings.commInterface = kSfeI2CMode; 162 | // settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() 163 | 164 | uint8_t chipID = begin(); 165 | 166 | if (chipID == 0x58) 167 | return (true); // Begin normal init with these settings. Should return chip ID of 0x58 for BMP 168 | if (chipID == 0x60) 169 | return (true); // Begin normal init with these settings. Should return chip ID of 0x60 for BME 170 | return (false); 171 | } 172 | 173 | // Begin comm with BME280 over software I2C 174 | #ifdef SoftwareWire_h 175 | bool BME280::beginI2C(SoftwareWire &wirePort) 176 | { 177 | _softPort = &wirePort; 178 | _wireType = SOFT_WIRE; 179 | 180 | settings.commInterface = kSfeI2CMode; 181 | // settings.I2CAddress = 0x77; //We assume user has set the I2C address using setI2CAddress() 182 | 183 | uint8_t chipID = begin(); 184 | 185 | if (chipID == 0x58) 186 | return (true); // Begin normal init with these settings. Should return chip ID of 0x58 for BMP 187 | if (chipID == 0x60) 188 | return (true); // Begin normal init with these settings. Should return chip ID of 0x60 for BME 189 | return (false); 190 | } 191 | #endif 192 | 193 | // Set the mode bits in the ctrl_meas register 194 | // Mode 00 = Sleep 195 | // 01 and 10 = Forced 196 | // 11 = Normal mode 197 | void BME280::setMode(uint8_t mode) 198 | { 199 | if (mode > 0b11) 200 | mode = 0; // Error check. Default to sleep mode 201 | 202 | uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); 203 | controlData &= ~((1 << 1) | (1 << 0)); // Clear the mode[1:0] bits 204 | controlData |= mode; // Set 205 | writeRegister(BME280_CTRL_MEAS_REG, controlData); 206 | } 207 | 208 | // Gets the current mode bits in the ctrl_meas register 209 | // Mode 00 = Sleep 210 | // 01 and 10 = Forced 211 | // 11 = Normal mode 212 | uint8_t BME280::getMode() 213 | { 214 | uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); 215 | return (controlData & 0b00000011); // Clear bits 7 through 2 216 | } 217 | 218 | // Set the standby bits in the config register 219 | // tStandby can be: 220 | // 0, 0.5ms 221 | // 1, 62.5ms 222 | // 2, 125ms 223 | // 3, 250ms 224 | // 4, 500ms 225 | // 5, 1000ms 226 | // 6, 10ms 227 | // 7, 20ms 228 | void BME280::setStandbyTime(uint8_t timeSetting) 229 | { 230 | if (timeSetting > 0b111) 231 | timeSetting = 0; // Error check. Default to 0.5ms 232 | 233 | uint8_t controlData = readRegister(BME280_CONFIG_REG); 234 | controlData &= ~((1 << 7) | (1 << 6) | (1 << 5)); // Clear the 7/6/5 bits 235 | controlData |= (timeSetting << 5); // Align with bits 7/6/5 236 | writeRegister(BME280_CONFIG_REG, controlData); 237 | } 238 | 239 | // Set the filter bits in the config register 240 | // filter can be off or number of FIR coefficients to use: 241 | // 0, filter off 242 | // 1, coefficients = 2 243 | // 2, coefficients = 4 244 | // 3, coefficients = 8 245 | // 4, coefficients = 16 246 | void BME280::setFilter(uint8_t filterSetting) 247 | { 248 | if (filterSetting > 0b111) 249 | filterSetting = 0; // Error check. Default to filter off 250 | 251 | uint8_t controlData = readRegister(BME280_CONFIG_REG); 252 | controlData &= ~((1 << 4) | (1 << 3) | (1 << 2)); // Clear the 4/3/2 bits 253 | controlData |= (filterSetting << 2); // Align with bits 4/3/2 254 | writeRegister(BME280_CONFIG_REG, controlData); 255 | } 256 | 257 | // Set the temperature oversample value 258 | // 0 turns off temp sensing 259 | // 1 to 16 are valid over sampling values 260 | void BME280::setTempOverSample(uint8_t overSampleAmount) 261 | { 262 | overSampleAmount = checkSampleValue(overSampleAmount); // Error check 263 | 264 | uint8_t originalMode = getMode(); // Get the current mode so we can go back to it at the end 265 | 266 | setMode(MODE_SLEEP); // Config will only be writeable in sleep mode, so first go to sleep mode 267 | 268 | // Set the osrs_t bits (7, 6, 5) to overSampleAmount 269 | uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); 270 | controlData &= ~((1 << 7) | (1 << 6) | (1 << 5)); // Clear bits 765 271 | controlData |= overSampleAmount << 5; // Align overSampleAmount to bits 7/6/5 272 | writeRegister(BME280_CTRL_MEAS_REG, controlData); 273 | 274 | setMode(originalMode); // Return to the original user's choice 275 | } 276 | 277 | // Set the pressure oversample value 278 | // 0 turns off pressure sensing 279 | // 1 to 16 are valid over sampling values 280 | void BME280::setPressureOverSample(uint8_t overSampleAmount) 281 | { 282 | overSampleAmount = checkSampleValue(overSampleAmount); // Error check 283 | 284 | uint8_t originalMode = getMode(); // Get the current mode so we can go back to it at the end 285 | 286 | setMode(MODE_SLEEP); // Config will only be writeable in sleep mode, so first go to sleep mode 287 | 288 | // Set the osrs_p bits (4, 3, 2) to overSampleAmount 289 | uint8_t controlData = readRegister(BME280_CTRL_MEAS_REG); 290 | controlData &= ~((1 << 4) | (1 << 3) | (1 << 2)); // Clear bits 432 291 | controlData |= overSampleAmount << 2; // Align overSampleAmount to bits 4/3/2 292 | writeRegister(BME280_CTRL_MEAS_REG, controlData); 293 | 294 | setMode(originalMode); // Return to the original user's choice 295 | } 296 | 297 | // Set the humidity oversample value 298 | // 0 turns off humidity sensing 299 | // 1 to 16 are valid over sampling values 300 | void BME280::setHumidityOverSample(uint8_t overSampleAmount) 301 | { 302 | overSampleAmount = checkSampleValue(overSampleAmount); // Error check 303 | 304 | uint8_t originalMode = getMode(); // Get the current mode so we can go back to it at the end 305 | 306 | setMode(MODE_SLEEP); // Config will only be writeable in sleep mode, so first go to sleep mode 307 | 308 | // Set the osrs_h bits (2, 1, 0) to overSampleAmount 309 | uint8_t controlData = readRegister(BME280_CTRL_HUMIDITY_REG); 310 | controlData &= ~((1 << 2) | (1 << 1) | (1 << 0)); // Clear bits 2/1/0 311 | controlData |= overSampleAmount << 0; // Align overSampleAmount to bits 2/1/0 312 | writeRegister(BME280_CTRL_HUMIDITY_REG, controlData); 313 | 314 | setMode(originalMode); // Return to the original user's choice 315 | } 316 | 317 | // Validates an over sample value 318 | // Allowed values are 0 to 16 319 | // These are used in the humidty, pressure, and temp oversample functions 320 | uint8_t BME280::checkSampleValue(uint8_t userValue) 321 | { 322 | switch (userValue) 323 | { 324 | case (0): 325 | return 0; 326 | break; // Valid 327 | case (1): 328 | return 1; 329 | break; // Valid 330 | case (2): 331 | return 2; 332 | break; // Valid 333 | case (4): 334 | return 3; 335 | break; // Valid 336 | case (8): 337 | return 4; 338 | break; // Valid 339 | case (16): 340 | return 5; 341 | break; // Valid 342 | default: 343 | return 1; // Default to 1x 344 | break; // Good 345 | } 346 | } 347 | 348 | // Set the global setting for the I2C address we want to communicate with 349 | // Default is 0x77 350 | void BME280::setI2CAddress(uint8_t address) 351 | { 352 | settings.I2CAddress = address; // Set the I2C address for this device 353 | } 354 | 355 | // Check the measuring bit and return true while device is taking measurement 356 | bool BME280::isMeasuring(void) 357 | { 358 | uint8_t stat = readRegister(BME280_STAT_REG); 359 | return (stat & (1 << 3)); // If the measuring bit (3) is set, return true 360 | } 361 | 362 | // Strictly resets. Run .begin() afterwards 363 | void BME280::reset(void) 364 | { 365 | writeRegister(BME280_RST_REG, 0xB6); 366 | } 367 | 368 | //****************************************************************************// 369 | // 370 | // Burst Measurement Section 371 | // 372 | //****************************************************************************// 373 | 374 | // Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout 375 | // tempScale = 0 for Celsius scale (default setting) 376 | // tempScale = 1 for Fahrenheit scale 377 | void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, uint8_t tempScale) 378 | { 379 | 380 | uint8_t dataBurst[8]; 381 | readRegisterRegion(dataBurst, BME280_MEASUREMENTS_REG, 8); 382 | 383 | if (tempScale == 0) 384 | { 385 | readTempCFromBurst(dataBurst, measurements); 386 | } 387 | else 388 | { 389 | readTempFFromBurst(dataBurst, measurements); 390 | } 391 | readFloatPressureFromBurst(dataBurst, measurements); 392 | readFloatHumidityFromBurst(dataBurst, measurements); 393 | } 394 | 395 | //****************************************************************************// 396 | // 397 | // Pressure Section 398 | // 399 | //****************************************************************************// 400 | float BME280::readFloatPressure(void) 401 | { 402 | 403 | // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). 404 | // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa 405 | uint8_t buffer[3]; 406 | readRegisterRegion(buffer, BME280_PRESSURE_MSB_REG, 3); 407 | int32_t adc_P = ((uint32_t)buffer[0] << 12) | ((uint32_t)buffer[1] << 4) | ((buffer[2] >> 4) & 0x0F); 408 | 409 | int64_t var1, var2, p_acc; 410 | var1 = ((int64_t)t_fine) - 128000; 411 | var2 = var1 * var1 * (int64_t)calibration.dig_P6; 412 | var2 = var2 + ((var1 * (int64_t)calibration.dig_P5) << 17); 413 | var2 = var2 + (((int64_t)calibration.dig_P4) << 35); 414 | var1 = ((var1 * var1 * (int64_t)calibration.dig_P3) >> 8) + ((var1 * (int64_t)calibration.dig_P2) << 12); 415 | var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)calibration.dig_P1) >> 33; 416 | if (var1 == 0) 417 | { 418 | return 0; // avoid exception caused by division by zero 419 | } 420 | p_acc = 1048576 - adc_P; 421 | p_acc = (((p_acc << 31) - var2) * 3125) / var1; 422 | var1 = (((int64_t)calibration.dig_P9) * (p_acc >> 13) * (p_acc >> 13)) >> 25; 423 | var2 = (((int64_t)calibration.dig_P8) * p_acc) >> 19; 424 | p_acc = ((p_acc + var1 + var2) >> 8) + (((int64_t)calibration.dig_P7) << 4); 425 | 426 | return (float)p_acc / 256.0; 427 | } 428 | 429 | void BME280::readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) 430 | { 431 | 432 | // Set pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). 433 | // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa 434 | 435 | int32_t adc_P = ((uint32_t)buffer[0] << 12) | ((uint32_t)buffer[1] << 4) | ((buffer[2] >> 4) & 0x0F); 436 | 437 | int64_t var1, var2, p_acc; 438 | var1 = ((int64_t)t_fine) - 128000; 439 | var2 = var1 * var1 * (int64_t)calibration.dig_P6; 440 | var2 = var2 + ((var1 * (int64_t)calibration.dig_P5) << 17); 441 | var2 = var2 + (((int64_t)calibration.dig_P4) << 35); 442 | var1 = ((var1 * var1 * (int64_t)calibration.dig_P3) >> 8) + ((var1 * (int64_t)calibration.dig_P2) << 12); 443 | var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)calibration.dig_P1) >> 33; 444 | if (var1 == 0) 445 | { 446 | measurements->pressure = 0; // avoid exception caused by division by zero 447 | } 448 | else 449 | { 450 | p_acc = 1048576 - adc_P; 451 | p_acc = (((p_acc << 31) - var2) * 3125) / var1; 452 | var1 = (((int64_t)calibration.dig_P9) * (p_acc >> 13) * (p_acc >> 13)) >> 25; 453 | var2 = (((int64_t)calibration.dig_P8) * p_acc) >> 19; 454 | p_acc = ((p_acc + var1 + var2) >> 8) + (((int64_t)calibration.dig_P7) << 4); 455 | 456 | measurements->pressure = (float)p_acc / 256.0; 457 | } 458 | } 459 | 460 | // Sets the internal variable _referencePressure so the altitude is calculated properly. 461 | // This is also known as "sea level pressure" and is in Pascals. The value is probably 462 | // within 10% of 101325. This varies based on the weather: 463 | // https://en.wikipedia.org/wiki/Atmospheric_pressure#Mean_sea-level_pressure 464 | // 465 | // if you are concerned about accuracy or precision, make sure to pull the 466 | // "sea level pressure"value from a trusted source like NOAA. 467 | void BME280::setReferencePressure(float refPressure) 468 | { 469 | _referencePressure = refPressure; 470 | } 471 | 472 | // Return the local reference pressure 473 | float BME280::getReferencePressure() 474 | { 475 | return (_referencePressure); 476 | } 477 | 478 | float BME280::readFloatAltitudeMeters(void) 479 | { 480 | float heightOutput = 0; 481 | 482 | // Getting height from a pressure reading is called the "international barometric height formula". 483 | // The magic value of 44330.77 was adjusted in issue #30. 484 | // There's also some discussion of it here: https://www.sparkfun.com/tutorials/253 485 | // This calculation is NOT designed to work on non-Earthlike planets such as Mars or Venus; 486 | // see NRLMSISE-00. That's why it is the "international" formula, not "interplanetary". 487 | // Sparkfun is not liable for incorrect altitude calculations from this 488 | // code on those planets. Interplanetary selfies are welcome, however. 489 | heightOutput = ((float)-44330.77) * (pow(((float)readFloatPressure() / (float)_referencePressure), 0.190263) - 490 | (float)1); // Corrected, see issue 30 491 | return heightOutput; 492 | } 493 | 494 | float BME280::readFloatAltitudeFeet(void) 495 | { 496 | float heightOutput = 0; 497 | 498 | heightOutput = readFloatAltitudeMeters() * 3.28084; 499 | return heightOutput; 500 | } 501 | 502 | //****************************************************************************// 503 | // 504 | // Humidity Section 505 | // 506 | //****************************************************************************// 507 | float BME280::readFloatHumidity(void) 508 | { 509 | 510 | // Returns humidity in %RH as unsigned 32 bit integer in Q22. 10 format (22 integer and 10 fractional bits). 511 | // Output value of “47445” represents 47445/1024 = 46. 333 %RH 512 | uint8_t buffer[2]; 513 | readRegisterRegion(buffer, BME280_HUMIDITY_MSB_REG, 2); 514 | int32_t adc_H = ((uint32_t)buffer[0] << 8) | ((uint32_t)buffer[1]); 515 | 516 | int32_t var1; 517 | var1 = (t_fine - ((int32_t)76800)); 518 | var1 = (((((adc_H << 14) - (((int32_t)calibration.dig_H4) << 20) - (((int32_t)calibration.dig_H5) * var1)) + 519 | ((int32_t)16384)) >> 520 | 15) * 521 | (((((((var1 * ((int32_t)calibration.dig_H6)) >> 10) * 522 | (((var1 * ((int32_t)calibration.dig_H3)) >> 11) + ((int32_t)32768))) >> 523 | 10) + 524 | ((int32_t)2097152)) * 525 | ((int32_t)calibration.dig_H2) + 526 | 8192) >> 527 | 14)); 528 | var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * ((int32_t)calibration.dig_H1)) >> 4)); 529 | var1 = (var1 < 0 ? 0 : var1); 530 | var1 = (var1 > 419430400 ? 419430400 : var1); 531 | 532 | return (float)(var1 >> 12) / 1024.0; 533 | } 534 | 535 | void BME280::readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) 536 | { 537 | 538 | // Set humidity in %RH as unsigned 32 bit integer in Q22. 10 format (22 integer and 10 fractional bits). 539 | // Output value of “47445” represents 47445/1024 = 46. 333 %RH 540 | int32_t adc_H = ((uint32_t)buffer[6] << 8) | ((uint32_t)buffer[7]); 541 | 542 | int32_t var1; 543 | var1 = (t_fine - ((int32_t)76800)); 544 | var1 = (((((adc_H << 14) - (((int32_t)calibration.dig_H4) << 20) - (((int32_t)calibration.dig_H5) * var1)) + 545 | ((int32_t)16384)) >> 546 | 15) * 547 | (((((((var1 * ((int32_t)calibration.dig_H6)) >> 10) * 548 | (((var1 * ((int32_t)calibration.dig_H3)) >> 11) + ((int32_t)32768))) >> 549 | 10) + 550 | ((int32_t)2097152)) * 551 | ((int32_t)calibration.dig_H2) + 552 | 8192) >> 553 | 14)); 554 | var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * ((int32_t)calibration.dig_H1)) >> 4)); 555 | var1 = (var1 < 0 ? 0 : var1); 556 | var1 = (var1 > 419430400 ? 419430400 : var1); 557 | 558 | measurements->humidity = (float)(var1 >> 12) / 1024.0; 559 | } 560 | 561 | //****************************************************************************// 562 | // 563 | // Temperature Section 564 | // 565 | //****************************************************************************// 566 | 567 | void BME280::setTemperatureCorrection(float corr) 568 | { 569 | settings.tempCorrection = corr; 570 | } 571 | 572 | float BME280::readTempC(void) 573 | { 574 | // Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. 575 | // t_fine carries fine temperature as global value 576 | 577 | // get the reading (adc_T); 578 | uint8_t buffer[3]; 579 | readRegisterRegion(buffer, BME280_TEMPERATURE_MSB_REG, 3); 580 | int32_t adc_T = ((uint32_t)buffer[0] << 12) | ((uint32_t)buffer[1] << 4) | ((buffer[2] >> 4) & 0x0F); 581 | 582 | // By datasheet, calibrate 583 | int64_t var1, var2; 584 | 585 | var1 = ((((adc_T >> 3) - ((int32_t)calibration.dig_T1 << 1))) * ((int32_t)calibration.dig_T2)) >> 11; 586 | var2 = (((((adc_T >> 4) - ((int32_t)calibration.dig_T1)) * ((adc_T >> 4) - ((int32_t)calibration.dig_T1))) >> 12) * 587 | ((int32_t)calibration.dig_T3)) >> 588 | 14; 589 | t_fine = var1 + var2; 590 | float output = (t_fine * 5 + 128) >> 8; 591 | 592 | output = output / 100 + settings.tempCorrection; 593 | 594 | return output; 595 | } 596 | 597 | float BME280::readTempFromBurst(uint8_t buffer[]) 598 | { 599 | int32_t adc_T = ((uint32_t)buffer[3] << 12) | ((uint32_t)buffer[4] << 4) | ((buffer[5] >> 4) & 0x0F); 600 | 601 | // By datasheet, calibrate 602 | int64_t var1, var2; 603 | 604 | var1 = ((((adc_T >> 3) - ((int32_t)calibration.dig_T1 << 1))) * ((int32_t)calibration.dig_T2)) >> 11; 605 | var2 = (((((adc_T >> 4) - ((int32_t)calibration.dig_T1)) * ((adc_T >> 4) - ((int32_t)calibration.dig_T1))) >> 12) * 606 | ((int32_t)calibration.dig_T3)) >> 607 | 14; 608 | t_fine = var1 + var2; 609 | float output = (t_fine * 5 + 128) >> 8; 610 | 611 | output = output / 100 + settings.tempCorrection; 612 | 613 | return output; 614 | } 615 | 616 | void BME280::readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) 617 | { 618 | measurements->temperature = readTempFromBurst(buffer); 619 | } 620 | 621 | float BME280::readTempF(void) 622 | { 623 | float output = readTempC(); 624 | output = (output * 9) / 5 + 32; 625 | 626 | return output; 627 | } 628 | 629 | void BME280::readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements) 630 | { 631 | float output = readTempFromBurst(buffer); 632 | output = (output * 9) / 5 + 32; 633 | 634 | measurements->temperature = output; 635 | } 636 | 637 | //****************************************************************************// 638 | // 639 | // Dew point Section 640 | // 641 | //****************************************************************************// 642 | // Returns Dew point in DegC 643 | double BME280::dewPointC(void) 644 | { 645 | double celsius = readTempC(); 646 | double humidity = readFloatHumidity(); 647 | // (1) Saturation Vapor Pressure = ESGG(T) 648 | double RATIO = 373.15 / (273.15 + celsius); 649 | double RHS = -7.90298 * (RATIO - 1); 650 | RHS += 5.02808 * log10(RATIO); 651 | RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1 / RATIO))) - 1); 652 | RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1); 653 | RHS += log10(1013.246); 654 | // factor -3 is to adjust units - Vapor Pressure SVP * humidity 655 | double VP = pow(10, RHS - 3) * humidity; 656 | // (2) DEWPOINT = F(Vapor Pressure) 657 | double T = log(VP / 0.61078); // temp var 658 | return (241.88 * T) / (17.558 - T); 659 | } 660 | 661 | // Returns Dew point in DegF 662 | double BME280::dewPointF(void) 663 | { 664 | return (dewPointC() * 1.8 + 32); // Convert C to F 665 | } 666 | 667 | //****************************************************************************// 668 | // 669 | // Utility 670 | // 671 | //****************************************************************************// 672 | void BME280::readRegisterRegion(uint8_t *outputPointer, uint8_t offset, uint8_t length) 673 | { 674 | // define pointer that will point to the external space 675 | uint8_t i = 0; 676 | char c = 0; 677 | 678 | switch (settings.commInterface) 679 | { 680 | 681 | case kSfeI2CMode: 682 | switch (_wireType) 683 | { 684 | case (HARD_WIRE): 685 | _hardPort->beginTransmission(settings.I2CAddress); 686 | _hardPort->write(offset); 687 | _hardPort->endTransmission(); 688 | 689 | // request bytes from slave device 690 | _hardPort->requestFrom(settings.I2CAddress, length); 691 | while ((_hardPort->available()) && (i < length)) // slave may send less than requested 692 | { 693 | c = _hardPort->read(); // receive a byte as character 694 | *outputPointer = c; 695 | outputPointer++; 696 | i++; 697 | } 698 | break; 699 | case (SOFT_WIRE): 700 | #ifdef SoftwareWire_h 701 | _softPort->beginTransmission(settings.I2CAddress); 702 | _softPort->write(offset); 703 | _softPort->endTransmission(); 704 | 705 | // request bytes from slave device 706 | _softPort->requestFrom(settings.I2CAddress, length); 707 | while ((_softPort->available()) && (i < length)) // slave may send less than requested 708 | { 709 | c = _softPort->read(); // receive a byte as character 710 | *outputPointer = c; 711 | outputPointer++; 712 | i++; 713 | } 714 | #endif 715 | break; 716 | } 717 | break; 718 | 719 | case kSfeSPIMode: 720 | _spiPort->beginTransaction(settings.spiSettings); 721 | // take the chip select low to select the device: 722 | digitalWrite(settings.chipSelectPin, LOW); 723 | // send the device the register you want to read: 724 | _spiPort->transfer(offset | 0x80); // Ored with "read request" bit 725 | while (i < length) // slave may send less than requested 726 | { 727 | c = _spiPort->transfer(0x00); // receive a byte as character 728 | *outputPointer = c; 729 | outputPointer++; 730 | i++; 731 | } 732 | // take the chip select high to de-select: 733 | digitalWrite(settings.chipSelectPin, HIGH); 734 | _spiPort->endTransaction(); 735 | break; 736 | 737 | default: 738 | break; 739 | } 740 | } 741 | 742 | uint8_t BME280::readRegister(uint8_t offset) 743 | { 744 | // Return value 745 | uint8_t result = 0; 746 | uint8_t numBytes = 1; 747 | uint8_t bytesAvailable; 748 | switch (settings.commInterface) 749 | { 750 | 751 | case kSfeI2CMode: 752 | switch (_wireType) 753 | { 754 | case (HARD_WIRE): 755 | _hardPort->beginTransmission(settings.I2CAddress); 756 | _hardPort->write(offset); 757 | _hardPort->endTransmission(); 758 | 759 | bytesAvailable = _hardPort->requestFrom(settings.I2CAddress, numBytes); 760 | if (bytesAvailable == numBytes) 761 | { 762 | result = _hardPort->read(); 763 | } 764 | break; 765 | 766 | case (SOFT_WIRE): 767 | #ifdef SoftwareWire_h 768 | _softPort->beginTransmission(settings.I2CAddress); 769 | _softPort->write(offset); 770 | _softPort->endTransmission(); 771 | 772 | bytesAvailable = _softPort->requestFrom(settings.I2CAddress, numBytes); 773 | if (bytesAvailable == numBytes) 774 | { 775 | result = _softPort->read(); 776 | } 777 | #endif 778 | break; 779 | } 780 | 781 | break; 782 | 783 | case kSfeSPIMode: 784 | readRegisterRegion(&result, offset, 1); 785 | break; 786 | 787 | default: 788 | break; 789 | } 790 | return result; 791 | } 792 | 793 | int16_t BME280::readRegisterInt16(uint8_t offset) 794 | { 795 | uint8_t myBuffer[2]; 796 | readRegisterRegion(myBuffer, offset, 2); // Does memory transfer 797 | int16_t output = (int16_t)myBuffer[0] | int16_t(myBuffer[1] << 8); 798 | 799 | return output; 800 | } 801 | 802 | void BME280::writeRegister(uint8_t offset, uint8_t dataToWrite) 803 | { 804 | switch (settings.commInterface) 805 | { 806 | case kSfeI2CMode: 807 | // Write the byte 808 | 809 | switch (_wireType) 810 | { 811 | case (HARD_WIRE): 812 | _hardPort->beginTransmission(settings.I2CAddress); 813 | _hardPort->write(offset); 814 | _hardPort->write(dataToWrite); 815 | _hardPort->endTransmission(); 816 | break; 817 | case (SOFT_WIRE): 818 | #ifdef SoftwareWire_h 819 | _softPort->beginTransmission(settings.I2CAddress); 820 | _softPort->write(offset); 821 | _softPort->write(dataToWrite); 822 | _softPort->endTransmission(); 823 | #endif 824 | break; 825 | } 826 | break; 827 | 828 | case kSfeSPIMode: 829 | _spiPort->beginTransaction(settings.spiSettings); 830 | // take the chip select low to select the device: 831 | digitalWrite(settings.chipSelectPin, LOW); 832 | // send the device the register you want to read: 833 | _spiPort->transfer(offset & 0x7F); 834 | // send a value of 0 to read the first byte returned: 835 | _spiPort->transfer(dataToWrite); 836 | // decrement the number of bytes left to read: 837 | // take the chip select high to de-select: 838 | digitalWrite(settings.chipSelectPin, HIGH); 839 | _spiPort->endTransaction(); 840 | break; 841 | 842 | default: 843 | break; 844 | } 845 | } 846 | --------------------------------------------------------------------------------