Interfacing BME680 with Arduino also measure Indoor Air Quality Index

Overview:

In this Tutorial, We are going to learn What is BME680? Which parameters can BME680 measures? How BME680 sensor works? BME680 pinout, how to measure weather parameters and indoor air quality by interfacing BME680 with Arduino microcontroller? and What are the applications of BME680?

What is BME680?

bme680 beakout board module

BME680 developed by BOSCH sensortec by is the first gas sensor which integrates high-linearity and high-accuracy gas, temperature, humidity and Pressure sensors. With long term stability and ultra low power consumption make this sensors ideal for mobile applications and smart watches. BME680 can detect wide range of gases like Volatile Organic Compounds(VOCs) which helps to measure Indoor Air Quality for Personal wellbeing.

BME680 comes with high accuracy and additional features when compared with old models BMP180 and BME280. The Gas sensor on BME680 detects gases, coming from wall paints(like formaldehyde), Adhesives, cleaning supplies, Alcohols like Ethanol, Alcohol and gases like Carbon Monoxide which makes it a standalone full stack environmental sensor.

What are VOCs?

Volatile organic compounds (VOCs) are substances from organic origin, i.e. they contain carbon and are found in gaseous form in the air. They are compounds that evaporate easily under normal conditions of temperature and pressure and their volatility gives them the ability to spread in the environment and modify their chemical composition. They are pollutants produced as a result of combustion, the processing of paints, adhesives, petroleum products, pharmaceuticals and refrigerants.

This includes emissions from automotive and industrial activities, among others. VOCs include hydrocarbons, alcohols, aldehydes and organic acids, solvents, liquid fuels, synthetic substances and numerous organic compounds formed in the course of biological processes. Each category has different chemical properties, giving rise to different problems.

What parameters can BME680 measures and detects?

As we learnt from the above paragraph, The 4 in 1 sensor BME680 is the combination of temperature, humidity, Pressure and Gas sensors which can measure the below parameters with greater accuracy.

  • Temperature
  • Humidity
  • Pressure
  • Few Gases (VOC)
  • Altitude
  • Dew point (can be calculated through software code using temperature and Humidity)

How BME680 gas sensor works?

BME680 gas sensor has metal oxide(MOx) surface to measure the VOC gases in the surrounding environment. Generally Metal oxide based sensors have metal oxide sensitive surface, a chip to measure the electrical conductivity and a heater to heat the surface of the sensitive metal oxide.

When the sensor is turned on the heater heats the metal oxide surface and oxygen is absorbed on the surface. In the clean air the electrons in the Metal Oxide are attracted to Oxygen molecules in the air and forms a potential barrier which resists the flow of electric current.

So when VOC gases comes in contact with the metal oxide sensitive surface the gases react with the oxygen molecules on the surface thus the electrons are free from oxygen molecules which reduces the potential barrier and increases the flow of electric current.

bme680 behaviour with voc gases changes resistance

So in simple: When VOC gases contacts the sensor resistance increases which reduces the electric conductivity. and when VOC gases decreases the resistance decreases which increases the electrical conductivity. By measuring the resistance we can detect the VOC gases.

Note: BME680 cannot detect the VOC gases individually instead it gives the sum of VOC gases. BME680 detect most of the VOC gases but it doesn’t detect Carbon Dioxide( CO2).

BME680 pinout diagram:

BME680 pinout diagram with bme680 chip

From the above BME680 pinout diagram you can see there are 6 pins from which we are going to use only 4 in this project as the other 2 are for SPI communication protocol.

  • VCC: To power the sensor
  • GND: Common GND
  • SCL:  for I2C clock communication(SCK pin for SPI communication)
  • SDA:  for I2C data communication(SDI (MOSI) pin for SPI communication)
  • SDO: (MISO) pin for SPI communication
  • CS: Chip select pin for SPI communication

Changing BME680 default I2C address

