Learn how to use the BME680 Environmental Sensor with Arduino. The BME680 is a tiny sensor that can measure temperature, humidity, pressure and gas concentration. It also supports different power modes, including an ultra-lower power mode, which makes it suitable for battery powered projects.
Required Parts
Below you will find the parts required for this project. Apart from the BME680 sensor you will need a microcontroller. I picked an Arduino UNO but you can use any other Arduino as well. Since the BME680 runs on 5V and 3.3V you can also use an ESP32 or ESP8622, for instance.

BME680 Sensor

Arduino Uno

Dupont Wire Set

Breadboard

USB Cable for Arduino UNO
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Overview of the BME680 Sensor
The BME680 is a tiny sensor (3x3x1 mm) that can measure temperature, humidity, pressure and the concentration of Volatile Organic Compound (VOC) gases such as Ethanol, Alcohol and Carbon Monoxide. The picture below shows the senor with the small hole for gas exchange on the top:

Communication with the sensor is via an I2C or and SPI interface and is compatible with an Arduino or ESP32, for instance.
The BME680 chip has a working voltage of 1.7V to 3.6V. But usually you will use a breakout board with a voltage regulator that allows you to run the sensor on 5V as well. More about that later.
Current consumption is around 4µA for humidity, pressure and temperature measurements and up to 12mA when using all sensors including gas. However, you can put the sensor into sleep mode where it consumes only 0.15µA. Furthermore, the individual humidity, pressure and gas sensors can be independently enabled or disabled to manage power consumption.
Concerning accuracy, the sensor can measure humidity with ±3% accuracy, barometric pressure with ±1 hPa absolute accuracy, and temperature with ±1.0°C accuracy. Because of the accuracy in pressure, the sensor can be used to estimate altitude within ±1 meter.
| Sensor | Accuracy | Range |
| Temperature | ± 1.0 ºC | -40 to 85 ºC |
| Humidity | ± 3 % | 0 to 100 % |
| Pressure | ± 1 hPa | 300 to 1100 hPa |
Gas sensor
The BME680 contains a MOx (metal-oxide) sensor with a heater to measure the concentration of Volatile Organic Compounds (VOCs) in the air, specifically Ethane, Isoprene /2-methyl-1,3 Butadiene, Ethanol, Acetone, Carbon Monoxide. However, it cannot distinguish between those VOCs. Instead it outputs a resistance value proportional to the VOC concentration.
Note, that the gas sensor needs a burn-in time of 5 to 30 minutes! If you want to put the sensor (and microcontroller) into sleep mode between measurements you need to store the sensor state to shorten this burn-in time for the gas sensor. For humidity, pressure and temperature measurements you don’t need this.
For the complete technical specification see the datasheet linked below:
Breakout board for BME680
Since the BME680 chip is so tiny, you usually want a breakout board to connect the sensor to an Arduino or ESP32. The picture below shows the front and back of a typical breakout board for the BME680:

Pinout of BME680
The breakout board typically has the XC6206 (662K) low-dropout Voltage Regulator that allows you to run the sensor on 3.3V or 5V. The BME680 is the small square metal box, on the right side in the photo below:

On the left side are the pins for the I2C or SPI interface, along with the power supply connections (VCC, GND). For I2C communication, only the SCL and SDA pins are required. When working with the SPI interface, the CS (Chip Select) pin allows multiple BME680 sensors to share the same bus. Each sensor can be individually controlled by connecting its CS pin to a separate GPIO.
With the I2C interface, the SDO pin determines the sensor’s I2C address. Leaving SDO unconnected sets the address to 0x77, while connecting it to ground changes the address to 0x76. This configuration helps prevent address conflicts with other I2C devices and also enables two BME680 sensors to operate on the same I2C bus.
Connecting the BME680 via I2C
Connecting the BME680 via I2C is easy. Connect SCL and SDA of the BME680 to the corresponding pins on the Arduino UNO. GND needs to connected to GND, and VCC can be connected to 5V or 3.3V. See the complete wiring below:

