Umweltsensor BME680: Misst Temperatur, Luftdruck, Luftfeuchtigkeit und die Luftqualität

Wer einen Umweltsensor sucht, der mehr kann als nur die Temperatur im Bastelzimmer anzuzeigen, landet schnell beim BME680 der Firma Bosch. Das kleine Modul misst gleich vier Werte auf einmal: Temperatur, Luftdruck, Luftfeuchtigkeit und die Luftqualität über den elektrischen Widerstand eines eingebauten Gassensors.

Schließt man das Modul an einen Arduino UNO R4 (egal ob die Variante Minima oder WiFi) an und lädt das erste Beispielprogramm hoch, tauchen im Seriellen Monitor oft solche Werte auf:

Auf den ersten Blick funktioniert alles. Doch beim zweiten Hinsehen stutzt man: Wohne ich plötzlich über 68 Meter unter dem Meeresspiegel? Und was genau sagen mir 129,65 Kiloohm beim Gaswert? In dieser Anleitung schauen wir uns genau an, was das BME680-Modul eigentlich misst, warum manche Rohwerte täuschen und wie wir sie im Programmcode so aufbereiten, dass wirklich brauchbare Daten für eigene Projekte entstehen.

Was steckt im BME680-Modul?

Der Begriff MEMS (Micro-Electro-Mechanical Systems – mikroelektromechanische Systeme) beschreibt Bauteile, die winzige mechanische und elektronische Strukturen auf einem einzigen Chip vereinen. Genau ein solches Bauteil ist der BME680. Auf einer Fläche von nur 3 mal 3 Millimetern unter der silbernen Metallkappe sitzen vier Sensoren:

  1. Temperatursensor: Misst die Umgebungstemperatur (Messbereich von -40 bis +85 Grad Celsius).
  2. Feuchtigkeitssensor: Misst die relative Luftfeuchtigkeit in Prozent (von 0 bis 100 Prozent).
  3. Barometer (Luftdrucksensor): Misst den aktuellen Luftdruck in hPa (Hektopascal, entspricht exakt einem Millibar).
  4. MOX-Gassensor (Metal Oxide – Metalloxid): Eine winzige Heizplatte im Inneren wird auf etwa 300 bis 320 Grad Celsius aufgeheizt. Dadurch reagiert die Metalloxidschicht auf VOC (Volatile Organic Compounds – flüchtige organische Verbindungen) in der Luft, wie etwa Lösungsmittel, Alkohol, Ausdünstungen von Möbeln oder verbrauchte Atemluft.

Die Anschlussbelegung am Arduino UNO R4

Die Datenübertragung läuft über den I2C-Bus (Inter-Integrated Circuit – ein weit verbreiteter Zweidraht-Datenbus für Sensoren). Dafür benötigen wir neben der Stromversorgung nur zwei Datenleitungen: SDA (Serial Data – die Datenleitung) und SCL (Serial Clock – die Taktleitung).

Am Arduino UNO R4 liegen diese beiden Anschlüsse genau wie beim klassischen UNO R3 auch am ende der digitalen GPIO´s, aber auch auf den analogen Pins A4 und A5.

BME680-PinArduino UNO R4Funktion und Bedeutung
VCC / VIN3.3V oder 5VStromversorgung (Moderne Breakout-Platinen haben einen Spannungsregler für 5 Volt an Bord)
GNDGNDMasse (Ground – gemeinsamer Minuspol)
SCL / SCKA5 oder SCLTaktleitung des I2C-Busses (Serial Clock)
SDA / SDIA4 oder SDADatenleitung des I2C-Busses (Serial Data)

Praxis-Hinweis zur I2C-Adresse: Je nach Hersteller der kleinen Trägerplatine (Breakout-Board) hört der BME680 auf die Hexadezimal-Adresse 0x77 (Standard bei Adafruit) oder 0x76 (häufig bei günstigen Modulen aus dem Online-Handel). Findet das Programm den Sensor nicht, muss im Code lediglich dieser Wert getauscht werden.

Deine Messwerte unter der Lupe: Warum -68.21 m Höhe?