The BME680 breakout module has a default I2C address of 0x76. There is a special feature through which you can change the default I2C Address so that you can connect and use up to two BME680 breakout modules on the same Arduino or ESP32. To change the I2C address to 0x77 simply connect SDO to GND.

Interfacing BME680 with Arduino microcontroller

Required components:

Product NameQuantityamazon logoamazon logo india
BME680 Environmental sensor module1https://amzn.to/3IGUFrshttps://amzn.to/3tBqRq0
Arduino Uno Microcontroller1https://amzn.to/3H4cKxZhttps://amzn.to/3638aTS
Few Connecting Wireshttps://amzn.to/3H2BV4ehttps://amzn.to/3J0WVu2
You can buy the required components from the given best buy links. We choose the components according to value for money.

Circuit diagram connecting BME680 and Arduino

Now connect all the required components as per the below Circuit diagram

interfacing bme680 with arduino circuit diagramFrom the above circuit diagram image you can see that we powered BME680 VCC and GND pins through 5v and GND pins of Arduino. And as we choose to use I2C communication we connected SCL and SDA of BME680 to A5 and A4 pins of Arduino board respectively. That’s it for connection which is very simple. Next step is to upload the code and get the environmental parameters to monitor.

Required Libraries

Adafruit developed a library for BME680 which does all the calculations in the background which makes us easy to get values without writing lots of code. Just install the libraries and call the function names to get the values.

You can install BME680 library through Arduino IDE default Library manager. or you can download the library through the below and extract it in Arduino libraries folder in Documents folder. This Library also requires another library Adafruit Unified sensor

  • Adafruit Unified sensor – Link
  • Adafruit BME680 Library – Link

Source code to display results without IAQ index:

Copy the below example code and paste it in the Arduino IDE workspace and hit upload button.

#include <Wire.h>
//including the BME680 sensor libraries
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
 
#define SEALEVELPRESSURE_HPA (1013.25)
 
Adafruit_BME680 bme; // I2C
 
void setup() 
{
  Serial.begin(9600);
  while (!Serial);
  Serial.println(F("BME680 test"));
 
  if (!bme.begin()) 
  {
    Serial.println("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() 
{
  if (! bme.performReading()) 
  {
    Serial.println("Failed to perform reading :(");
    return;
  }
  
  float temperature = bme.temperature;
  float pressure = bme.pressure / 100.0;
  float altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
  float humidity = bme.humidity;
  float gas = bme.gas_resistance / 1000.0;
  double dewPoint = dewPointFast(temperature, humidity);
  
  Serial.print("Temperature = ");
  Serial.print(temperature);
  Serial.println(" *C");
 
  Serial.print("Humidity = ");
  Serial.print(humidity);
  Serial.println(" %");

  Serial.print("Pressure = "); 
  Serial.print(pressure); 
  Serial.println(" hPa");
 
  Serial.print("Dew Point = ");
  Serial.print(dewPoint);
  Serial.println(" *C");
 
  Serial.print("Approx. Altitude = ");
  Serial.print(altitude);
  Serial.println(" m");
 
  Serial.print("Gas = ");
  Serial.print(gas);
  Serial.println(" KOhms");
  Serial.println();
  delay(2000);
}
 
double dewPointFast(double celsius, double humidity)
{
  double a = 17.271;
  double b = 237.7;
  double temp = (a * celsius) / (b + celsius) + log(humidity * 0.01);
  double Td = (b * temp) / (a - temp);
  return Td;
}

After uploading the code open serial monitor with baud rate 9600 to check the output as below image.

bme680 with arduino output on serial monitor

 

You can see there are temperature, humidity, Pressure, dewpoint, Approx. altitude and Gas parameters are displayed on the serial monitor but Indoor air quality index (IAQ index) values is not displayed. For that you need to install another library from BOSCH Sensortec BSEC Library and write few lines of code.

Source code to measure Air Quality Index:

About BSEC Library:

The BSEC fusion library has been conceptualized to provide a higher-level signal processing and fusion for the BME680. The library receives compensated sensor values from the sensor API. It processes the BME680 signals to provide the requested sensor outputs.

Key features

  • Precise calculation of ambient air temperature outside the device
  • Precise calculation of ambient relative humidity outside the device
  • Precise calculation of pressure outside the device
  • Precise calculation of air quality (IAQ) level outside the device

IAQ of BME680 depends 75% on gas sensor values and 25% on humidity values. The library has the mathematical equations which calculates the Air quality index.

BSEC library is supported on 8, 16, and 32 bit MCU platforms due to higher level signal processing this library doesn’t support Arduino UNO, Nano, Pro Mini, etc. but it supports on few higher level Arduino boards like Arduino MEGA 2560, Arduino Zero & Arduino Due.

Download the BSEC library through the below GitHub link and follow the steps to modify the library files according to the microprocessor board.

  • BSEC Arduino Library official GitHub page: Link

Source code to display IAQ index on serial monitor

Copy and paste the below example on Arduino IDE workspace to display all the parameters. You can customise the output by adding or removing few lines of code.

#include "bsec.h"
 
// Helper functions declarations
void checkIaqSensorStatus(void);
void errLeds(void);
 
// Create an object of the class Bsec
Bsec iaqSensor;
 
String output;
 
// Entry point for the example
void setup(void)
{
  Serial.begin(115200);
  Wire.begin();
 
  iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, 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);
}
 
// Function that is looped forever
void loop(void)
{
  unsigned long time_trigger = millis();
  if (iaqSensor.run()) { // If new data is available
    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);
  } else {
    checkIaqSensorStatus();
  }
}
 
// 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);
      for (;;)
        errLeds(); /* Halt in case of failure */
    } 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);
      for (;;)
        errLeds(); /* Halt in case of failure */
    } else {
      output = "BME680 warning code : " + String(iaqSensor.bme680Status);
      Serial.println(output);
    }
  }
}
 