If you don’t know, which pins are the hardware I2C pins for your board have a look at the Find I2C and SPI default pins tutorial. If you use a 3.3V board, e.g. an ESP32, make sure to connect VCC to 3.3V!
Code for measuring Temperature, Humidity, Pressure, Altitude and Gas
The following code demonstrates how to measure Temperature, Humidity, Pressure, Altitude and Gas concentration with the BME680. Have a quick look at the complete code first before we discuss its details:
#include "Adafruit_BME680.h"
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME680 bme;
void setup() {
Serial.begin(115200);
bme.begin();
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() {
if (bme.performReading()) {
Serial.print("Temperature = ");
Serial.print(bme.temperature);
Serial.println(" *C");
Serial.print("Humidity = ");
Serial.print(bme.humidity);
Serial.println(" %");
Serial.print("Pressure = ");
Serial.print(bme.pressure / 100.0);
Serial.println(" hPa");
Serial.print("Altitude = ");
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
Serial.print("Gas = ");
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(" KOhms");
Serial.println();
delay(2000);
}
}
libraries
To start, the code includes the Adafruit BME680 library that provides all the essential functions for the BME680 sensor. This library handles communication over I2C or SPI and simplifies sensor readings.
#include "Adafruit_BME680.h"
You can install this library as usual via the LIBRARY MANAGER. Just search for “bme680” and look for the “Adafruit BME680 Library” as shown below:

constants
Next, the code defines a constant for sea-level pressure in hectopascals (hPA). This value is important when calculating altitude. You can adjust it based on your location to improve accuracy. This map might help.
#define SEALEVELPRESSURE_HPA (1013.25)
objects
Here, the code creates an instance of the Adafruit_BME680 class. This object will let us access sensor readings and configure the sensor.
Adafruit_BME680 bme;
If you keep SDO unconnected and use the default I2C pins for your microcontroller, then this constructor should work as it is. Otherwise, you can specify the I2C address via bme.begin(addr) in the setup function:
bme.begin(uint8_t addr = BME68X_DEFAULT_ADDRESS);
or different I2C pins via
Adafruit_BME680(TwoWire *theWire = &Wire);
when constructing the sensor object.
setup
Inside the setup() function, the code begins serial communication at 115200 baud. This is essential for printing sensor data to the Serial Monitor.
Serial.begin(115200);
Then it initializes the BME680 sensor by calling bme.begin(). If the sensor is connected correctly and the library is working, it will begin communication.
bme.begin();
Remember, that you can specify a different I2C address by calling bme.begin(addr) instead, if needed.
The sensor’s accuracy depends heavily on its oversampling settings. In this line, the temperature measurement is set to oversample 8 times, which smooths out fluctuations and improves reliability.
bme.setTemperatureOversampling(BME680_OS_8X);
The BME680 supports the following settings for oversampling:
BME680_OS_NONEBME680_OS_1XBME680_OS_2XBME680_OS_4XBME680_OS_8XBME680_OS_16X
Humidity is set to be oversampled 2 times. That’s usually enough for most applications where humidity isn’t changing rapidly.
bme.setHumidityOversampling(BME680_OS_2X);
For pressure readings, the sensor uses 4x oversampling. Atmospheric pressure can fluctuate slowly, so this level provides a good balance between speed and accuracy.
bme.setPressureOversampling(BME680_OS_4X);
The code also applies a low-pass filter to the sensor readings using an IIR filter (Infinite Impulse Response). This helps eliminate noise from the pressure readings.
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
The following filter sizes are supported:
BME680_FILTER_SIZE_0BME680_FILTER_SIZE_1BME680_FILTER_SIZE_3BME680_FILTER_SIZE_7BME680_FILTER_SIZE_15BME680_FILTER_SIZE_31BME680_FILTER_SIZE_63BME680_FILTER_SIZE_127
Finally, there is a special setting for the gas sensor. It needs to heat up before taking a reading. This line sets the heater to 320°C for 150 milliseconds. This is critical for measuring volatile organic compounds (VOCs) in the air.
bme.setGasHeater(320, 150); // 320*C for 150 ms
loop
Now let’s look at the loop() function, which runs continuously. It starts by checking if a sensor reading is available using bme.performReading(). If the reading is successful, it proceeds to print the data.
if (bme.performReading()) {
The temperature is retrieved from bme.temperature, and the value is printed to the Serial Monitor in degrees Celsius.
Serial.print("Temperature = ");
Serial.print(bme.temperature);
Serial.println(" *C");
Similarly, the humidity reading is pulled from bme.humidity and printed in percent.
Serial.print("Humidity = ");
Serial.print(bme.humidity);
Serial.println(" %");
Atmospheric pressure is accessed from bme.pressure. The value is in Pascals, so dividing by 100 converts it to hPa (hectopascals), which is a standard unit for barometric pressure.
Serial.print("Pressure = ");
Serial.print(bme.pressure / 100.0);
Serial.println(" hPa");
Altitude is not directly measured—it’s calculated from the pressure using the sea-level reference. The readAltitude() function handles this for you.
Serial.print("Altitude = ");
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
Finally, the gas resistance (in Ohms) is printed. This value gives insight into the air quality. The sensor doesn’t tell you exactly which gases are present, but high resistance usually means cleaner air. Dividing by 1000 converts the value into kilo-ohms for easier reading.
Serial.print("Gas = ");
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(" KOhms");
The loop then pauses for 2 seconds before repeating. This delay helps you see the output clearly in the Serial Monitor. You should see the following output:

That’s it! You now understand how to set up and read data from the BME680 connected to an Arduino board via I2C. In the next section, I quickly show you how to use the SPI interface instead.
Connecting the BME680 via SPI
Instead of I2C you can also communicate with the BME680 via SPI, which requires more connections but allows for faster measurements.
Depending on the microcontroller board the pins for hardware SPI differ. See the Find I2C and SPI default pins tutorial, if you need to identify them. For the Arduino UNO those pins are 13 (SCK), 12 (MISO/SDO), 11 (MOSI/SDA) and 10 (CS/SS). The diagram below shows the connections you have to make.

Compared to the previous code, you only need to replace the following line that creates the sensor object
Adafruit_BME680 bme;
by this line, which specifies the pins used to connect BME680 via SPI:
#define BME_SCK 13 #define BME_MISO 12 #define BME_MOSI 11 #define BME_CS 10 Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);
All the other code can remain exactly the same.
Conclusion
In this tutorial you learned how to use the BME680 Environmental Sensor with an Arduino. The BME680 is very small sensor that can measure temperature, humidity, pressure and gas concentrations accurately.
In comparison to the very similar BME280, the BME680 has the additional gas sensor but that also means it needs to warm up for 5–20 minutes before gas readings are reliable and it consumes more power. If you don’t need the gas measurements go with the cheaper and smaller BME280. See the How To Use BME280 Pressure Sensor With Arduino tutorial for more information.
Note that there is also a BMP280, which is cheaper and uses less power, but only measures temperature and pressure. If you need only temperature and humidity go with the SI7021, instead, which is even smaller and more accurate. Have a look at the Si7021 Temperature Sensor Arduino Tutorial.
Other common but less accurate sensors to consider are the LM35, the TMP36, the DS18B20 and the DHT11/ DHT22. For displaying sensor data have a look at the Weather Station on e-Paper Display and the Temperature Plotter on e-Paper Display tutorials.
Finally, if you want to send environmental data over longer distance that are beyond Bluetooth or Wi-Fi range, long-range communication via LoRa might be of interest to you: Send Environmental Data with LoRa.
We did not talk about the interpretation of gas concentration measurements of the BME680. If you want to measure Air Quality have a look at the Measure Air Quality with BME680 tutorial, where we discuss this in detail.
If you have any questions, feel free to leave them in the comment section.
Happy Tinkering ; )
Stefan is a professional software developer and researcher. He has worked in robotics, bioinformatics, image/audio processing and education at Siemens, IBM and Google. He specializes in AI and machine learning and has a keen interest in DIY projects involving Arduino and 3D printing.