Gehen wir die Werte aus deiner Messung der Reihe nach durch, um zu verstehen, woher die Abweichungen kommen:

  • Pressure = 1021.96 hPa und Approx. Altitude = -68.21 m: Der Sensor besitzt kein eingebautes GPS (Global Positioning System – weltweites Positionsbestimmungssystem). Er berechnet die Höhe rein rechnerisch über den Luftdruck: Je höher man steigt, desto dünner wird die Luft und desto geringer ist der Druck. Als Vergleichswert ist in den Standard-Beispielprogrammen ein fester Wert von 1013.25 hPa für den Druck auf Meereshöhe hinterlegt. Herrscht an deinem Wohnort gerade schönes Hochdruckwetter mit 1021.45 hPa, ist der Luftdruck höher als dieser Standardwert. Die Formel im Arduino rechnet stur rückwärts und glaubt deshalb, du befindest dich 72,27 Meter unter dem Meeresspiegel.
  • Temperature = 25.01 °C und Humidity = 51.07 %: Um Gase zu messen, schaltet der BME680 bei jeder Messung seine interne Heizplatte ein. Diese Wärme strahlt im gesamten Gehäuse ab. Dadurch zeigt der Temperatursensor oft 1,5 bis 3,0 Grad Celsius zu viel an. Da warme Luft mehr Feuchtigkeit aufnehmen kann als kalte, sinkt durch diese Eigenerwärmung gleichzeitig der angezeigte Wert der relativen Luftfeuchtigkeit leicht ab.
  • Gas = 129.65 KOhms: Der Sensor gibt für die Luftqualität keinen fertigen Prozentwert aus, sondern einen elektrischen Widerstand in kOhm (Kiloohm, also 1.000 Ohm). Die goldene Faustregel lautet hier: Je höher der Widerstandswert, desto sauberer ist die Luft. Bei frischer Raumluft steigt der Wert deutlich über 100 kOhm (meine 129,65 kOhm zeigen also gute Luftqualität). Hältst du kurz einen geöffneten Edding-Stift oder etwas Reinigungsalkohol in die Nähe des Sensors, bricht der Widerstand sofort auf Werte unter 35 kOhm ein und brauch dann wieder über 10 Minuten um sich zu beruhigen.
Gas-Widerstand (kOhm)Einschätzung der RaumluftEmpfohlene Aktion im Projekt
Größer als 100 kOhmSehr gute, frische RaumluftGrüne Status-Anzeige (Alles im grünen Bereich)
50 bis 100 kOhmNormale Raumluft (leicht verbraucht)Gelbe Status-Anzeige (Demnächst lüften)
Kleiner als 50 kOhmSchlechte Luft / hohe Belastung durch GaseRote Warn-Anzeige oder Lüfter einschalten

Wichtiger Hinweis (Nicht nachweisbares Wissen): Die Firma Bosch bietet für den BME680 eine zusätzliche Software-Bibliothek namens BSEC (Bosch Software Environmental Cluster) an, die aus dem Widerstandswert einen genauen Luftqualitäts-Index namens IAQ (Indoor Air Quality – Raumluftqualität) von 0 bis 500 berechnet. Die genaue mathematische Formel und die internen Gewichtungen dieser Software sind jedoch ein geschütztes Betriebsgeheimnis des Herstellers (Closed Source) und lassen sich im Quellcode nicht unabhängig nachprüfen. Deshalb berechnen wir im folgenden Programm unsere Auswertung komplett transparent selbst!

Mein Praxis-Tipp:
Wenn du auf dem Steckbrett (Breadboard) experimentierst, den Sensor immer nur stundenweise einschaltest oder deinen eigenen Schwellenwert für eine Lüftungsampel im Code selbst bestimmen willst, bleib bei unserer offenen Berechnung aus diesem Beitrag.
Möchtest du den Arduino UNO R4 hingegen fest an der Wand montieren und rund um die Uhr als Wetterstation durchlaufen lassen, lohnt sich ein Blick auf die BSEC2-Bibliothek – denn sie passt sich über mehrere Tage hinweg automatisch an die sauberste Luft in deinem Zimmer an.

Schritt-für-Schritt: Brauchbare Werte im Code übernehmen

Damit du die Werte in deinen eigenen Projekten (zum Beispiel für ein Display, ein Webradio-Zusatzmodul oder eine Lüftersteuerung) sauber weiterverarbeiten kannst, müssen wir vier Dinge im Code anpassen:

  1. Tagesaktuellen Luftdruck eintragen: Schau in einer Wetter-App nach dem aktuellen Luftdruck auf Meereshöhe (in der Wetterkunde QNH genannt) für deinen Standort. Alternativ trägst du deine echte Wohnort-Höhe ein und passt den Druckwert im Code so lange an, bis die Höhe stimmt.
  2. Temperatur-Offset (Korrekturwert) abziehen: Wir ziehen die Eigenerwärmung des Moduls ab und korrigieren über die sogenannte Magnus-Formel (eine physikalische Standardformel für den Sättigungsdampfdruck) auch gleich die Luftfeuchtigkeit.
  3. Aufwärmphase beachten: Der Gassensor braucht nach dem Einschalten etwa 5 bis 20 Minuten, bis sich der Widerstandswert stabilisiert hat.
  4. Blockierungsfreier Code mit millis(): Statt den Mikrocontroller mit delay() komplett anzuhalten, nutzen wir einen Zeitstempel. So bleibt der Arduino UNO R4 jederzeit frei für Tastereingaben oder Display-Ausgaben.

