Arduino Lektion #113: Umweltsensor BME680

In diesem Beitrag möchte ich dir den Umweltsensor BME680 vorstellen. Mit diesem Umweltsensor kannst du die relative Luftfeuchtigkeit, den Luftdruck sowie die Luftqualität messen.

Sensor BME680 für rel. Luftfeuchtigkeit, Temperatur, Luftdruck und Luftqualität
Sensor BME680 für rel. Luftfeuchtigkeit, Temperatur, Luftdruck und Luftqualität

Bezug

Den Sensor BME680 habe ich im Online Shop von Watterott für 13,65€ zzgl. Versandkosten bestellt.
Du findest diesen Sensor aber auch auf ebay.de zu einem ähnlichen Preis.

Lieferumfang

Zum Lieferumfang des Sensors gehört neben der Platine eine 8fach Stiftleiste im Rastermaß 2,54 mm.

Technische Daten des Umweltsensors BME680

  • Betriebsspannung 3,3V … 5V
  • I2C Adresse
    • 0x76 wenn SDO auf 0 gesetzt ist, oder
    • 0x77 wenn SDO auf 1 gesetzt ist

rel. Luftfeuchtigkeitssensor

  • Antwortzeit (t63%) 8 Sekunden
  • Toleranz ± 3%
  • Hysteresis 1,5% rel. Luftfeuchtigkeit

Luftdrucksensor

  • Messbereich 300…1100 hPa
  • rel. Toleranz ± 0.12 hPa (950…1050hPa bei 25°C)
  • absolute Toleranz ± 1 hPa (bei 0… +40°C)

Temperatursensor

  • Messbereich -40°C … +85°C
  • volle Genauigkeit 0°C … +65°C

Luftqualitätssensor

  • Antwortzeit (t33-63%) 1 Sekunde
  • „Indoor Air Quality (IAQ) Index“

Anschluss vom Umweltsensor BME680 an den Arduino

Den Sensor BME680 kann man entweder auf ein Breadboard stecken und mit Breadboardkabel an den Arduino anschließen oder aber direkt mit dem Breadboardkabel. Jedoch bevorzuge ich den Anschluss über ein Breadboard, denn dann „fliegt“ die Platine nicht auf dem Schreibtisch umher.

Platine BME680 auf einem 170 Pin Breadboard
Platine BME680 auf einem 170 Pin Breadboard

Auf dem Sensor sind folgende Pins angeschlossen, welche mit dem Arduino UNO R3 wie folgt verbunden werden:

SensorArduino UNO R3
GNDGND
NC 
VCC3,3V
SCL / SCKanaloger Pin A5
SDA / SDIanaloger Pin A4
SDO 
CS 

In diesem Beitrag möchte ich den Sensor über I2C betreiben d.h. ich werde die beiden Pins SCL & SDA verwenden.

Sensor BME680 am Arduino UNO R3
Sensor BME680 am Arduino UNO R3

Programmieren

Zum Programmieren des Sensors über I2C benötigst du neben einer zusätzlichen Bibliothek auch die Adresse des Sensors. Diese I2C Adresse kannst du zbsp. mit dem I2C Scanner Sketch abfragen. Du findest dieses sehr nützliche Programm unter https://playground.arduino.cc/Main/I2cScanner/.

ermittelte Adresse 0x77 des Sensors BME680 mit dem I2C Scanner
ermittelte Adresse 0x77 des Sensors BME680 mit dem I2C Scanner

Bibliothek zum betreiben des Sensors in der Arduino IDE

Für das auslesen der Werte des Sensors verwende ich die Bibliothek von Adafruit welche recht einfach über den Bibliotheksverwalter installiert werden kann.

Dazu musst du zuerst nach dem Begriff „bme680“ (1) suchen, und dann wählst du die Schaltfläche „Installieren“ im Eintrag „Adafruit BME680 Library“ aus. Nachdem diese aus dem Internet geladen und installiert wurde, kannst du dieses Fenster über die Schaltfläche „Schließen“ (3) verlassen.

installieren der Adafruit Bibliothek für den Sensor BME680
installieren der Adafruit Bibliothek für den Sensor BME680

Dieser Bibliothek liegen 3 Beispiele bei welche sofort lauffähig sind. Das Beispiel mit der Bezeichnung „bme680test“ liefert auf der seriellen Schnittstelle folgende Ausgabe:

Ausgabe des Beispieles "bme680test" auf der seriellen Schnittstelle der Arduino IDE
Ausgabe des Beispieles „bme680test“ auf der seriellen Schnittstelle der Arduino IDE

Ausgeben der Daten vom Umweltsensor BME680 auf einem Display

In dem Beispiel aus der Adafruit Bibliothek zum Sensor BME680 werden die Daten bereits auf der seriellen Schnittstelle ausgegeben, einzig soll nun die Luftqualität welche in kOhm angezeigt werden in einem anderen Format auf einem 0,96″ OLED Display angezeigt werden.

Schaltung - Sensor BME680 & OLED Display am Arduino UNO
Schaltung – Sensor BME680 & OLED Display am Arduino UNO

Aufbau der Schaltung

Das Pinout des Sensors habe ich bereits gezeigt, in diesem Abschnitt kommt lediglich ein zusätzliches 0,91″ OLED Display hinzu, welches ebenfalls über I2C angeschlossen wird.

Dieses 0,91″ OLED Display habe ich im Beitrag Arduino Lektion 76: 0,91 Zoll OLED Display ausführlich vorgestellt.

Aufbau der Schaltung - Sensor BME680 mit OLED Display am Arduino UNO
Aufbau der Schaltung – Sensor BME680 mit OLED Display am Arduino UNO