void errLeds(void)
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

After Uploading the code the following parameters will be displayed every 3 seconds:

  • Timestamp in milliseconds
  • Raw Temperature in °C
  • Pressure in hPa
  • Raw Relative Humidity in %
  • Raw data from the gas sensor as a resistance value in Ohm
  • IAQ index
  • IAQ Accuracy
  • Temperature in °C
  • Relative Humidity in %
  • Static IAQ
  • CO2 equivalent
  • Breath VOC equivalent output

Indoor Air Quality Index for BME680 ranges from 0 to 500. The library calculates the index value based on the resistance and humidity from the sensor and apply smart algorithms through BSEC library. The value 0 indicates the minimum and very good Air quality, as the value increases the Air quality is decreased. You can refer the below chart image of values and their respective air quality.

Indoor air quality index chart for bme680 sensor

Applications of BME680:

  • Indoor Air Quality monitoring system
  • Internet of Things(IOT)
  • Home Automations
  • IOT based Health monitoring systems
  • Indoor navigation (change of floor detection, elevator detection)
  • Outdoor navigation, leisure and sports applications
  • Vertical velocity indication (rise/sink speed)
  • Weather forecast
  • GPS enhancement (e.g. time-to-first-fix improvement, slope detection, dead reckoning)
  • Mobile phones, tablet PCs, Wearables, Home weather stations, Smart watches, Home appliances, IOT cloud based monitoring devices

Important Notes about BME680 gas sensor:

When you first get the sensor, it is recommended to run it for 48 hours before collecting “real” gas data. To get the optimal results It is also recommend to run the sensor for 30 minutes before getting a gas reading as the sensor needs to be heated.

To get the accurate measurements you can calibrate BME680 with known sources and adding the offset in the code.

2 comments
    1. Hi timan,
      We declared the “dewPointFast” as double and that’s working fine for us. Please copy the complete code and try again. And also download the Adafruit BME680 library if you are using other.

Leave a Reply

Your email address will not be published. Required fields are marked *