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.

Not every chipset is supported by the closed-source BSEC library!

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!

Install Library

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

Load Example & Adjust

Load up the basic example

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.

QT Py + OLED Demo

Here's a demo that uses a 1.3" OLED + QT Py for a plug-n-play air quality display

Animation of Adafruit QT Py with onboard NeoPixel in a rainbow swirl.
What a cutie pie! Or is it... a QT Py? This diminutive dev board comes with our favorite lil chip, the SAMD21 (as made famous in our GEMMA M0 and Trinket M0 boards).This time it...
$7.50
In Stock
Monochrome 1.3" OLED module with Adafruit logos falling like snow
These displays are small, only about 1.3" diagonal, but very readable due to the high contrast of an OLED display. This display is made of 128x64 individual white OLED pixels,...
$19.95
In Stock
Angled shot of STEMMA QT / Qwiic JST SH 4-pin Cable.
This 4-wire cable is a little over 100mm / 4" long and fitted with JST-SH female 4-pin connectors on both ends. Compared with the chunkier JST-PH these are 1mm pitch instead of...
Out of Stock
// 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);
    }
  }
}

This guide was first published on Nov 08, 2017. It was last updated on Nov 08, 2017.

This page (BSEC Air Quality Library) was last updated on Feb 09, 2023.

Text editor powered by tinymce.