einrichten der zusätzlichen Bibliothek für das OLED Display

Für das OLED Display benötigen wir zusätzlich eine Bibliothek, welche ebenfalls von Adafruit kommt und über den Bibliotheksverwalter installiert wird.

0,91 Zoll OLED Display
0,91 Zoll OLED Display

Im Bibliotheksverwalter der Arduino IDE suchen wir nach dem Begriff „adafruit ssd1306“ (1) und wählen der Liste den Eintrag „Adafruit SSD1306“ (2) aus, nachdem die Installation abgeschlossen ist kann der Dialog über die Schaltfläche „Schließen“ geschlossen werden.

Installieren der Adafruit SSD1306 Bibliothek
Installieren der Adafruit SSD1306 Bibliothek

Quellcode zum Programmieren vom Umweltsensor BME680

Für die Berechnung der Luftqualität habe ich auf dem GitHub Repository G6EJD / BME680-Example ein Beispiel gefunden, welches diesen recht zuverlässig berechnet und als Text ausgibt.

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.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

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

float hum_score, gas_score;
float gas_reference = 250000;
float hum_reference = 40;
int   getgasreference_count = 0;

void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  delay(1000);
  display.clearDisplay();

  if (!bme.begin()) {
    Serial.println("Der Sensor BME680 konnte nicht gefunden werden!");
    while (1);
  }

  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;
  }

  delay(1000);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);

  String temp = "Temp.: ";
  temp += String(bme.temperature, 2);
  temp += "C";

  display.println(temp);

  display.setCursor(0, 8);
  String hum = "Hum.: ";
  hum += String(bme.humidity, 2);
  hum += "%";
  display.println(hum);

  String gas = "Gas: ";
  gas += String(bme.gas_resistance / 1000.0, 2);
  gas += " KOhms";
  display.setCursor(0, 16);
  display.println(gas);

  String airQuality = getAirQuality();
  display.setCursor(0, 24);
  display.println(airQuality);

  display.display();
  display.clearDisplay();
}

String getAirQuality() {
  float current_humidity = bme.readHumidity();
  if (current_humidity >= 38 && current_humidity <= 42)
    hum_score = 0.25*100; // Humidity +/-5% around optimum 
  else
  { //sub-optimal
    if (current_humidity < 38) 
      hum_score = 0.25/hum_reference*current_humidity*100;
    else
    {
      hum_score = ((-0.25/(100-hum_reference)*current_humidity)+0.416666)*100;
    }
  }
  
  //Calculate gas contribution to IAQ index
  float gas_lower_limit = 5000;   // Bad air quality limit
  float gas_upper_limit = 50000;  // Good air quality limit 
  if (gas_reference > gas_upper_limit) gas_reference = gas_upper_limit; 
  if (gas_reference < gas_lower_limit) gas_reference = gas_lower_limit;
  gas_score = (0.75/(gas_upper_limit-gas_lower_limit)*gas_reference -(gas_lower_limit*(0.75/(gas_upper_limit-gas_lower_limit))))*100;
  float air_quality_score = hum_score + gas_score;
  if ((getgasreference_count++)%10==0) GetGasReference(); 
return CalculateIAQ(air_quality_score);
}

void GetGasReference(){
  int readings = 10;
  for (int i = 1; i <= readings; i++){
    gas_reference += bme.readGas();
  }
  gas_reference = gas_reference / readings;
}

String CalculateIAQ(float score) {
  String IAQ_text = "Air quality is ";
  score = (100 - score) * 5;
  if      (score >= 301)                  IAQ_text += "Hazardous";
  else if (score >= 201 && score <= 300 ) IAQ_text += "Very Unhealthy";
  else if (score >= 176 && score <= 200 ) IAQ_text += "Unhealthy";
  else if (score >= 151 && score <= 175 ) IAQ_text += "Unhealthy for Sensitive Groups";
  else if (score >=  51 && score <= 150 ) IAQ_text += "Moderate";
  else if (score >=  00 && score <=  50 ) IAQ_text += "Good";
  return IAQ_text;
}

Vergleich der Sensordaten vom BME680 mit einem Aranet4

Wenn man die Sensordaten vom BME680 mit einem Aranet4 vergleicht, sieht man das die Werte für die Temperatur, rel. Luftfeuchtigkeit relativ dicht beieinander liegen. Einzig die Luftqualität ist deutlich anders, denn der Aranet4 misst deutlich genauer und liefert den Wert in „ppm“. Der BME680 jedoch misst den Wert in IAQ und diesen Wert müsste man zunächst umrechnen.

Wenn du einen zuverlässigen Wert für die Luftqualität benötigst so empfehle ich dir die Bibliothek von Bosch welche du auf dem GitHub Repository https://github.com/BoschSensortec/BME680_driver findest.

Vergleich der Sensordaten von einem BME680 und einen Aranet4
Vergleich der Sensordaten von einem BME680 und einen Aranet4

4 Kommentare

  1. Hallo 🙂
    Ich habe heute einfach dieses Projekt mit dem LCD nachgebaut und deinen Code kopiert. Wieso gibst du Gas in kOhm aus statt bspw. den Luftdruck auszugeben?
    Was müsste man dann im Code genau ändern?
    Ich bin absoluter Anfänger und versuche das nachzuvollziehen.
    Viele Grüße!

    1. Hallo Felix,

      vielen Dank für deinen Kommentar.
      Die Ausgabe des Wertes für GAS ist in „kOhm“ (KiloOhm) da der Sensor für einen Aussagekräftigen Wert für ein Gasgemisch zu ungenau ist.
      Man müsste diesen zuvor immer justieren / kalibrieren, wie es die teuren Sensoren machen.

      Gruß

      Stefan

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert