The BME680 doesn't have built-in air quality calcualtion capabilities like other sensors like the SGP30 or CCS811. Instead, you only get temperature, pressure, humidity and gas resistance (the raw resistance value of the sensor in the BME60. So we have to use a separate library from Bosch to perform the conversion to get Air Quality values like the VOC and equivalent CO2.
The Bosch BSEC library is an all-in-one Arduino library that will get you all the values from the sensor and also perform the AQI calculations. It is not an open source library! You can only use it in Arduino and only with the chipsets supported.
We have tested the Adafruit SAMD21 (M0) series of chips and these work great. You can use an Adafruit QT Py, Trinket M0, Feather M0, etc!
According to Bosch, ESP32 and ESP8266 are also supported. AVR is not recommended - you definitely cannot fit the library into an Uno/ATmega328 or ATmega32u4, you could try using an Arduino Mega but it isnt suggested.
Really we recommend a SAMD21 or ESP board!
To avoid potential issues with some releases of the BSEC library, a specific release version should be selected when installing the library via Library Manager.
- Open Arduino Library Manager
- Search for "bsec" to find the library
- In the version drop down (see below), select 1.6.1480
- this version should work fine for this simple demo
- Click Install
Look for the part in setup()
where the iaqSensor
is started.
Change BME680_I2C_ADDR_PRIMARY
to BME680_I2C_ADDR_SECONDARY
We also recommend adding
while (!Serial) delay(10); // wait for console
right after Serial.begin
so that the console will print any errors out right after its opened
Upload to your board and open up the serial console at 115200 baud. You will see comma-separated values with the following heading
Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%], Static IAQ, CO2 equivalent, breath VOC equivalent
Note that the last 3 values are the calculated values. They will take a few minutes to normalize. Make sure to start your sensor in a clean air environment so it can normalize!
You can check the basic_config_state
example if you want to calibrate the sensor, store the state in EEPROM, then re-write it on boot so you don't have to go through the normalization process.



// SPDX-FileCopyrightText: 2020 Limor Fried for Adafruit Industries // SPDX-FileCopyrightText: 2020 Kevin Townsend for Adafruit Industries // // SPDX-License-Identifier: MIT /*************************************************************************** This is a library for the BME680 gas, humidity, temperature & pressure sensor 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 <Adafruit_SSD1306.h> #include "bsec.h" Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire); Bsec iaqSensor; String output; void setup() { Serial.begin(9600); //while (!Serial); Serial.println(F("BME680 test")); // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64 Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } Serial.println("OLED begun"); display.display(); delay(100); display.clearDisplay(); display.display(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setRotation(0); iaqSensor.begin(BME680_I2C_ADDR_SECONDARY, Wire); output = "\nBSEC library version " + String(iaqSensor.version.major) + "." + String(iaqSensor.version.minor) + "." + String(iaqSensor.version.major_bugfix) + "." + String(iaqSensor.version.minor_bugfix); Serial.println(output); checkIaqSensorStatus(); bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_RAW_TEMPERATURE, BSEC_OUTPUT_RAW_PRESSURE, BSEC_OUTPUT_RAW_HUMIDITY, BSEC_OUTPUT_RAW_GAS, BSEC_OUTPUT_IAQ, BSEC_OUTPUT_STATIC_IAQ, BSEC_OUTPUT_CO2_EQUIVALENT, BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, }; iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); checkIaqSensorStatus(); // Print the header output = "Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%], Static IAQ, CO2 equivalent, breath VOC equivalent"; Serial.println(output); } void loop() { display.setCursor(0,0); display.clearDisplay(); unsigned long time_trigger = millis(); if (! iaqSensor.run()) { // If no data is available checkIaqSensorStatus(); return; } output = String(time_trigger); output += ", " + String(iaqSensor.rawTemperature); output += ", " + String(iaqSensor.pressure); output += ", " + String(iaqSensor.rawHumidity); output += ", " + String(iaqSensor.gasResistance); output += ", " + String(iaqSensor.iaq); output += ", " + String(iaqSensor.iaqAccuracy); output += ", " + String(iaqSensor.temperature); output += ", " + String(iaqSensor.humidity); output += ", " + String(iaqSensor.staticIaq); output += ", " + String(iaqSensor.co2Equivalent); output += ", " + String(iaqSensor.breathVocEquivalent); Serial.println(output); Serial.print("Temperature = "); Serial.print(iaqSensor.temperature); Serial.println(" *C"); display.print("Temperature: "); display.print(iaqSensor.temperature); display.println(" *C"); Serial.print("Pressure = "); Serial.print(iaqSensor.pressure / 100.0); Serial.println(" hPa"); display.print("Pressure: "); display.print(iaqSensor.pressure / 100); display.println(" hPa"); Serial.print("Humidity = "); Serial.print(iaqSensor.humidity); Serial.println(" %"); display.print("Humidity: "); display.print(iaqSensor.humidity); display.println(" %"); Serial.print("IAQ = "); Serial.print(iaqSensor.staticIaq); Serial.println(""); display.print("IAQ: "); display.print(iaqSensor.staticIaq); display.println(""); Serial.print("CO2 equiv = "); Serial.print(iaqSensor.co2Equivalent); Serial.println(""); display.print("CO2eq: "); display.print(iaqSensor.co2Equivalent); display.println(""); Serial.print("Breath VOC = "); Serial.print(iaqSensor.breathVocEquivalent); Serial.println(""); display.print("VOC: "); display.print(iaqSensor.breathVocEquivalent); display.println(""); Serial.println(); display.display(); delay(2000); } // Helper function definitions void checkIaqSensorStatus(void) { if (iaqSensor.status != BSEC_OK) { if (iaqSensor.status < BSEC_OK) { output = "BSEC error code : " + String(iaqSensor.status); Serial.println(output); display.setCursor(0,0); display.println(output); display.display(); for (;;) delay(10); } else { output = "BSEC warning code : " + String(iaqSensor.status); Serial.println(output); } } if (iaqSensor.bme680Status != BME680_OK) { if (iaqSensor.bme680Status < BME680_OK) { output = "BME680 error code : " + String(iaqSensor.bme680Status); Serial.println(output); display.setCursor(0,0); display.println(output); display.display(); for (;;) delay(10); } else { output = "BME680 warning code : " + String(iaqSensor.bme680Status); Serial.println(output); } } }