Das fertige Arduino-Programm für die Praxis

Installiere vorab im Bibliotheksverwalter der IDE (Integrated Development Environment – Entwicklungsumgebung) die Bibliothek Adafruit BME680 Library (inklusive der benötigten Zusatzbibliothek Adafruit Unified Sensor).

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"

// =========================================================================
// EINSTELLUNGEN FÜR DEINEN STANDORT UND SENSOR-KORREKTUR
// =========================================================================

// 1. Luftdruck auf Meereshöhe (in hPa) für deinen Standort.
// Bei deinem Messwert von 1021.96 hPa und z.B. 65m echter Höhe in Frechen
// liegt der lokale Druck auf Meereshöhe aktuell bei ca. 1029.80 hPa.
const float LUFTDRUCK_MEERESSPIEGEL_HPA = 1029.80; 

// 2. Korrektur der Eigenerwärmung durch die Heizplatte im BME680 (in °C).
// Meist liegt der Wert zwischen -1.5 und -2.5 Grad. Am besten mit einem
// zweiten Thermometer im Raum vergleichen!
const float TEMPERATUR_KORREKTUR = -2.0;

// 3. Referenzwert für gute Raumluft in kOhm (Basiswert im frisch gelüfteten Raum)
const float GAS_REFERENZ_KOHM = 130.0;

// Messintervall in Millisekunden (3000 ms = alle 3 Sekunden)
const unsigned long MESS_INTERVALL_MS = 3000;
unsigned long letzteMessungMs = 0;

// Sensor-Objekt für I2C (Pins A4 = SDA, A5 = SCL am Arduino UNO R4)
Adafruit_BME680 bme;

// Datenstruktur für unsere fertig bereinigten, brauchbaren Messwerte
struct SensorDaten {
  float temperatur;       // Korrigierte Temperatur in °C
  float luftfeuchtigkeit; // Korrigierte relative Feuchte in %
  float luftdruck;        // Gemessener Luftdruck in hPa
  float hoehe;            // Berechnete Höhe über dem Meeresspiegel in m
  float gasWiderstand;    // Elektrischer Widerstand des Gassensors in kOhm
  float luftqualitaet;    // Eigener Luft-Score von 0 % (schlecht) bis 100 % (top)
  bool  datenGueltig;     // Prüfflag, ob die Messung erfolgreich war
};

SensorDaten aktuelleWerte;

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ; // Warten bis die serielle Schnittstelle bereit ist
  }

  Serial.println(F("--- Prilchen LABS: BME680 Praxis-Auswertung ---"));

  // Sensor starten: Erst Standard-Adresse 0x77 testen, sonst 0x76
  if (!bme.begin(0x77)) {
    if (!bme.begin(0x76)) {
      Serial.println(F("FEHLER: BME680 nicht gefunden! Bitte Verkabelung an A4/A5 prüfen."));
      while (1);
    }
  }

  // Übersetzung (Oversampling) und Filter für ruhige, stabile Messwerte einstellen
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  
  // Heizplatte auf 320 Grad Celsius für 150 Millisekunden pro Messung einstellen
  bme.setGasHeater(320, 150); 
  
  Serial.println(F("Sensor erfolgreich initialisiert. Messung startet...\n"));
}

