├── assets └── board.jpg ├── .gitignore ├── library.properties ├── .github ├── workflows │ └── githubci.yml ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── keywords.txt ├── LICENSE ├── examples ├── bme280_unified │ └── bme280_unified.ino ├── bme280test │ └── bme280test.ino └── advancedsettings │ └── advancedsettings.ino ├── README.md ├── Adafruit_BME280.h └── Adafruit_BME280.cpp /assets/board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_BME280_Library/HEAD/assets/board.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # osx 2 | .DS_Store 3 | 4 | # doxygen 5 | Doxyfile* 6 | doxygen_sqlite3.db 7 | html 8 | *.tmp 9 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit BME280 Library 2 | version=2.3.0 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Arduino library for BME280 sensors. 6 | paragraph=Arduino library for BME280 humidity and pressure sensors. 7 | category=Sensors 8 | url=https://github.com/adafruit/Adafruit_BME280_Library 9 | architectures=* 10 | depends=Adafruit Unified Sensor, Adafruit BusIO 11 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py main_platforms 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "Adafruit BME280 Library" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For BMPE80 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | BME280 KEYWORD1 10 | Adafruit_BME280 KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | Adafruit_Sensor KEYWORD2 17 | Adafruit_BME280 KEYWORD2 18 | readPressure KEYWORD2 19 | readAltitude KEYWORD2 20 | readTemperature KEYWORD2 21 | readHumidity KEYWORD2 22 | setSampling KEYWORD2 23 | sealLevelForAltitude KEYWORD2 24 | bme KEYWORD2 25 | 26 | ####################################### 27 | # Constants (LITERAL1) 28 | MODE_SLEEP LITERAL1 29 | MODE_FORCED LITERAL1 30 | MODE_NORMAL LITERAL1 31 | SAMPLING_NONE LITERAL1 32 | SAMPLING_X1 LITERAL1 33 | SAMPLING_X2 LITERAL1 34 | SAMPLING_X4 LITERAL1 35 | SAMPLING_X8 LITERAL1 36 | SAMPLING_X16 LITERAL1 37 | FILTER_OFF LITERAL1 38 | FILTER_X2 LITERAL1 39 | FILTER_X4 LITERAL1 40 | FILTER_X8 LITERAL1 41 | FILTER_X16 LITERAL1 42 | STANDBY_MS_0_5 LITERAL1 43 | STANDBY_MS_10 LITERAL1 44 | STANDBY_MS_20 LITERAL1 45 | STANDBY_MS_62_5 LITERAL1 46 | STANDBY_MS_125 LITERAL1 47 | STANDBY_MS_250 LITERAL1 48 | STANDBY_MS_500 LITERAL1 49 | STANDBY_MS_1000 LITERAL1 50 | 51 | ####################################### 52 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Limor Fried & Kevin Townsend for Adafruit Industries 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of Adafruit Industries nor the names of its 13 | contributors may be used to endorse or promote products derived from 14 | this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | 28 | -------------------------------------------------------------------------------- /examples/bme280_unified/bme280_unified.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the BME280 humidity, temperature & pressure sensor 3 | This example shows how to take Sensor Events instead of direct readings 4 | 5 | Designed specifically to work with the Adafruit BME280 Breakout 6 | ----> http://www.adafruit.com/products/2652 7 | 8 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 9 | to interface. 10 | 11 | Adafruit invests time and resources providing this open source code, 12 | please support Adafruit and open-source hardware by purchasing products 13 | from Adafruit! 14 | 15 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 16 | BSD license, all text above must be included in any redistribution 17 | ***************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | Adafruit_BME280 bme; // use I2C interface 24 | Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); 25 | Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); 26 | Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); 27 | 28 | void setup() { 29 | Serial.begin(9600); 30 | Serial.println(F("BME280 Sensor event test")); 31 | 32 | if (!bme.begin()) { 33 | Serial.println(F("Could not find a valid BME280 sensor, check wiring!")); 34 | while (1) delay(10); 35 | } 36 | 37 | bme_temp->printSensorDetails(); 38 | bme_pressure->printSensorDetails(); 39 | bme_humidity->printSensorDetails(); 40 | } 41 | 42 | void loop() { 43 | sensors_event_t temp_event, pressure_event, humidity_event; 44 | bme_temp->getEvent(&temp_event); 45 | bme_pressure->getEvent(&pressure_event); 46 | bme_humidity->getEvent(&humidity_event); 47 | 48 | Serial.print(F("Temperature = ")); 49 | Serial.print(temp_event.temperature); 50 | Serial.println(" *C"); 51 | 52 | Serial.print(F("Humidity = ")); 53 | Serial.print(humidity_event.relative_humidity); 54 | Serial.println(" %"); 55 | 56 | Serial.print(F("Pressure = ")); 57 | Serial.print(pressure_event.pressure); 58 | Serial.println(" hPa"); 59 | 60 | Serial.println(); 61 | delay(1000); 62 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit BME280 Library [![Build Status](https://github.com/adafruit/Adafruit_BME280_Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BME280_Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_BME280_Library/html/index.html) 2 | 3 | 4 | 5 | 6 | This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor 7 | 8 | Designed specifically to work with the Adafruit BME280 Breakout 9 | * http://www.adafruit.com/products/2652 10 | 11 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 12 | 13 | # Installation 14 | To install, use the Arduino Library Manager and search for "Adafruit BME280" and install the library. 15 | 16 | ## Dependencies 17 | * [Adafruit Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor) 18 | 19 | # Contributing 20 | 21 | Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit_PM25AQI/blob/master/CODE_OF_CONDUCT.md>) 22 | before contributing to help this project stay welcoming. 23 | 24 | ## Documentation and doxygen 25 | Documentation is produced by doxygen. Contributions should include documentation for any new code added. 26 | 27 | Some examples of how to use doxygen can be found in these guide pages: 28 | 29 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen 30 | 31 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips 32 | 33 | ## Formatting and clang-format 34 | This library uses [`clang-format`](https://releases.llvm.org/download.html) to standardize the formatting of `.cpp` and `.h` files. 35 | Contributions should be formatted using `clang-format`: 36 | 37 | The `-i` flag will make the changes to the file. 38 | ```bash 39 | clang-format -i *.cpp *.h 40 | ``` 41 | If you prefer to make the changes yourself, running `clang-format` without the `-i` flag will print out a formatted version of the file. You can save this to a file and diff it against the original to see the changes. 42 | 43 | Note that the formatting output by `clang-format` is what the automated formatting checker will expect. Any diffs from this formatting will result in a failed build until they are addressed. Using the `-i` flag is highly recommended. 44 | 45 | ### clang-format resources 46 | * [Binary builds and source available on the LLVM downloads page](https://releases.llvm.org/download.html) 47 | * [Documentation and IDE integration](https://clang.llvm.org/docs/ClangFormat.html) 48 | 49 | ## About this Driver 50 | Written by Ladyada for Adafruit Industries. 51 | 52 | BSD license, check license.txt for more information 53 | 54 | All text above must be included in any redistribution 55 | -------------------------------------------------------------------------------- /examples/bme280test/bme280test.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the BME280 humidity, temperature & pressure sensor 3 | 4 | Designed specifically to work with the Adafruit BME280 Breakout 5 | ----> http://www.adafruit.com/products/2652 6 | 7 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 8 | to interface. The device's I2C address is either 0x76 or 0x77. 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit andopen-source hardware by purchasing products 12 | from Adafruit! 13 | 14 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | See the LICENSE file for details. 17 | ***************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define BME_SCK 13 25 | #define BME_MISO 12 26 | #define BME_MOSI 11 27 | #define BME_CS 10 28 | 29 | #define SEALEVELPRESSURE_HPA (1013.25) 30 | 31 | Adafruit_BME280 bme; // I2C 32 | //Adafruit_BME280 bme(BME_CS); // hardware SPI 33 | //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI 34 | 35 | unsigned long delayTime; 36 | 37 | void setup() { 38 | Serial.begin(9600); 39 | while(!Serial); // time to get serial running 40 | Serial.println(F("BME280 test")); 41 | 42 | unsigned status; 43 | 44 | // default settings 45 | status = bme.begin(); 46 | // You can also pass in a Wire library object like &Wire2 47 | // status = bme.begin(0x76, &Wire2) 48 | if (!status) { 49 | Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!"); 50 | Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16); 51 | Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n"); 52 | Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n"); 53 | Serial.print(" ID of 0x60 represents a BME 280.\n"); 54 | Serial.print(" ID of 0x61 represents a BME 680.\n"); 55 | while (1) delay(10); 56 | } 57 | 58 | Serial.println("-- Default Test --"); 59 | delayTime = 1000; 60 | 61 | Serial.println(); 62 | } 63 | 64 | 65 | void loop() { 66 | printValues(); 67 | delay(delayTime); 68 | } 69 | 70 | 71 | void printValues() { 72 | Serial.print("Temperature = "); 73 | Serial.print(bme.readTemperature()); 74 | Serial.println(" °C"); 75 | 76 | Serial.print("Pressure = "); 77 | 78 | Serial.print(bme.readPressure() / 100.0F); 79 | Serial.println(" hPa"); 80 | 81 | Serial.print("Approx. Altitude = "); 82 | Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); 83 | Serial.println(" m"); 84 | 85 | Serial.print("Humidity = "); 86 | Serial.print(bme.readHumidity()); 87 | Serial.println(" %"); 88 | 89 | Serial.println(); 90 | } 91 | -------------------------------------------------------------------------------- /examples/advancedsettings/advancedsettings.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the BME280 humidity, temperature & pressure sensor 3 | 4 | Designed specifically to work with the Adafruit BME280 Breakout 5 | ----> http://www.adafruit.com/products/2652 6 | 7 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 8 | to interface. The device's I2C address is either 0x76 or 0x77. 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit andopen-source hardware by purchasing products 12 | from Adafruit! 13 | 14 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | See the LICENSE file for details. 17 | ***************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define BME_SCK 13 25 | #define BME_MISO 12 26 | #define BME_MOSI 11 27 | #define BME_CS 10 28 | 29 | #define SEALEVELPRESSURE_HPA (1013.25) 30 | 31 | Adafruit_BME280 bme; // I2C 32 | //Adafruit_BME280 bme(BME_CS); // hardware SPI 33 | //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI 34 | 35 | unsigned long delayTime; 36 | 37 | void setup() { 38 | Serial.begin(9600); 39 | Serial.println(F("BME280 test")); 40 | 41 | if (! bme.begin(0x77, &Wire)) { 42 | Serial.println("Could not find a valid BME280 sensor, check wiring!"); 43 | while (1); 44 | } 45 | 46 | Serial.println("-- Default Test --"); 47 | Serial.println("normal mode, 16x oversampling for all, filter off,"); 48 | Serial.println("0.5ms standby period"); 49 | delayTime = 5000; 50 | 51 | 52 | // For more details on the following scenarious, see chapter 53 | // 3.5 "Recommended modes of operation" in the datasheet 54 | 55 | /* 56 | // weather monitoring 57 | Serial.println("-- Weather Station Scenario --"); 58 | Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,"); 59 | Serial.println("filter off"); 60 | bme.setSampling(Adafruit_BME280::MODE_FORCED, 61 | Adafruit_BME280::SAMPLING_X1, // temperature 62 | Adafruit_BME280::SAMPLING_X1, // pressure 63 | Adafruit_BME280::SAMPLING_X1, // humidity 64 | Adafruit_BME280::FILTER_OFF ); 65 | 66 | // suggested rate is 1/60Hz (1m) 67 | delayTime = 60000; // in milliseconds 68 | */ 69 | 70 | /* 71 | // humidity sensing 72 | Serial.println("-- Humidity Sensing Scenario --"); 73 | Serial.println("forced mode, 1x temperature / 1x humidity / 0x pressure oversampling"); 74 | Serial.println("= pressure off, filter off"); 75 | bme.setSampling(Adafruit_BME280::MODE_FORCED, 76 | Adafruit_BME280::SAMPLING_X1, // temperature 77 | Adafruit_BME280::SAMPLING_NONE, // pressure 78 | Adafruit_BME280::SAMPLING_X1, // humidity 79 | Adafruit_BME280::FILTER_OFF ); 80 | 81 | // suggested rate is 1Hz (1s) 82 | delayTime = 1000; // in milliseconds 83 | */ 84 | 85 | /* 86 | // indoor navigation 87 | Serial.println("-- Indoor Navigation Scenario --"); 88 | Serial.println("normal mode, 16x pressure / 2x temperature / 1x humidity oversampling,"); 89 | Serial.println("0.5ms standby period, filter 16x"); 90 | bme.setSampling(Adafruit_BME280::MODE_NORMAL, 91 | Adafruit_BME280::SAMPLING_X2, // temperature 92 | Adafruit_BME280::SAMPLING_X16, // pressure 93 | Adafruit_BME280::SAMPLING_X1, // humidity 94 | Adafruit_BME280::FILTER_X16, 95 | Adafruit_BME280::STANDBY_MS_0_5 ); 96 | 97 | // suggested rate is 25Hz 98 | // 1 + (2 * T_ovs) + (2 * P_ovs + 0.5) + (2 * H_ovs + 0.5) 99 | // T_ovs = 2 100 | // P_ovs = 16 101 | // H_ovs = 1 102 | // = 40ms (25Hz) 103 | // with standby time that should really be 24.16913... Hz 104 | delayTime = 41; 105 | */ 106 | 107 | /* 108 | // gaming 109 | Serial.println("-- Gaming Scenario --"); 110 | Serial.println("normal mode, 4x pressure / 1x temperature / 0x humidity oversampling,"); 111 | Serial.println("= humidity off, 0.5ms standby period, filter 16x"); 112 | bme.setSampling(Adafruit_BME280::MODE_NORMAL, 113 | Adafruit_BME280::SAMPLING_X1, // temperature 114 | Adafruit_BME280::SAMPLING_X4, // pressure 115 | Adafruit_BME280::SAMPLING_NONE, // humidity 116 | Adafruit_BME280::FILTER_X16, 117 | Adafruit_BME280::STANDBY_MS_0_5 ); 118 | 119 | // Suggested rate is 83Hz 120 | // 1 + (2 * T_ovs) + (2 * P_ovs + 0.5) 121 | // T_ovs = 1 122 | // P_ovs = 4 123 | // = 11.5ms + 0.5ms standby 124 | delayTime = 12; 125 | */ 126 | 127 | Serial.println(); 128 | } 129 | 130 | 131 | void loop() { 132 | // Only needed in forced mode! In normal mode, you can remove the next line. 133 | bme.takeForcedMeasurement(); // has no effect in normal mode 134 | 135 | printValues(); 136 | delay(delayTime); 137 | } 138 | 139 | 140 | void printValues() { 141 | Serial.print("Temperature = "); 142 | Serial.print(bme.readTemperature()); 143 | Serial.println(" *C"); 144 | 145 | Serial.print("Pressure = "); 146 | 147 | Serial.print(bme.readPressure() / 100.0F); 148 | Serial.println(" hPa"); 149 | 150 | Serial.print("Approx. Altitude = "); 151 | Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); 152 | Serial.println(" m"); 153 | 154 | Serial.print("Humidity = "); 155 | Serial.print(bme.readHumidity()); 156 | Serial.println(" %"); 157 | 158 | Serial.println(); 159 | } 160 | -------------------------------------------------------------------------------- /Adafruit_BME280.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_BME280.h 3 | * 4 | * Designed specifically to work with the Adafruit BME280 Breakout 5 | * ----> http://www.adafruit.com/products/2650 6 | * 7 | * These sensors use I2C or SPI to communicate, 2 or 4 pins are required 8 | * to interface. 9 | * 10 | * Adafruit invests time and resources providing this open source code, 11 | * please support Adafruit and open-source hardware by purchasing 12 | * products from Adafruit! 13 | * 14 | * Written by Kevin "KTOWN" Townsend for Adafruit Industries. 15 | * 16 | * BSD license, all text here must be included in any redistribution. 17 | * See the LICENSE file for details. 18 | * 19 | */ 20 | 21 | #ifndef __BME280_H__ 22 | #define __BME280_H__ 23 | 24 | #include "Arduino.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /*! 31 | * @brief default I2C address 32 | */ 33 | #define BME280_ADDRESS (0x77) // Primary I2C Address 34 | /*! 35 | * @brief alternate I2C address 36 | */ 37 | #define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address 38 | 39 | /*! 40 | * @brief Register addresses 41 | */ 42 | enum { 43 | BME280_REGISTER_DIG_T1 = 0x88, 44 | BME280_REGISTER_DIG_T2 = 0x8A, 45 | BME280_REGISTER_DIG_T3 = 0x8C, 46 | 47 | BME280_REGISTER_DIG_P1 = 0x8E, 48 | BME280_REGISTER_DIG_P2 = 0x90, 49 | BME280_REGISTER_DIG_P3 = 0x92, 50 | BME280_REGISTER_DIG_P4 = 0x94, 51 | BME280_REGISTER_DIG_P5 = 0x96, 52 | BME280_REGISTER_DIG_P6 = 0x98, 53 | BME280_REGISTER_DIG_P7 = 0x9A, 54 | BME280_REGISTER_DIG_P8 = 0x9C, 55 | BME280_REGISTER_DIG_P9 = 0x9E, 56 | 57 | BME280_REGISTER_DIG_H1 = 0xA1, 58 | BME280_REGISTER_DIG_H2 = 0xE1, 59 | BME280_REGISTER_DIG_H3 = 0xE3, 60 | BME280_REGISTER_DIG_H4 = 0xE4, 61 | BME280_REGISTER_DIG_H5 = 0xE5, 62 | BME280_REGISTER_DIG_H6 = 0xE7, 63 | 64 | BME280_REGISTER_CHIPID = 0xD0, 65 | BME280_REGISTER_VERSION = 0xD1, 66 | BME280_REGISTER_SOFTRESET = 0xE0, 67 | 68 | BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 69 | 70 | BME280_REGISTER_CONTROLHUMID = 0xF2, 71 | BME280_REGISTER_STATUS = 0XF3, 72 | BME280_REGISTER_CONTROL = 0xF4, 73 | BME280_REGISTER_CONFIG = 0xF5, 74 | BME280_REGISTER_PRESSUREDATA = 0xF7, 75 | BME280_REGISTER_TEMPDATA = 0xFA, 76 | BME280_REGISTER_HUMIDDATA = 0xFD 77 | }; 78 | 79 | /**************************************************************************/ 80 | /*! 81 | @brief calibration data 82 | */ 83 | /**************************************************************************/ 84 | typedef struct { 85 | uint16_t dig_T1; ///< temperature compensation value 86 | int16_t dig_T2; ///< temperature compensation value 87 | int16_t dig_T3; ///< temperature compensation value 88 | 89 | uint16_t dig_P1; ///< pressure compensation value 90 | int16_t dig_P2; ///< pressure compensation value 91 | int16_t dig_P3; ///< pressure compensation value 92 | int16_t dig_P4; ///< pressure compensation value 93 | int16_t dig_P5; ///< pressure compensation value 94 | int16_t dig_P6; ///< pressure compensation value 95 | int16_t dig_P7; ///< pressure compensation value 96 | int16_t dig_P8; ///< pressure compensation value 97 | int16_t dig_P9; ///< pressure compensation value 98 | 99 | uint8_t dig_H1; ///< humidity compensation value 100 | int16_t dig_H2; ///< humidity compensation value 101 | uint8_t dig_H3; ///< humidity compensation value 102 | int16_t dig_H4; ///< humidity compensation value 103 | int16_t dig_H5; ///< humidity compensation value 104 | int8_t dig_H6; ///< humidity compensation value 105 | } bme280_calib_data; 106 | /*=========================================================================*/ 107 | 108 | class Adafruit_BME280; 109 | 110 | /** Adafruit Unified Sensor interface for temperature component of BME280 */ 111 | class Adafruit_BME280_Temp : public Adafruit_Sensor { 112 | public: 113 | /** @brief Create an Adafruit_Sensor compatible object for the temp sensor 114 | @param parent A pointer to the BME280 class */ 115 | Adafruit_BME280_Temp(Adafruit_BME280 *parent) { _theBME280 = parent; } 116 | bool getEvent(sensors_event_t *); 117 | void getSensor(sensor_t *); 118 | 119 | private: 120 | int _sensorID = 280; 121 | Adafruit_BME280 *_theBME280 = NULL; 122 | }; 123 | 124 | /** Adafruit Unified Sensor interface for pressure component of BME280 */ 125 | class Adafruit_BME280_Pressure : public Adafruit_Sensor { 126 | public: 127 | /** @brief Create an Adafruit_Sensor compatible object for the pressure sensor 128 | @param parent A pointer to the BME280 class */ 129 | Adafruit_BME280_Pressure(Adafruit_BME280 *parent) { _theBME280 = parent; } 130 | bool getEvent(sensors_event_t *); 131 | void getSensor(sensor_t *); 132 | 133 | private: 134 | int _sensorID = 280; 135 | Adafruit_BME280 *_theBME280 = NULL; 136 | }; 137 | 138 | /** Adafruit Unified Sensor interface for humidity component of BME280 */ 139 | class Adafruit_BME280_Humidity : public Adafruit_Sensor { 140 | public: 141 | /** @brief Create an Adafruit_Sensor compatible object for the humidity sensor 142 | @param parent A pointer to the BME280 class */ 143 | Adafruit_BME280_Humidity(Adafruit_BME280 *parent) { _theBME280 = parent; } 144 | bool getEvent(sensors_event_t *); 145 | void getSensor(sensor_t *); 146 | 147 | private: 148 | int _sensorID = 280; 149 | Adafruit_BME280 *_theBME280 = NULL; 150 | }; 151 | 152 | /**************************************************************************/ 153 | /*! 154 | @brief Class that stores state and functions for interacting with BME280 IC 155 | */ 156 | /**************************************************************************/ 157 | class Adafruit_BME280 { 158 | public: 159 | /**************************************************************************/ 160 | /*! 161 | @brief sampling rates 162 | */ 163 | /**************************************************************************/ 164 | enum sensor_sampling { 165 | SAMPLING_NONE = 0b000, 166 | SAMPLING_X1 = 0b001, 167 | SAMPLING_X2 = 0b010, 168 | SAMPLING_X4 = 0b011, 169 | SAMPLING_X8 = 0b100, 170 | SAMPLING_X16 = 0b101 171 | }; 172 | 173 | /**************************************************************************/ 174 | /*! 175 | @brief power modes 176 | */ 177 | /**************************************************************************/ 178 | enum sensor_mode { 179 | MODE_SLEEP = 0b00, 180 | MODE_FORCED = 0b01, 181 | MODE_NORMAL = 0b11 182 | }; 183 | 184 | /**************************************************************************/ 185 | /*! 186 | @brief filter values 187 | */ 188 | /**************************************************************************/ 189 | enum sensor_filter { 190 | FILTER_OFF = 0b000, 191 | FILTER_X2 = 0b001, 192 | FILTER_X4 = 0b010, 193 | FILTER_X8 = 0b011, 194 | FILTER_X16 = 0b100 195 | }; 196 | 197 | /**************************************************************************/ 198 | /*! 199 | @brief standby duration in ms 200 | */ 201 | /**************************************************************************/ 202 | enum standby_duration { 203 | STANDBY_MS_0_5 = 0b000, 204 | STANDBY_MS_10 = 0b110, 205 | STANDBY_MS_20 = 0b111, 206 | STANDBY_MS_62_5 = 0b001, 207 | STANDBY_MS_125 = 0b010, 208 | STANDBY_MS_250 = 0b011, 209 | STANDBY_MS_500 = 0b100, 210 | STANDBY_MS_1000 = 0b101 211 | }; 212 | 213 | // constructors 214 | Adafruit_BME280(); 215 | Adafruit_BME280(int8_t cspin, SPIClass *theSPI = &SPI); 216 | Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin); 217 | ~Adafruit_BME280(void); 218 | bool begin(uint8_t addr = BME280_ADDRESS, TwoWire *theWire = &Wire); 219 | bool init(); 220 | 221 | void setSampling(sensor_mode mode = MODE_NORMAL, 222 | sensor_sampling tempSampling = SAMPLING_X16, 223 | sensor_sampling pressSampling = SAMPLING_X16, 224 | sensor_sampling humSampling = SAMPLING_X16, 225 | sensor_filter filter = FILTER_OFF, 226 | standby_duration duration = STANDBY_MS_0_5); 227 | 228 | bool takeForcedMeasurement(void); 229 | float readTemperature(void); 230 | float readPressure(void); 231 | float readHumidity(void); 232 | 233 | float readAltitude(float seaLevel); 234 | float seaLevelForAltitude(float altitude, float pressure); 235 | uint32_t sensorID(void); 236 | 237 | float getTemperatureCompensation(void); 238 | void setTemperatureCompensation(float); 239 | 240 | Adafruit_Sensor *getTemperatureSensor(void); 241 | Adafruit_Sensor *getPressureSensor(void); 242 | Adafruit_Sensor *getHumiditySensor(void); 243 | 244 | protected: 245 | Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface 246 | Adafruit_SPIDevice *spi_dev = NULL; ///< Pointer to SPI bus interface 247 | 248 | Adafruit_BME280_Temp *temp_sensor = NULL; 249 | //!< Adafruit_Sensor compat temperature sensor component 250 | 251 | Adafruit_BME280_Pressure *pressure_sensor = NULL; 252 | //!< Adafruit_Sensor compat pressure sensor component 253 | 254 | Adafruit_BME280_Humidity *humidity_sensor = NULL; 255 | //!< Adafruit_Sensor compat humidity sensor component 256 | 257 | void readCoefficients(void); 258 | bool isReadingCalibration(void); 259 | 260 | void write8(byte reg, byte value); 261 | uint8_t read8(byte reg); 262 | uint16_t read16(byte reg); 263 | uint32_t read24(byte reg); 264 | int16_t readS16(byte reg); 265 | uint16_t read16_LE(byte reg); // little endian 266 | int16_t readS16_LE(byte reg); // little endian 267 | 268 | uint8_t _i2caddr; //!< I2C addr for the TwoWire interface 269 | int32_t _sensorID; //!< ID of the BME Sensor 270 | int32_t t_fine; //!< temperature with high resolution, stored as an attribute 271 | //!< as this is used for temperature compensation reading 272 | //!< humidity and pressure 273 | 274 | int32_t t_fine_adjust = 0; //!< add to compensate temp readings and in turn 275 | //!< to pressure and humidity readings 276 | 277 | bme280_calib_data _bme280_calib; //!< here calibration data is stored 278 | 279 | /**************************************************************************/ 280 | /*! 281 | @brief config register 282 | */ 283 | /**************************************************************************/ 284 | struct config { 285 | // inactive duration (standby time) in normal mode 286 | // 000 = 0.5 ms 287 | // 001 = 62.5 ms 288 | // 010 = 125 ms 289 | // 011 = 250 ms 290 | // 100 = 500 ms 291 | // 101 = 1000 ms 292 | // 110 = 10 ms 293 | // 111 = 20 ms 294 | unsigned int t_sb : 3; ///< inactive duration (standby time) in normal mode 295 | 296 | // filter settings 297 | // 000 = filter off 298 | // 001 = 2x filter 299 | // 010 = 4x filter 300 | // 011 = 8x filter 301 | // 100 and above = 16x filter 302 | unsigned int filter : 3; ///< filter settings 303 | 304 | // unused - don't set 305 | unsigned int none : 1; ///< unused - don't set 306 | unsigned int spi3w_en : 1; ///< unused - don't set 307 | 308 | /// @return combined config register 309 | unsigned int get() { return (t_sb << 5) | (filter << 2) | spi3w_en; } 310 | }; 311 | config _configReg; //!< config register object 312 | 313 | /**************************************************************************/ 314 | /*! 315 | @brief ctrl_meas register 316 | */ 317 | /**************************************************************************/ 318 | struct ctrl_meas { 319 | // temperature oversampling 320 | // 000 = skipped 321 | // 001 = x1 322 | // 010 = x2 323 | // 011 = x4 324 | // 100 = x8 325 | // 101 and above = x16 326 | unsigned int osrs_t : 3; ///< temperature oversampling 327 | 328 | // pressure oversampling 329 | // 000 = skipped 330 | // 001 = x1 331 | // 010 = x2 332 | // 011 = x4 333 | // 100 = x8 334 | // 101 and above = x16 335 | unsigned int osrs_p : 3; ///< pressure oversampling 336 | 337 | // device mode 338 | // 00 = sleep 339 | // 01 or 10 = forced 340 | // 11 = normal 341 | unsigned int mode : 2; ///< device mode 342 | 343 | /// @return combined ctrl register 344 | unsigned int get() { return (osrs_t << 5) | (osrs_p << 2) | mode; } 345 | }; 346 | ctrl_meas _measReg; //!< measurement register object 347 | 348 | /**************************************************************************/ 349 | /*! 350 | @brief ctrl_hum register 351 | */ 352 | /**************************************************************************/ 353 | struct ctrl_hum { 354 | /// unused - don't set 355 | unsigned int none : 5; 356 | 357 | // humidity oversampling 358 | // 000 = skipped 359 | // 001 = x1 360 | // 010 = x2 361 | // 011 = x4 362 | // 100 = x8 363 | // 101 and above = x16 364 | unsigned int osrs_h : 3; ///< humidity oversampling 365 | 366 | /// @return combined ctrl hum register 367 | unsigned int get() { return (osrs_h); } 368 | }; 369 | ctrl_hum _humReg; //!< hum register object 370 | }; 371 | 372 | #endif 373 | -------------------------------------------------------------------------------- /Adafruit_BME280.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_BME280.cpp 3 | * 4 | * @mainpage Adafruit BME280 humidity, temperature & pressure sensor 5 | * 6 | * @section intro_sec Introduction 7 | * 8 | * Driver for the BME280 humidity, temperature & pressure sensor 9 | * 10 | * These sensors use I2C or SPI to communicate, 2 or 4 pins are required 11 | * to interface. 12 | * 13 | * Designed specifically to work with the Adafruit BME280 Breakout 14 | * ----> http://www.adafruit.com/products/2652 15 | * 16 | * Adafruit invests time and resources providing this open source code, 17 | * please support Adafruit and open-source hardware by purchasing 18 | * products from Adafruit! 19 | * 20 | * @section author Author 21 | * 22 | * Written by Kevin "KTOWN" Townsend for Adafruit Industries. 23 | * 24 | * @section license License 25 | * 26 | * BSD license, all text here must be included in any redistribution. 27 | * See the LICENSE file for details. 28 | * 29 | */ 30 | 31 | #include "Adafruit_BME280.h" 32 | #include "Arduino.h" 33 | 34 | /*! 35 | * @brief class constructor 36 | */ 37 | Adafruit_BME280::Adafruit_BME280() {} 38 | 39 | /*! 40 | * @brief class constructor if using hardware SPI 41 | * @param cspin the chip select pin to use 42 | * @param *theSPI 43 | * optional SPI object 44 | */ 45 | Adafruit_BME280::Adafruit_BME280(int8_t cspin, SPIClass *theSPI) { 46 | spi_dev = new Adafruit_SPIDevice(cspin, 1000000, SPI_BITORDER_MSBFIRST, 47 | SPI_MODE0, theSPI); 48 | } 49 | 50 | /*! 51 | * @brief class constructor if using software SPI 52 | * @param cspin the chip select pin to use 53 | * @param mosipin the MOSI pin to use 54 | * @param misopin the MISO pin to use 55 | * @param sckpin the SCK pin to use 56 | */ 57 | Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, 58 | int8_t sckpin) { 59 | spi_dev = new Adafruit_SPIDevice(cspin, sckpin, misopin, mosipin); 60 | } 61 | 62 | Adafruit_BME280::~Adafruit_BME280(void) { 63 | if (spi_dev) { 64 | delete spi_dev; 65 | } 66 | if (i2c_dev) { 67 | delete i2c_dev; 68 | } 69 | if (temp_sensor) { 70 | delete temp_sensor; 71 | } 72 | if (pressure_sensor) { 73 | delete pressure_sensor; 74 | } 75 | if (humidity_sensor) { 76 | delete humidity_sensor; 77 | } 78 | } 79 | 80 | /*! 81 | * @brief Initialise sensor with given parameters / settings 82 | * @param addr the I2C address the device can be found on 83 | * @param theWire the I2C object to use, defaults to &Wire 84 | * @returns true on success, false otherwise 85 | */ 86 | bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) { 87 | if (spi_dev == NULL) { 88 | // I2C mode 89 | if (i2c_dev) 90 | delete i2c_dev; 91 | i2c_dev = new Adafruit_I2CDevice(addr, theWire); 92 | if (!i2c_dev->begin()) 93 | return false; 94 | } else { 95 | // SPI mode 96 | if (!spi_dev->begin()) 97 | return false; 98 | } 99 | return init(); 100 | } 101 | 102 | /*! 103 | * @brief Initialise sensor with given parameters / settings 104 | * @returns true on success, false otherwise 105 | */ 106 | bool Adafruit_BME280::init() { 107 | // check if sensor, i.e. the chip ID is correct 108 | _sensorID = read8(BME280_REGISTER_CHIPID); 109 | if (_sensorID != 0x60) 110 | return false; 111 | 112 | // reset the device using soft-reset 113 | // this makes sure the IIR is off, etc. 114 | write8(BME280_REGISTER_SOFTRESET, 0xB6); 115 | 116 | // wait for chip to wake up. 117 | delay(10); 118 | 119 | // if chip is still reading calibration, delay 120 | while (isReadingCalibration()) 121 | delay(10); 122 | 123 | readCoefficients(); // read trimming parameters, see DS 4.2.2 124 | 125 | setSampling(); // use defaults 126 | 127 | delay(100); 128 | 129 | return true; 130 | } 131 | 132 | /*! 133 | * @brief setup sensor with given parameters / settings 134 | * 135 | * @param mode the power mode to use for the sensor 136 | * @param tempSampling the temp samping rate to use 137 | * @param pressSampling the pressure sampling rate to use 138 | * @param humSampling the humidity sampling rate to use 139 | * @param filter the filter mode to use 140 | * @param duration the standby duration to use 141 | */ 142 | void Adafruit_BME280::setSampling(sensor_mode mode, 143 | sensor_sampling tempSampling, 144 | sensor_sampling pressSampling, 145 | sensor_sampling humSampling, 146 | sensor_filter filter, 147 | standby_duration duration) { 148 | _measReg.mode = mode; 149 | _measReg.osrs_t = tempSampling; 150 | _measReg.osrs_p = pressSampling; 151 | 152 | _humReg.osrs_h = humSampling; 153 | _configReg.filter = filter; 154 | _configReg.t_sb = duration; 155 | _configReg.spi3w_en = 0; 156 | 157 | // making sure sensor is in sleep mode before setting configuration 158 | // as it otherwise may be ignored 159 | write8(BME280_REGISTER_CONTROL, MODE_SLEEP); 160 | 161 | // you must make sure to also set REGISTER_CONTROL after setting the 162 | // CONTROLHUMID register, otherwise the values won't be applied (see 163 | // DS 5.4.3) 164 | write8(BME280_REGISTER_CONTROLHUMID, _humReg.get()); 165 | write8(BME280_REGISTER_CONFIG, _configReg.get()); 166 | write8(BME280_REGISTER_CONTROL, _measReg.get()); 167 | } 168 | 169 | /*! 170 | * @brief Writes an 8 bit value over I2C or SPI 171 | * @param reg the register address to write to 172 | * @param value the value to write to the register 173 | */ 174 | void Adafruit_BME280::write8(byte reg, byte value) { 175 | byte buffer[2]; 176 | buffer[1] = value; 177 | if (i2c_dev) { 178 | buffer[0] = reg; 179 | i2c_dev->write(buffer, 2); 180 | } else { 181 | buffer[0] = reg & ~0x80; 182 | spi_dev->write(buffer, 2); 183 | } 184 | } 185 | 186 | /*! 187 | * @brief Reads an 8 bit value over I2C or SPI 188 | * @param reg the register address to read from 189 | * @returns the data byte read from the device 190 | */ 191 | uint8_t Adafruit_BME280::read8(byte reg) { 192 | uint8_t buffer[1]; 193 | if (i2c_dev) { 194 | buffer[0] = uint8_t(reg); 195 | i2c_dev->write_then_read(buffer, 1, buffer, 1); 196 | } else { 197 | buffer[0] = uint8_t(reg | 0x80); 198 | spi_dev->write_then_read(buffer, 1, buffer, 1); 199 | } 200 | return buffer[0]; 201 | } 202 | 203 | /*! 204 | * @brief Reads a 16 bit value over I2C or SPI 205 | * @param reg the register address to read from 206 | * @returns the 16 bit data value read from the device 207 | */ 208 | uint16_t Adafruit_BME280::read16(byte reg) { 209 | uint8_t buffer[2]; 210 | 211 | if (i2c_dev) { 212 | buffer[0] = uint8_t(reg); 213 | i2c_dev->write_then_read(buffer, 1, buffer, 2); 214 | } else { 215 | buffer[0] = uint8_t(reg | 0x80); 216 | spi_dev->write_then_read(buffer, 1, buffer, 2); 217 | } 218 | return uint16_t(buffer[0]) << 8 | uint16_t(buffer[1]); 219 | } 220 | 221 | /*! 222 | * @brief Reads a signed 16 bit little endian value over I2C or SPI 223 | * @param reg the register address to read from 224 | * @returns the 16 bit data value read from the device 225 | */ 226 | uint16_t Adafruit_BME280::read16_LE(byte reg) { 227 | uint16_t temp = read16(reg); 228 | return (temp >> 8) | (temp << 8); 229 | } 230 | 231 | /*! 232 | * @brief Reads a signed 16 bit value over I2C or SPI 233 | * @param reg the register address to read from 234 | * @returns the 16 bit data value read from the device 235 | */ 236 | int16_t Adafruit_BME280::readS16(byte reg) { return (int16_t)read16(reg); } 237 | 238 | /*! 239 | * @brief Reads a signed little endian 16 bit value over I2C or SPI 240 | * @param reg the register address to read from 241 | * @returns the 16 bit data value read from the device 242 | */ 243 | int16_t Adafruit_BME280::readS16_LE(byte reg) { 244 | return (int16_t)read16_LE(reg); 245 | } 246 | 247 | /*! 248 | * @brief Reads a 24 bit value over I2C 249 | * @param reg the register address to read from 250 | * @returns the 24 bit data value read from the device 251 | */ 252 | uint32_t Adafruit_BME280::read24(byte reg) { 253 | uint8_t buffer[3]; 254 | 255 | if (i2c_dev) { 256 | buffer[0] = uint8_t(reg); 257 | i2c_dev->write_then_read(buffer, 1, buffer, 3); 258 | } else { 259 | buffer[0] = uint8_t(reg | 0x80); 260 | spi_dev->write_then_read(buffer, 1, buffer, 3); 261 | } 262 | 263 | return uint32_t(buffer[0]) << 16 | uint32_t(buffer[1]) << 8 | 264 | uint32_t(buffer[2]); 265 | } 266 | 267 | /*! 268 | * @brief Take a new measurement (only possible in forced mode) 269 | @returns true in case of success else false 270 | */ 271 | bool Adafruit_BME280::takeForcedMeasurement(void) { 272 | bool return_value = false; 273 | // If we are in forced mode, the BME sensor goes back to sleep after each 274 | // measurement and we need to set it to forced mode once at this point, so 275 | // it will take the next measurement and then return to sleep again. 276 | // In normal mode simply does new measurements periodically. 277 | if (_measReg.mode == MODE_FORCED) { 278 | return_value = true; 279 | // set to forced mode, i.e. "take next measurement" 280 | write8(BME280_REGISTER_CONTROL, _measReg.get()); 281 | // Store current time to measure the timeout 282 | uint32_t timeout_start = millis(); 283 | // wait until measurement has been completed, otherwise we would read the 284 | // the values from the last measurement or the timeout occurred after 2 sec. 285 | while (read8(BME280_REGISTER_STATUS) & 0x08) { 286 | // In case of a timeout, stop the while loop 287 | if ((millis() - timeout_start) > 2000) { 288 | return_value = false; 289 | break; 290 | } 291 | delay(1); 292 | } 293 | } 294 | return return_value; 295 | } 296 | 297 | /*! 298 | * @brief Reads the factory-set coefficients 299 | */ 300 | void Adafruit_BME280::readCoefficients(void) { 301 | _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); 302 | _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); 303 | _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); 304 | 305 | _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); 306 | _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); 307 | _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); 308 | _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); 309 | _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); 310 | _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); 311 | _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); 312 | _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); 313 | _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); 314 | 315 | _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); 316 | _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); 317 | _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3); 318 | _bme280_calib.dig_H4 = ((int8_t)read8(BME280_REGISTER_DIG_H4) << 4) | 319 | (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF); 320 | _bme280_calib.dig_H5 = ((int8_t)read8(BME280_REGISTER_DIG_H5 + 1) << 4) | 321 | (read8(BME280_REGISTER_DIG_H5) >> 4); 322 | _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); 323 | } 324 | 325 | /*! 326 | * @brief return true if chip is busy reading cal data 327 | * @returns true if reading calibration, false otherwise 328 | */ 329 | bool Adafruit_BME280::isReadingCalibration(void) { 330 | uint8_t const rStatus = read8(BME280_REGISTER_STATUS); 331 | 332 | return (rStatus & (1 << 0)) != 0; 333 | } 334 | 335 | /*! 336 | * @brief Returns the temperature from the sensor 337 | * @returns the temperature read from the device or NaN if sampling off 338 | */ 339 | float Adafruit_BME280::readTemperature(void) { 340 | int32_t var1, var2; 341 | if (_measReg.osrs_t == sensor_sampling::SAMPLING_NONE) 342 | return NAN; 343 | 344 | int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); 345 | adc_T >>= 4; 346 | 347 | var1 = (int32_t)((adc_T / 8) - ((int32_t)_bme280_calib.dig_T1 * 2)); 348 | var1 = (var1 * ((int32_t)_bme280_calib.dig_T2)) / 2048; 349 | var2 = (int32_t)((adc_T / 16) - ((int32_t)_bme280_calib.dig_T1)); 350 | var2 = (((var2 * var2) / 4096) * ((int32_t)_bme280_calib.dig_T3)) / 16384; 351 | 352 | t_fine = var1 + var2 + t_fine_adjust; 353 | 354 | int32_t T = (t_fine * 5 + 128) / 256; 355 | 356 | return (float)T / 100; 357 | } 358 | 359 | /*! 360 | * @brief Returns the pressure from the sensor 361 | * @returns the pressure value (in Pascal) or NaN if sampling off 362 | */ 363 | float Adafruit_BME280::readPressure(void) { 364 | int64_t var1, var2, var3, var4; 365 | if (_measReg.osrs_p == sensor_sampling::SAMPLING_NONE) 366 | return NAN; 367 | 368 | readTemperature(); // must be done first to get t_fine 369 | 370 | int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); 371 | adc_P >>= 4; 372 | 373 | var1 = ((int64_t)t_fine) - 128000; 374 | var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; 375 | var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) * 131072); 376 | var2 = var2 + (((int64_t)_bme280_calib.dig_P4) * 34359738368); 377 | var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) / 256) + 378 | ((var1 * ((int64_t)_bme280_calib.dig_P2) * 4096)); 379 | var3 = ((int64_t)1) * 140737488355328; 380 | var1 = (var3 + var1) * ((int64_t)_bme280_calib.dig_P1) / 8589934592; 381 | 382 | if (var1 == 0) { 383 | return 0; // avoid exception caused by division by zero 384 | } 385 | 386 | var4 = 1048576 - adc_P; 387 | var4 = (((var4 * 2147483648) - var2) * 3125) / var1; 388 | var1 = (((int64_t)_bme280_calib.dig_P9) * (var4 / 8192) * (var4 / 8192)) / 389 | 33554432; 390 | var2 = (((int64_t)_bme280_calib.dig_P8) * var4) / 524288; 391 | var4 = ((var4 + var1 + var2) / 256) + (((int64_t)_bme280_calib.dig_P7) * 16); 392 | 393 | float P = var4 / 256.0; 394 | 395 | return P; 396 | } 397 | 398 | /*! 399 | * @brief Returns the humidity from the sensor 400 | * @returns the humidity value read from the device or NaN if sampling off 401 | */ 402 | float Adafruit_BME280::readHumidity(void) { 403 | int32_t var1, var2, var3, var4, var5; 404 | if (_humReg.osrs_h == sensor_sampling::SAMPLING_NONE) 405 | return NAN; 406 | 407 | readTemperature(); // must be done first to get t_fine 408 | 409 | int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA); 410 | var1 = t_fine - ((int32_t)76800); 411 | var2 = (int32_t)(adc_H * 16384); 412 | var3 = (int32_t)(((int32_t)_bme280_calib.dig_H4) * 1048576); 413 | var4 = ((int32_t)_bme280_calib.dig_H5) * var1; 414 | var5 = (((var2 - var3) - var4) + (int32_t)16384) / 32768; 415 | var2 = (var1 * ((int32_t)_bme280_calib.dig_H6)) / 1024; 416 | var3 = (var1 * ((int32_t)_bme280_calib.dig_H3)) / 2048; 417 | var4 = ((var2 * (var3 + (int32_t)32768)) / 1024) + (int32_t)2097152; 418 | var2 = ((var4 * ((int32_t)_bme280_calib.dig_H2)) + 8192) / 16384; 419 | var3 = var5 * var2; 420 | var4 = ((var3 / 32768) * (var3 / 32768)) / 128; 421 | var5 = var3 - ((var4 * ((int32_t)_bme280_calib.dig_H1)) / 16); 422 | var5 = (var5 < 0 ? 0 : var5); 423 | var5 = (var5 > 419430400 ? 419430400 : var5); 424 | uint32_t H = (uint32_t)(var5 / 4096); 425 | 426 | return (float)H / 1024.0; 427 | } 428 | 429 | /*! 430 | * Calculates the altitude (in meters) from the specified atmospheric 431 | * pressure (in hPa), and sea-level pressure (in hPa). 432 | * @param seaLevel Sea-level pressure in hPa 433 | * @returns the altitude value read from the device 434 | */ 435 | float Adafruit_BME280::readAltitude(float seaLevel) { 436 | // Equation taken from BMP180 datasheet (page 16): 437 | // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf 438 | 439 | // Note that using the equation from wikipedia can give bad results 440 | // at high altitude. See this thread for more information: 441 | // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 442 | 443 | float atmospheric = readPressure() / 100.0F; 444 | return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); 445 | } 446 | 447 | /*! 448 | * Calculates the pressure at sea level (in hPa) from the specified 449 | * altitude (in meters), and atmospheric pressure (in hPa). 450 | * @param altitude Altitude in meters 451 | * @param atmospheric Atmospheric pressure in hPa 452 | * @returns the pressure at sea level (in hPa) from the specified altitude 453 | */ 454 | float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) { 455 | // Equation taken from BMP180 datasheet (page 17): 456 | // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf 457 | 458 | // Note that using the equation from wikipedia can give bad results 459 | // at high altitude. See this thread for more information: 460 | // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 461 | 462 | return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255); 463 | } 464 | 465 | /*! 466 | * Returns Sensor ID found by init() for diagnostics 467 | * @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280 468 | */ 469 | uint32_t Adafruit_BME280::sensorID(void) { return _sensorID; } 470 | 471 | /*! 472 | * Returns the current temperature compensation value in degrees Celsius 473 | * @returns the current temperature compensation value in degrees Celsius 474 | */ 475 | float Adafruit_BME280::getTemperatureCompensation(void) { 476 | return float((t_fine_adjust * 5) >> 8) / 100.0; 477 | }; 478 | 479 | /*! 480 | * Sets a value to be added to each temperature reading. This adjusted 481 | * temperature is used in pressure and humidity readings. 482 | * @param adjustment Value to be added to each temperature reading in Celsius 483 | */ 484 | void Adafruit_BME280::setTemperatureCompensation(float adjustment) { 485 | // convert the value in C into and adjustment to t_fine 486 | t_fine_adjust = ((int32_t(adjustment * 100) << 8)) / 5; 487 | }; 488 | 489 | /*! 490 | @brief Gets an Adafruit Unified Sensor object for the temp sensor component 491 | @return Adafruit_Sensor pointer to temperature sensor 492 | */ 493 | Adafruit_Sensor *Adafruit_BME280::getTemperatureSensor(void) { 494 | if (!temp_sensor) { 495 | temp_sensor = new Adafruit_BME280_Temp(this); 496 | } 497 | 498 | return temp_sensor; 499 | } 500 | 501 | /*! 502 | @brief Gets an Adafruit Unified Sensor object for the pressure sensor 503 | component 504 | @return Adafruit_Sensor pointer to pressure sensor 505 | */ 506 | Adafruit_Sensor *Adafruit_BME280::getPressureSensor(void) { 507 | if (!pressure_sensor) { 508 | pressure_sensor = new Adafruit_BME280_Pressure(this); 509 | } 510 | return pressure_sensor; 511 | } 512 | 513 | /*! 514 | @brief Gets an Adafruit Unified Sensor object for the humidity sensor 515 | component 516 | @return Adafruit_Sensor pointer to humidity sensor 517 | */ 518 | Adafruit_Sensor *Adafruit_BME280::getHumiditySensor(void) { 519 | if (!humidity_sensor) { 520 | humidity_sensor = new Adafruit_BME280_Humidity(this); 521 | } 522 | return humidity_sensor; 523 | } 524 | 525 | /**************************************************************************/ 526 | /*! 527 | @brief Gets the sensor_t data for the BME280's temperature sensor 528 | */ 529 | /**************************************************************************/ 530 | void Adafruit_BME280_Temp::getSensor(sensor_t *sensor) { 531 | /* Clear the sensor_t object */ 532 | memset(sensor, 0, sizeof(sensor_t)); 533 | 534 | /* Insert the sensor name in the fixed length char array */ 535 | strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); 536 | sensor->name[sizeof(sensor->name) - 1] = 0; 537 | sensor->version = 1; 538 | sensor->sensor_id = _sensorID; 539 | sensor->type = SENSOR_TYPE_AMBIENT_TEMPERATURE; 540 | sensor->min_delay = 0; 541 | sensor->min_value = -40.0; /* Temperature range -40 ~ +85 C */ 542 | sensor->max_value = +85.0; 543 | sensor->resolution = 0.01; /* 0.01 C */ 544 | } 545 | 546 | /**************************************************************************/ 547 | /*! 548 | @brief Gets the temperature as a standard sensor event 549 | @param event Sensor event object that will be populated 550 | @returns True 551 | */ 552 | /**************************************************************************/ 553 | bool Adafruit_BME280_Temp::getEvent(sensors_event_t *event) { 554 | /* Clear the event */ 555 | memset(event, 0, sizeof(sensors_event_t)); 556 | 557 | event->version = sizeof(sensors_event_t); 558 | event->sensor_id = _sensorID; 559 | event->type = SENSOR_TYPE_AMBIENT_TEMPERATURE; 560 | event->timestamp = millis(); 561 | event->temperature = _theBME280->readTemperature(); 562 | return true; 563 | } 564 | 565 | /**************************************************************************/ 566 | /*! 567 | @brief Gets the sensor_t data for the BME280's pressure sensor 568 | */ 569 | /**************************************************************************/ 570 | void Adafruit_BME280_Pressure::getSensor(sensor_t *sensor) { 571 | /* Clear the sensor_t object */ 572 | memset(sensor, 0, sizeof(sensor_t)); 573 | 574 | /* Insert the sensor name in the fixed length char array */ 575 | strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); 576 | sensor->name[sizeof(sensor->name) - 1] = 0; 577 | sensor->version = 1; 578 | sensor->sensor_id = _sensorID; 579 | sensor->type = SENSOR_TYPE_PRESSURE; 580 | sensor->min_delay = 0; 581 | sensor->min_value = 300.0; /* 300 ~ 1100 hPa */ 582 | sensor->max_value = 1100.0; 583 | sensor->resolution = 0.012; /* 0.12 hPa relative */ 584 | } 585 | 586 | /**************************************************************************/ 587 | /*! 588 | @brief Gets the pressure as a standard sensor event 589 | @param event Sensor event object that will be populated 590 | @returns True 591 | */ 592 | /**************************************************************************/ 593 | bool Adafruit_BME280_Pressure::getEvent(sensors_event_t *event) { 594 | /* Clear the event */ 595 | memset(event, 0, sizeof(sensors_event_t)); 596 | 597 | event->version = sizeof(sensors_event_t); 598 | event->sensor_id = _sensorID; 599 | event->type = SENSOR_TYPE_PRESSURE; 600 | event->timestamp = millis(); 601 | event->pressure = _theBME280->readPressure() / 100; // convert Pa to hPa 602 | return true; 603 | } 604 | 605 | /**************************************************************************/ 606 | /*! 607 | @brief Gets the sensor_t data for the BME280's humidity sensor 608 | */ 609 | /**************************************************************************/ 610 | void Adafruit_BME280_Humidity::getSensor(sensor_t *sensor) { 611 | /* Clear the sensor_t object */ 612 | memset(sensor, 0, sizeof(sensor_t)); 613 | 614 | /* Insert the sensor name in the fixed length char array */ 615 | strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); 616 | sensor->name[sizeof(sensor->name) - 1] = 0; 617 | sensor->version = 1; 618 | sensor->sensor_id = _sensorID; 619 | sensor->type = SENSOR_TYPE_RELATIVE_HUMIDITY; 620 | sensor->min_delay = 0; 621 | sensor->min_value = 0; 622 | sensor->max_value = 100; /* 0 - 100 % */ 623 | sensor->resolution = 3; /* 3% accuracy */ 624 | } 625 | 626 | /**************************************************************************/ 627 | /*! 628 | @brief Gets the humidity as a standard sensor event 629 | @param event Sensor event object that will be populated 630 | @returns True 631 | */ 632 | /**************************************************************************/ 633 | bool Adafruit_BME280_Humidity::getEvent(sensors_event_t *event) { 634 | /* Clear the event */ 635 | memset(event, 0, sizeof(sensors_event_t)); 636 | 637 | event->version = sizeof(sensors_event_t); 638 | event->sensor_id = _sensorID; 639 | event->type = SENSOR_TYPE_RELATIVE_HUMIDITY; 640 | event->timestamp = millis(); 641 | event->relative_humidity = _theBME280->readHumidity(); 642 | return true; 643 | } 644 | --------------------------------------------------------------------------------