The BME680 is an environmental digital sensor that measures gas, pressure, humidity and temperature. In this guide you’ll learn how to use the BME680 sensor module with the Arduino board. The sensor communicates with a microcontroller using I2C or SPI communication protocols.
You’ll learn how to wire the sensor to the Arduino board, install the required libraries and use a simple sketch to display the sensor readings in the Serial Monitor.
Introducing BME680 Environmental Sensor Module
The BME680 is an environmental sensor that combines gas, pressure, humidity and temperature sensors. The gas sensor can detect a broad range of gases like volatile organic compounds (VOC). For this reason, the BME680 can be used in indoor air quality control.
BME680 Measurements
The BME680 is a 4-in-1 digital sensor that measures:
- Temperature
- Humidity
- Barometric pressure
- Gas: Volatile Organic Compounds (VOC) like ethanol and carbon monoxide
Gas Sensor
The BME680 contains a MOX (Metal-oxide) sensor that detects VOCs in the air. This sensor gives you a qualitative idea of the sum of VOCs/contaminants in the surrounding air – it is not specific for a specific gas molecule.
MOX sensors are composed of a metal-oxide surface, a sensing chip to measure changes in conductivity, and a heater. It detects VOCs by adsorption of oxygen molecules on its sensitive layer. The BME680 reacts to most VOCs polluting indoor air (except CO2).
When the sensor comes into contact with the reducing gases, the oxygen molecules react and increase the conductivity across the surface. As a raw signal, the BME680 outputs resistance values. These values change due to variations in VOC concentrations:
- Higher concentration of VOCs » Lower resistance
- Lower concentration of VOCs » Higher resistance
The reactions that occur on the sensor surface (thus, the resistance) are influenced by parameters other than VOC concentration like temperature and humidity.
Relevant Information Regarding Gas Sensor
The gas sensor gives you a qualitative idea of VOCs gasses in the surrounding air. So, you can get trends, compare your results and see if the air quality is increasing or decreasing. To get precise measurements, you need to calibrate the sensor against knows sources and build a calibration curve.
When you first get the sensor, it is recommended to run it for 48 hours after start collecting “real” data. After that, it is also recommend to run the sensor for 30 minutes before getting a gas reading.
BME680 Accuracy
Here’s the accuracy of the temperature, humidity and pressure sensors of the BME680:
Sensor | Accuracy |
Temperature | +/- 1.0 ºC |
Humidity | +/- 3 % |
Pressure | +/- 1 hPa |
BME680 Operation Range
The following table shows the operation range for the temperature, humidity and pressure sensors for the BME680.
Sensor | Operation Range |
Temperature | -40 to 85 ºC |
Humidity | 0 to 100 % |
Pressure | 300 to 1100 hPa |
BME680 Pinout
Here’s the BME680 Pinout:
VCC | Powers the sensor |
GND | Common GND |
SCL | SCL pin for I2C communication SCK pin for SPI communication |
SDA | SDA pin for I2C communication SDI (MOSI) pin for SPI communication |
SDO | SDO (MISO) pin for SPI communication |
CS | Chip select pin for SPI communication |
BME680 Interface
The BME680 supports I2C and SPI Interfaces.
BME680 I2C
To use I2C communication protocol, use the following pins:
BME680 | Arduino |
SCL | A5 |
SDA | A4 |
BME680 SPI
To use SPI communication protocol, use the following pins:
BME680 | Arduino |
SCL (SCK SPI Clock) | D13 |
SDA (SDI MOSI) | D11 |
SDO (MISO) | D12 |
CS (Chip Select) | D10 |
Parts Required
To complete this tutorial you need the following parts:
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Schematic – Arduino with BME680
The BME680 can communicate using I2C or SPI communication protocols.
Arduino with BME680 using I2C
Follow the next schematic diagram to wire the BME680 to the Arduino using the I2C pins.
Arduino with BME680 using SPI
Alternatively, you may want to use SPI communication protocol instead. In that case, follow the next schematic diagram to wire the BME680 to the Arduino using the SPI pins.
Installing the BME680 Library
To get readings from the BME680 sensor module we’ll use the Adafruit_BME680 library. Follow the next steps to install the library in your Arduino IDE:
Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries. The Library Manager should open.
Search for “adafruit bme680 ” on the Search box and install the library.
Installing the Adafruit_Sensor Library
To use the BME680 library, you also need to install the Adafruit_Sensor library. Follow the next steps to install the library in your Arduino IDE:
Go to Sketch > Include Library > Manage Libraries and type “Adafruit Unified Sensor” in the search box. Scroll all the way down to find the library and install it.
After installing the libraries, restart your Arduino IDE.
Code Arduino – Reading BME680 Gas, Pressure, Humidity and Temperature
To read gas, pressure, temperature, and humidity we’ll use a sketch example from the library.
After installing the BME680 library, and the Adafruit_Sensor library, open the Arduino IDE and, go to File > Examples > Adafruit BME680 Library > bme680async.
/***
Read Our Complete Guide: https://RandomNerdTutorials.com/bme680-sensor-arduino-gas-temperature-humidity-pressure/
Designed specifically to work with the Adafruit BME680 Breakout ----> http://www.adafruit.com/products/3660 These sensors use I2C or SPI to communicate, 2 or 4 pins are required to interface. Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried & Kevin Townsend for Adafruit Industries. BSD license, all text above must be included in any redistribution
***/
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
/*#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10*/
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME680 bme; // I2C
//Adafruit_BME680 bme(BME_CS); // hardware SPI
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);
void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println(F("BME680 async test"));
if (!bme.begin()) {
Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
while (1);
}
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
}
void loop() {
// Tell BME680 to begin measurement.
unsigned long endTime = bme.beginReading();
if (endTime == 0) {
Serial.println(F("Failed to begin reading :("));
return;
}
Serial.print(F("Reading started at "));
Serial.print(millis());
Serial.print(F(" and will finish at "));
Serial.println(endTime);
Serial.println(F("You can do other work during BME680 measurement."));
delay(50); // This represents parallel work.
// There's no need to delay() until millis() >= endTime: bme.endReading()
// takes care of that. It's okay for parallel work to take longer than
// BME680's measurement time.
// Obtain measurement results from BME680. Note that this operation isn't
// instantaneous even if milli() >= endTime due to I2C/SPI latency.
if (!bme.endReading()) {
Serial.println(F("Failed to complete reading :("));
return;
}
Serial.print(F("Reading completed at "));
Serial.println(millis());
Serial.print(F("Temperature = "));
Serial.print(bme.temperature);
Serial.println(F(" *C"));
Serial.print(F("Pressure = "));
Serial.print(bme.pressure / 100.0);
Serial.println(F(" hPa"));
Serial.print(F("Humidity = "));
Serial.print(bme.humidity);
Serial.println(F(" %"));
Serial.print(F("Gas = "));
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(F(" KOhms"));
Serial.print(F("Approx. Altitude = "));
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(F(" m"));
Serial.println();
delay(2000);
}
How the Code Works
Continue reading this section to learn how the code works, or skip to the Demonstration section.
Libraries
The code starts by including the needed libraries: the wire library to use I2C, the SPI library (if you want to use SPI instead of I2C), the Adafruit_Sensor and Adafruit_BME680 libraries to interface with the BME680 sensor.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
SPI communication
We prefer to use I2C communication protocol with the sensor. However, the code is prepared if you want to use SPI. You just need to uncomment the following lines of code that define the SPI pins.
/*#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10*/
Sea level pressure
A variable called SEALEVELPRESSURE_HPA is created.
#define SEALEVELPRESSURE_HPA (1013.25)
This variable saves the pressure at the sea level in hectopascal (is equivalent to milibar). This variable is used to estimate the altitude for a given pressure by comparing it with the sea level pressure. This example uses the default value, but for accurate results, replace the value with the current sea level pressure at your location.
I2C
This example uses I2C communication protocol by default. The following line creates an Adafruit_BME680 object called bme on the Arduino I2C pins: D5 (SCL), D4 (SDA).
Adafruit_BME680 bme; // I2C
To use SPI, you need to comment this previous line and uncomment the following line.
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
setup()
In the setup() start a serial communication.
Serial.begin(115200);
Init BME680 Sensor
Initialize the BME680 sensor:
if (!bme.begin()) {
Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
while (1);
}
Set up the following parameters (oversampling, filter and gas heater) for the sensor.
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
To increase the resolution of the raw sensor data, it supports oversampling. We’ll use the default oversampling parameters, but you can change them.
- setTemperatureOversampling(): set temperature oversampling.
- setHumidityOversampling(): set humidity oversampling.
- setPressureOversampling(): set pressure oversampling.
These methods can accepts one of the following parameters:
- BME680_OS_NONE: turn off reading;
- BME680_OS_1X
- BME680_OS_2X
- BME680_OS_4X
- BME680_OS_8X
- BME680_OS_16X
The BME680 sensor integrates an internal IIR filter to reduce short-term changes in sensor output values caused by external disturbances. The setIIRFilterSize() method sets the IIR filter. It accepts the filter size as a parameter:
- BME680_FILTER_SIZE_0 (no filtering)
- BME680_FILTER_SIZE_1
- BME680_FILTER_SIZE_3
- BME680_FILTER_SIZE_7
- BME680_FILTER_SIZE_15
- BME680_FILTER_SIZE_31
- BME680_FILTER_SIZE_63
- BME680_FILTER_SIZE_127
The gas sensor integrates a heater. Set the heater profile using the setGasHeater() method that accepts as arguments:
- the heater temperature (in degrees Centigrade)
- the time the heater should be on (in milliseconds)
We’ll use the default settings: 320 ºC for 150 ms.
loop()
In the loop(), we’ll get measurements from the BME680 sensor.
First, tell the sensor to start an asynchronous reading with bme.beginReading(). This returns the time when the reading would be ready.
// Tell BME680 to begin measurement.
unsigned long endTime = bme.beginReading();
if (endTime == 0) {
Serial.println(F("Failed to begin reading :("));
return;
}
Serial.print(F("Reading started at "));
Serial.print(millis());
Serial.print(F(" and will finish at "));
Serial.println(endTime);
Then, call the endReading() method to end an asynchronous reading. If the asynchronous reading is still in progress, block until it ends.
if (!bme.endReading()) {
Serial.println(F("Failed to complete reading :("));
return;
}
After this, we can get the readings as follows:
- bme.temperature: returns temperature reading
- bme.pressure: returns pressure reading
- bme.humidity: returns humidity reading
- bme.gas_resistance: returns gas resistance
Serial.print(F("Temperature = "));
Serial.print(bme.temperature);
Serial.println(F(" *C"));
Serial.print(F("Pressure = "));
Serial.print(bme.pressure / 100.0);
Serial.println(F(" hPa"));
Serial.print(F("Humidity = "));
Serial.print(bme.humidity);
Serial.println(F(" %"));
Serial.print(F("Gas = "));
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(F(" KOhms"));
Serial.print(F("Approx. Altitude = "));
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(F(" m"));
For more information about the library methods, take a look at the Adafruit_BME680 Class Reference.
Demonstration
Upload the code to your Arduino board. Go to Tools > Board and select the Arduino board you’re using. Go to Tools > Port and select the port your board is connected to. Then, click the upload button.
Open the Serial Monitor at a baud rate of 115200, press the on-board RST button. The sensor measurements will be displayed.
Wrapping Up
The BME680 sensor module is a 4-in-1 digital sensor that combines gas, pressure, temperature and humidity sensors. The BME680 contains a MOX sensor that senses the presence of most VOC gases. This sensor gives you a qualitative idea of the sum of VOCs/contaminants in the surrounding air. For this reason, the BME680 can be used to monitor indoor air quality.
We hope you’ve found this getting started guide useful. We have guides for other popular sensors:
- BME280 Sensor with Arduino (Pressure, Temperature, Humidity)
- DS18B20 Temperature Sensor with Arduino
- DHT11/DHT22 Humidity and Temperature Sensor With Arduino
- LM35, LM335 and LM34 Temperature Sensors with Arduino
- DHT11 vs DHT22 vs LM35 vs DS18B20 vs BME280 vs BMP180
Learn more about the Arduino with our resources:
Thanks for reading.
Parabéns pelo post, Bme680, bem didático e amplia a utilização do Arduino UNO que anda esquecido.
Carlos Bruni
Ainda bem que gostou do post.
Obrigada 🙂
Cumprimentos,
Sara
It appears that BME680 has proprietary software to compute the air quality value from the other parameters. Do you have any experience with the software? I should be most grateful to receive your comments.
Thanks for another clear and concise report.
Hi.
Unfortunately, I don’t.
Regards,
Sara
I have used this sensor. Because of the heater they usually read 2-3C high compared to a reference thermometer, but you can allow for that with an offset in your code. But more seriously if you repeat readings at short intervals – less than a minute – the sensor accumulates heat and the offset steadily increases !
The extra Bosch library to analyse the raw readings is quite useful, but is usually too big for UNO type devices, but suitable for ESP32. Be careful that the values reported for CO2 are being implied by measuring VOCs, do not confuse these with direct CO2 measurements.
Thanks for sharing your experience with this sensors.
Regards,
Sara
Thanks, Hamish! I have not used BME680 yet but hope to very soon. Your comments are very helpful. I did not know about the temperature offset or the difficulty with fitting the library into UNO’s memory!
Hi,
I wanted to use this sensor as CO2-Sensor.
What means Gas: 66.06 KOhm based on CO2?
Hi.
To do that, you need the Bosch BSCE library: https://github.com/BoschSensortec/BSEC-Arduino-library
However, I couldn’t get it working.
Regards,
Sara
Thank you for the Guide. My first steps after 30 years without programming ans code. But the problem is the difference between the temperature of the BME680 and other thermometer. I like to try the offset method.
Best regards
Tobias
My experience is that if you use the BME680 under i2c.
That then the CS and the SDO pins must be connected to the GND.
Then scan for the i2c address with the i2c scanner from Arduino ide.
The module then continues to work stably.
If the pins stay open, they float and sometimes the i2c address changes so that the module is no longer seen by the software.
This sensor is 3.3v and not 5v.
And to help anyone reading this, just use a D1 Mini and ESPHome Bsec and have it working fast and easy
I need relative humidity, not humidity. Relative humidity is an equation of dew point and humidity. I need relative humidity. Can you add coding for that?
Dear Michael
The sensor measures rel. humidity directly, see the we page of Bosch: https://www.bosch-sensortec.com/products/environmental-sensors/gas-sensors/bme680/