// Funktion liest den Sensor aus, korrigiert die Rohwerte und speichert sie
bool leseUndKorrigiereBME680(SensorDaten &daten) {
  if (!bme.performReading()) {
    daten.datenGueltig = false;
    return false;
  }

  // 1. Rohwerte vom Sensor abholen
  float rohTemp = bme.temperature;
  float rohFeuchte = bme.humidity;

  // 2. Temperatur um die Eigenerwärmung korrigieren
  daten.temperatur = rohTemp + TEMPERATUR_KORREKTUR;

  // 3. Luftfeuchtigkeit physikalisch an die korrigierte Temperatur anpassen (Magnus-Formel)
  float dampfdruckRoh = 6.112 * exp((17.62 * rohTemp) / (243.12 + rohTemp));
  float dampfdruckKorrigiert = 6.112 * exp((17.62 * daten.temperatur) / (243.12 + daten.temperatur));
  daten.luftfeuchtigkeit = rohFeuchte * (dampfdruckRoh / dampfdruckKorrigiert);
  
  // Begrenzung auf maximal 100 Prozent und minimal 0 Prozent
  if (daten.luftfeuchtigkeit > 100.0) daten.luftfeuchtigkeit = 100.0;
  if (daten.luftfeuchtigkeit < 0.0)   daten.luftfeuchtigkeit = 0.0;

  // 4. Luftdruck von Pascal (Pa) in Hektopascal (hPa) umrechnen
  daten.luftdruck = bme.pressure / 100.0;

  // 5. Realistische Höhe mit dem aktuellen Referenzdruck berechnen
  daten.hoehe = bme.readAltitude(LUFTDRUCK_MEERESSPIEGEL_HPA);

  // 6. Gaswiderstand von Ohm in Kiloohm (kOhm) umrechnen
  daten.gasWiderstand = bme.gas_resistance / 1000.0;

  // 7. Eigenen Luftqualitäts-Wert in Prozent (0 bis 100 %) berechnen:
  //    75 % Gewichtung auf den Gaswiderstand, 25 % auf optimale Luftfeuchte (um 40-50 %)
  float gasAnteil = (daten.gasWiderstand / GAS_REFERENZ_KOHM) * 75.0;
  if (gasAnteil > 75.0) gasAnteil = 75.0;

  float feuchteAbweichung = abs(daten.luftfeuchtigkeit - 45.0);
  float feuchteAnteil = 25.0 - (feuchteAbweichung * 0.5);
  if (feuchteAnteil < 0.0) feuchteAnteil = 0.0;

  daten.luftqualitaet = gasAnteil + feuchteAnteil;
  daten.datenGueltig = true;
  return true;
}

void loop() {
  unsigned long aktuelleZeitMs = millis();

  // Nicht-blockierende Abfrage über millis()
  if (aktuelleZeitMs - letzteMessungMs >= MESS_INTERVALL_MS) {
    letzteMessungMs = aktuelleZeitMs;

    if (leseUndKorrigiereBME680(aktuelleWerte)) {
      Serial.println(F("================ MESSWERTE ================"));
      Serial.print(F("Temperatur (korrigiert): "));
      Serial.print(aktuelleWerte.temperatur, 2);
      Serial.println(F(" °C"));

      Serial.print(F("Luftfeuchtigkeit:        "));
      Serial.print(aktuelleWerte.luftfeuchtigkeit, 2);
      Serial.println(F(" %"));

      Serial.print(F("Luftdruck:               "));
      Serial.print(aktuelleWerte.luftdruck, 2);
      Serial.println(F(" hPa"));

      Serial.print(F("Berechnete Höhe:         "));
      Serial.print(aktuelleWerte.hoehe, 1);
      Serial.println(F(" m"));

      Serial.print(F("Gas-Widerstand:          "));
      Serial.print(aktuelleWerte.gasWiderstand, 2);
      Serial.println(F(" kOhm"));

      Serial.print(F("Raumluft-Qualität:       "));
      Serial.print(aktuelleWerte.luftqualitaet, 0);
      Serial.println(F(" % (100% = Ideal)"));
      Serial.println(F("===========================================\n"));
      
      // HIER kannst du nun direkt mit den Variablen weiterarbeiten!
      // Beispiel: Lüfter oder Warn-LED schalten, wenn die Luftqualität unter 50 % fällt:
      if (aktuelleWerte.luftqualitaet < 50.0) {
        Serial.println(F("-> HINWEIS: Bitte mal wieder das Fenster öffnen!"));
      }
    } else {
      Serial.println(F("Messung fehlgeschlagen!"));
    }
  }
}

Fazit für den Basteltisch

Der BME680 ist ein extrem vielseitiger Sensor, wenn man weiß, wie man seine Eigenheiten im Programmcode abfängt.
Durch die kleine Korrektur der Eigenerwärmung, die Anpassung der Luftfeuchtigkeit und den passenden Referenzdruck verschwinden seltsame Werte wie -72 Meter Höhe sofort.
Da alle bereinigten Daten im obigen Sketch sauber im Datenpaket aktuelleWerte (zum Beispiel unter aktuelleWerte.temperatur oder aktuelleWerte.luftqualitaet) landen, kannst du sie direkt an ein Display schicken oder per WLAN (Wireless Local Area Network – drahtloses lokales Netzwerk) auf einem ESP32 oder Arduino UNO R4 WiFi weiterverarbeiten.

, ,
Datenschutz-Übersicht

Diese Website verwendet Cookies, damit wir dir die bestmögliche Benutzerkomfort bieten können. Cookie-Informationen werden in deinem Browser gespeichert und führen Funktionen aus, wie das Wiedererkennen von dir, wenn du auf unsere Website zurückkehrst und hilft uns zu verstehen, welche Abschnitte der Website für dich am interessantesten und nützlichsten sind.