Barometrischer Sensor BMP180

BMP180 und BMP280 Luftdrucksensoren

Viele kennen sicher die »Wetterstationen«, die bei Eltern oder Großeltern an der Wohnzimmerwand hingen oder noch hängen: Barometer, Hygrometer und Thermometer als analoge Instrumente zum Messen von Luftdruck, relativer Luftfeuchtigkeit und Temperatur. Das alles ist inzwischen in kleinen Sensoren realisiert, von denen einige zum Messen von Temperatur und Luftfeuchtigkeit hier schon vorgestellt wurden – es fehlt noch ein barometrischer Sensor wie der Bosch BMP180, um die digitale Version so einer Wetterstation mit einem Mikrocontroller aufzubauen. Er und sein Nachfolger BMP280 messen zusätzlich zum Luftdruck auch die Temperatur und bieten über die Bibliotheken Funktionen, um z.B. den gemessenen Luftdruck in den Druck auf Höhe des Meeresspiegels umzurechnen.

Gegenüber der ersten Version des Beitrags vom 16.12.2020 habe ich im Januar 2021 Bilder und Text zum Kombisensor mit dem BMP280 (und AHT20) und der zugehörigen Programmbibliothek ergänzt, im Mai 2021 Bilder zum BMP280.

Luftdruck und Höhe über dem Meeresspiegel

Vereinfacht entspricht der Luftdruck der Gewichtskraft der Luftsäule, die auf die Erdoberfläche oder einen Gegenstand drückt.[1]Eine exakte Definition liefert Wikipedia: Luftdruck. Die Maßeinheit für den Luftdruck ist das Pascal (Pa) bzw. gebräuchlicher das Hektopascal (hPa; 100 Pa = 1 hPa); auch Bar bzw. Millibar werden verwendet (1 bar= 1000 mbar = 1000 hPa). Auf Meereshöhe beträgt der mittlere Luftdruck normgemäß 1013,25 hPa = 101.325 Pa = 1013,25 mbar, also ungefähr 1 bar.

Mit steigender Höhe nimmt der Luftdruck ab. Auf Meereshöhe ist das eine Änderung von ca. 1 hPa pro 8,4 Meter. Das machen sich barometrische Höhenmesser zunutze: bei stabiler Wetterlage bedeutet eine Zu- oder Abnahme des Luftdrucks um 1 Prozent, dass sich die Höhe um rund 84 Meter geändert hat. Andersherum bewirkt eine Höhenänderung von 10 Metern eine Änderung des Luftdrucks um ca. 1,2 hPa (auf Meereshöhe).

Für den Zusammenhang zwischen Höhe und Luftdruck gibt es Formeln, die dem Datenblatt zum BMP180 entnommen sind und so auch in der Programmbibliothek zum Sensor verwendet werden.[2]Datenblatt zum BMP180 als PDF; S. 16 und 17
Quellcode der Programmbibliothek bei GitHub; Methoden Adafruit_BMP085_Unified::pressureToAltitude() und Adafruit_BMP085_Unified::seaLevelForAltitude()

Kennt man für seinen Standort den Druck auf Meereshöhe p0 (z.B. aus den Daten eines Wetterdienstes; s.u.) und misst einen Luftdruck p, errechnet sich die lokale Höhe h als

Formel zur Berechnung der Höhe
Formel zur Berechnung der Höhe

Die berechnete Höhe sollte man nur als Schätzwert verstehen. Die Rechnung liefert auch nur eine kurze Zeit gute Werte, da der Luftdruck an einem Ort meist nicht allzu lange konstant bleibt und man ja auch nicht für jeden Ort die Daten einer Wetterstation in der Nähe findet. Die BMP-Sensoren messen aber so genau, dass sich auch kleine Höhenänderungen bemerkbar machen: Stellt man eine mit dem Sensor aufgebaute Schaltung auf den Boden und vergleicht den dort gemessenen Luftdruck mit dem etwa zwei Meter höher, indem man das Breadboard mit ausgestrecktem Arm nach oben hält, sollte man – je nach Länge der Arme oder des USB-(Verlängerungs-)Kabels – eine Druck-Änderung um 2-3 Zehntel hPa festellen können. Auch die berechnete Höhe über dem Meeresspiegel sollte sich entsprechend ändern.[3]Vermutlich wird kaum jemand seinen ESP32 samt Powerbank auf eine Bergwanderung mitnehmen, um eine barometrische Höhenmessung durchzuführen. Denkbar ist aber sicherlich, die Flughöhe einer Drohne … Continue reading

Kennt man die Höhe über dem Meeresspiegel h seines Standorts, kann man aus dem gemessenen Luftdruck p den Luftdruck auf Meereshöhe p0 berechnen:

Formel zur Berechnung des Drucks auf Meereshöhe
Formel zur Berechnung des Drucks auf Meereshöhe

Für eine Wetterstation zuhause, deren Höhe vermutlich konstant ist, ist das wohl der interessantere Wert, denn man kann so seine eigenen Messungen mit denen anderer Stationen (von Wetterdiensten) vergleichen. Die nennen alle den auf Meereshöhe umgerechneten Luftdruck – manchmal wird er dort mit dem Kürzel »QFF« bezeichnet.[4]Siehe Wikipedia: Barometrische Höhenmessung in der Luftfahrt

Woher erhält man nun aktuelle Werte für den Luftdruck? Und welche Höhe über dem Meeresspiegel hat mein Wohnort?

Quellen für Luftdruck-Daten

Um für seinen Wohnort (oder einen Ort in der Nähe) aktuelle Wetterdaten – u.a. den Luftdruck auf Meereshöhe – zu bekommen, kann man auf die Seiten verschiedener Wetterdienste zugreifen, z.B.:

  • Deutscher Wetterdienst (DWD): halbstündlich aktualisierte Wetterdaten für über 70 Orte in Deutschland
  • Kachelmannwetter: Karte mit den Luftdruck-Werten vieler Messstationen; hineinzoomen oder Anzeige einzelner Bundesländer ist möglich; Anklicken eines Wertes liefert genaue Angaben zur jeweiligen Station; neben dem Luftdruck kann man sich auch andere Angaben anzeigen lassen

Mglw. bietet auch die eigene Stadt oder der Landkreis entsprechende Daten an. Z.B. betreibt mein Wohnort Hamburg ein Luftmessnetz und zeigt auf der Homepage der Stadt u.a. Luftdruck-Daten von zwei Messstationen an.

Quelle für Höhenangaben

Der Dienst topographic-map.com bietet für Mitteleuropa eine topographische Karte an, in die man sehr weit hineinzoomen kann – auch in kleinen Gemeinden bis auf Straßenebene. Durch Anklicken eines Punktes auf der Karte wird die Höhe des Ortes über dem Meeresspiegel angezeigt – wesentlich genauer, als wenn man z.B. die Höhenangabe aus Wikipedia nimmt, die ja nur einen zentralen Punkt des jeweiligen Ortes betrifft.

BMP180 und BMP280 Luftdrucksensoren: Technische Daten

  BMP180 BMP280
Luftdruck: 300 – 1100 hPa 300 – 1100 hPa
   rel. Genauigkeit: ±0,12 hPa ±0,12 hPa
   Auflösung: 0,01 hPa 0,0016 hPa
Temperatur: -40 bis +85°C -40 bis +85°C
   Genauigkeit: ±0,5 °C (bei 25°C) ±0,5 °C (bei 25°C)
   Auflösung: 0,1 °C 0,01 °C
Versorgungsspannung: 1,8 bis 3,6 V 1,71 bis 3,6 V
Schnittstelle: I2C I2C, SPI
I2C-Adresse: 0x77 0x77 (alternativ 0x78)
Größe des Sensors: 3,6 mm * 3,8 mm 2 mm * 2,5 mm
Größe der Modul-Platine: ca. 10 mm * 13 mm (4 Pins) ca. 15 mm * 12 mm (6 Pins)[5]Es gibt auch BMP280-Module, die nur die I2C-Schnittstelle unterstützen. Diese haben 4 Pins und sind so groß wie die BMP180-Module.

Datenblätter

Der BME280 ähnelt dem BMP280 und misst zusätzlich die relative Luftfeuchtigkeit (Bereich 0 … 100% mit einer Genauigkeit von ±3%) – er vereint alle Funktionen einer Wetterstation für die eigenen vier Wände auf gut 6 Quadratmillimetern Fläche. Technische Daten nennt die Produktseite des Herstellers Bosch Sensortec, auf der das Datenblatt verlinkt ist.

Sensormodule

BMP180-Modul mit nicht eingelöteten Pins
BMP180-Modul mit nicht eingelöteten Pins

BMP180 und BMP280 sind für den Einsatz mit Mikrocontrollern ausschließlich als Modul (manchmal als Shield bzeichnet) erhältlich – der Sensor ist dabei auf eine kleine Platine gelötet, auf der sich u.a. auch Pull-Up-Widerstände für die I2C-Kommunikation befinden. Bei den mir bekannten BMP180-Modulen (blaue Platinenfarbe) ist auch ein Spannungsregler vorhanden, sodass sie mit 3,3 und 5 Volt (also mit ESP32/ESP8266 und den Arduinos) arbeiten, ohne dass man darauf achten muss, welche Spannung man verwendet. Die meisten BMP280-Module (Platinenfarbe violett) sind für 3,3 Volt ausgelegt, es gibt aber auch welche mit Spannungsregler für 5 Volt.

BMP180-Modul: Pin-Beschriftung auf der Unterseite
BMP180-Modul: Unterseite

Die Stiftleisten sind nicht eingelötet, sondern werden lose mitgeliefert – ich habe bisher keinen Online-Händler gefunden, der fertig gelötete Module anbietet. Hier muss man also selbst zum Lötkolben greifen.

Die BMP180- und BMP280-Module sind meist zu Preisen ab ca. 4  € erhältlich (bei Direktbestellung in China deutlich unter 1 €). Module mit dem BME280 sind etwas teurer. Die BMP180-Module findet man oft auch unter dem Namen »GY-68«.

Den BMP280 gibt es auch als Kombi-Modul zusammen mit dem Sensor AHT20 zur Temperatur- und Luftfeuchtigkeitsmessung – wie beim BME280 hat man hier eine komplette Wetterstation auf einer Platine. Das Modul hat allerdings keine Pinleiste, sondern einen Grove-Anschluss (zur Pinbelegung siehe den Hinweis weiter unten).[6]Das Grove-System nutzt einen vierpoligen Anschluss – Spannung, Masse und zwei Datenleitungen –, um ein einfach zu verwendendes Stecksystem zur Verbindung von Mikrocontrollern und Sensoren … Continue reading Man benötigt zusätzlich ein passendes Grove-Kabel (und einen Mikrocontroller mit Grove-Anschluss – entsprechende Shields gibt es u.a. für verschiedene Arduino-Modelle) oder ein Adapterkabel, um das Modul auf dem Breadboard nutzen zu können.

Mit Abmessungen von ca. 16 * 16 mm ist die Platine nur wenig größer als die Module mit dem BMP180 oder BMP280. Lt. Angaben der Anbieter[7]Ich habe das Modul in China über Aliexpress gekauft (Produktsuche). Die Preise lagen im Januar 2021 bei knapp 2 € zzgl. Versandkosten. ist das Modul ausgelegt für Spannungen zwischen 2,0 und 5 Volt.
(Leider scheint bei dem Modul, das ich besitze, beim AHT20 die Messung der rel. Luftfeuchtigkeit nicht zu funktionieren. Deshalb verzichte ich vorerst darauf, den AHT20 und dieses Modul in einem eigenen Beitrag zu behandeln.)

I2C-Schnittstelle

BMP180-Modul: Anschlüsse und Bauteile
BMP180-Modul: Anschlüsse und Bauteile

Das BMP180-Modul hat vier Anschlüsse, die auf der Unterseite beschriftet sind. In der Draufsicht sind das von links nach rechts (bei den BMP280-Modulen mit vier Pins sollte es genauso aussehen):

  1. SDA (Daten)
  2. SCL (Takt)
  3. GND (Masse)
  4. VIN (Versorgungsspannung)

Außerdem sind auf dem Bild folgende Bauteile zu erkennen:

  • (A) zwei Pull-Up-Widerstände für SDA und SCL; jeweils 10 KΩ (Beschriftung »103«)
  • (B) Spannungsregler von 5 auf 3,3 Volt (Beschriftung »662K«)
  • (C) der eigentliche BMP180-Sensor
Rückseite des Kombisensors mit Beschriftung der I2C-Anschlüsse
Rückseite des Kombisensors mit Beschriftung der I2C-Anschlüsse

Auch das Kombi-Modul nutzt über den Grove-Anschluss die I2C-Schnittstelle, wie man an der Beschriftung auf der Rückseite der Platine erkennt.

Die Anordnung der Pins scheint allerdings nicht dem Grove-Standard »SCL – SDA – Spannung (VCC) – Masse (GND)« zu entsprechen. Mangels entsprechender Hardware kann ich das aber nicht prüfen – ich schließe den Sensor mit einem Adapterkabel auf dem Breadboard an. Wer Hardware mit dem Grove-System nutzt, sollte jedenfalls vor dem Anschließen des Sensors die korrekte Zuordnung der Pins prüfen. Evtl. muss man sich auch für diesen Fall ein Adapterkabel beschaffen oder basteln.

Bibliotheken

Die Bibliotheken zur Programmierung der Sensoren können einfach über die Bibliotheksverwaltung der Arduino-IDE installiert werden (Suchbegriffe z.B. »bmp180« und »adafruit unified sensor«); eine ausführliche Anleitung zur Installation von Bibliotheken in der Arduino-IDE gibt der Beitrag »Arduino-IDE: Bibliotheken verwalten«.

BMP180

Adafruit stellt die Bibliothek Adafruit BMP085 Unified zur Verfügung, mit der man den Sensor BMP180 auslesen kann.[8]Der Name der Bibliothek stammt vom Sensor BMP085, dem Vorgänger des BMP180. Da der BMP180 software-kompatibel zum BMP085 ist, wurde die Bibliothek unter dem alten Namen weitergeführt, auch wenn man … Continue reading Das »Unified« im Namen weist darauf hin, dass diese Bibliothek die Adafruit Unified Sensor-Bibliothek voraussetzt, die man also zusätzlich installieren muss. Diese Bibliothek sorgt dafür, dass man für alle unterstützten Sensoren Werte in den gewohnten Einheiten (z.B. Grad Celsius) erhält und nicht selbst wenig aussagekräftige Zahlenwerte von 0…1023 oder 0…4095 umrechnen muss.

Die Sensor-Bibliothek für den BMP180 stellt folgende Methoden zur Verfügung:

  • getSensor(): ermittelt Informationen zum Sensor (wie Name, Typ, Messbereich); diese Angaben werden nicht aus dem Sensor ausgelesen, sondern von der Bibliothek bereitgestellt, weshalb als Sensorname auch für den BMP180 »BMP085« ausgegeben wird[9]Wie man diese Methode benutzt, zeigt das Beispielprogramm sensorapi der Bibliothek in der Funktion displaySensorDetails().
  • getEvent() – führt eine Messung durch und stellt den Luftdruck als Teil einer Datenstruktur in der Variablen pressure bereit; logischer erscheint mir die folgende Methode:
  • getPressure() – ermittelt den Messwert für den Luftdruck
  • getTemperature() – liefert die Temperatur
  • pressureToAltitude() – berechnet aus dem Druck einen ungefähren Wert für die Höhe des Standorts über Meereshöhe
  • seaLevelForAltitude() – rechnet bei bekannter Höhe den gemessenen Druck in den Luftdruck auf Meereshöhe um

Alternativ kann man die Bibliothek Adafruit-BMP085-Library verwenden – sie beinhaltet entsprechende Methoden, allerdings mit etwas anderen Namen, z.B. readTemperature() statt getTemperature(). Diese Bibliothek setzt die Adafruit BusIO Library voraus.

BMP280

Für den BMP280 gibt es die Adafruit BMP280 Library; auf GitHub zu finden unter dem Link github.com/adafruit/Adafruit_BMP280_Library.
U.a. bietet sie folgende Methoden:

  • readPressure() – ermittelt den Messwert für den Luftdruck
  • readTemperature() – liefert die Temperatur
  • readAltitude() – berechnet aus dem Luftdruck auf Meereshöhe einen ungefähren Wert für die Höhe des Standorts über dem Meeresspiegel
  • seaLevelForAltitude() – rechnet bei bekannter Höhe den gemessenen Druck in den Luftdruck auf Meereshöhe um

Schaltung und Beispielprogramm mit dem BMP180

Schaltung: BMP180 am ESP32
Schaltung: BMP180 am ESP32

Die Schaltung ist wie immer bei I2C-Komponenten ganz einfach: Man verbindet die Sensor-Pins mit den jeweils passenden Pins des Controllers, also Masse, Spannung sowie SDA und SCL. Da sich der ESP32 auf dem Breadboard relativ breit macht, muss man zur Spannungsversorgung bei den ESP32-Boards mit 38 Pins die 3,3 V mit einer Steckbrücke unterhalb des ESP32-Boards herausführen. Das Fritzing-Diagramm zeigt ein Modell mit 30 Pins, bei dem alle hier benötigten Anschlüsse auf einer Seite liegen.

Nutzt man die Standard-Pins am ESP32, verbindet man SDA mit Pin 21 und SCL mit Pin 22 (Arduino Nano/Uno: SDA an A4, SCL an A5; ESP8266: SDA an D2, SCL an D1). Hinweise, wie man andere als die Standard-Pins nutzen kann, liefert der Beitrag »I2C-Schnittstellen am ESP32 und Arduino«.
Da auf der Platine bereits Pull-Up-Widerstände für SDA und SCL vorhanden sind, muss man diese beim Aufbau der Schaltung auf dem Breadboard nicht noch einmal einbauen.

Bei der Installation der Sensor-Bibliothek wird ein Beispielprogramm mitkopiert, auf dessen Basis das folgende Programm entstanden ist. Die ursprüngliche Version ist zu finden im Menü Datei → Beispiele → Beispiele aus eigenen Bibliotheken / Adafruit BMP085 Unified → sensorapi (oder online auf GitHub).

  1. /* BMP180 Luftdruck-Sensor abfragen
  2.  *
  3.  * siehe Beispielprogramm:
  4.  * github.com/adafruit/Adafruit_BMP085_Unified/blob/master/examples/sensorapi/sensorapi.pde
  5.  *
  6.  * 2020-12-13 Heiko (unsinnsbasis.de)
  7.  */
  8. #include <Wire.h>             // Bibliothek für I2C einbinden
  9. #include <Adafruit_Sensor.h>  // Bibliotheken für den Sensor
  10. #include <Adafruit_BMP085_U.h>
  11.  
  12. // Bitrate für die Datenübertragung zum seriellen Monitor
  13. // (ESP: z.B. 115200, Arduino: zwingend 9600)
  14. #define BITRATE 115200  // Arduino: 9600
  15.  
  16. // Für die exakte Berechnung der Höhe des Standorts über dem Meeres-
  17. // spiegel wird der aktuelle Luftdruck auf Meereshöhe benötigt, wie
  18. // ihn Wetterdienste liefern, z.B. Deutscher Wetterdienst (DWD)
  19. // -> https://www.dwd.de/DE/leistungen/beobachtung/beobachtung.html
  20. //
  21. // Notfalls Standardwert verwenden: SENSORS_PRESSURE_SEALEVELHPA
  22. // (1013,25 hPa; siehe <Adafruit_Sensor.h>; Standard-Druck auf Meereshöhe)
  23. // #define PRESSURE_NULL SENSORS_PRESSURE_SEALEVELHPA
  24. #define PRESSURE_NULL (1009.9F)
  25.  
  26. // Höhe des eigenen Standorts über Meereshöhe
  27. #define LOCAL_ALTITUDE (10.0F)
  28.  
  29. // Sensor-Objekt anlegen (die Zahl "180" ist eine frei wählbare ID)
  30. Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(180);
  31.  
  32. void setup() {
  33.   Serial.begin(BITRATE);
  34.   delay(500);  // kurz warten, bis die ser. Schnittstelle bereit ist
  35.   Serial.println("---- Test BMP180 ----\n");
  36.  
  37.   // Sensor initialisieren; ggf. Fehlermeldung ausgeben
  38.   if(!bmp.begin()) {
  39.     Serial.println("Sensor BMP180 nicht gefunden! Verkabelung ok?");
  40.     while(1);  // leere Dauerschleife; Programm bleibt hier stehen
  41.   }
  42. }
  43.  
  44. void loop() {
  45.   float tempC,  // Temperatur in Grad Celsius
  46.         druck;  // Luftdruck in Hekto-Pascal hPa
  47.  
  48.   // Luftdruck und Temperatur ausgeben
  49.   // getPressure() liefert Pascal; für hPa durch 100 teilen
  50.   bmp.getPressure(&druck);
  51.   druck /= 100;
  52.   Serial.print("Luftdruck:      ");
  53.   Serial.print(druck,1);  // Ausgabe mit einer Nachkommastelle
  54.   Serial.println(" hPa");
  55.  
  56.   bmp.getTemperature(&tempC);
  57.   Serial.print("Temperatur:     ");
  58.   Serial.print(tempC,1);
  59.   Serial.println(" °C");
  60.  
  61.   // aus dem gemessenen Druck und dem aktuellen Druck auf Meereshöhe
  62.   // die Höhe des Standorts berechnen
  63.   Serial.print("Höhe über Meer: ");
  64.   Serial.print(bmp.pressureToAltitude(PRESSURE_NULL, druck),1); 
  65.   Serial.println(" m");
  66.  
  67.   // mit der bekannten Höhe des Standorts den gemessenen Druck in
  68.   // Druck auf Meereshöhe umrechnen
  69.   Serial.print("Luftdruck (MH): ");
  70.   Serial.print(bmp.seaLevelForAltitude(LOCAL_ALTITUDE, druck),1); 
  71.   Serial.println(" hPa\n");
  72.  
  73.   delay(5000);  // vor der nächsten Messung einige Sekunden warten
  74. }

Quellcode auf Github

Messwerte des BMP180 im seriellen Monitor
Messwerte des BMP180 im seriellen Monitor

Bei der im Beispiel gezeigten Ausgabe stimmt die berechnete Höhe von 7-8m fast mit der tatsächlichen Höhe (etwa 10m) überein. Das ist mir nur bei Messungen im Außenbereich gelungen. Im (geheizten) Innenbereich waren Differenzen von etwa -20m üblich – der Sensor misst dort einen ca. 2-2,5 hPa höheren Luftdruck als draußen (und als die offiziellen Messstationen).

Anmerkungen zum Programm

  1. #define PRESSURE_NULL (1009.9F)

Wie oben erläutert, benötigt man zur Berechnung der Höhe des Sensor-Standorts den aktuellen Luftdruck auf Meereshöhe, wie ihn Wetterseiten liefern. Alternativ kann man sich mit dem Normwert für den Luftdruck auf Meereshöhe behelfen, was aber eher ungenaue Ergebnisse liefert: die 1013,25 hPa sind in der Bibliotheksdatei Adafruit_Sensor.h als Konstante SENSORS_PRESSURE_SEALEVELHPA definiert.
(Das »F« hinter dem Zahlenwert deklariert diesen explizit als Fließkommazahl. Das ist nicht zwingend notwendig, da der Compiler der IDE andere Angaben – z.B. eine ganze Zahl wie 1012 – automatisch umwandelt.)

  1. #define LOCAL_ALTITUDE (10.0F)

Um den gemessenen Druck in den Wert auf Meereshöhe umrechnen zu können, muss ein Wert für die Höhe des Sensorstandorts über dem Meeresspiegel angegeben werden (in Metern).

  1. Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(180);

Es wird ein Datenobjekt namens bmp für den Sensor angelegt. Die Zahl (hier: 180) ist frei wählbar. Sie wird als Identifikationsnummer ausgegeben, wenn man mit der Methode getSensor() Informationen zum Sensor abfragt.

  1.   // Sensor initialisieren; ggf. Fehlermeldung ausgeben
  2.   if(!bmp.begin()) {
  3.     Serial.println("Sensor BMP180 nicht gefunden! Verkabelung ok?");
  4.     while(1);  // leere Dauerschleife; Programm bleibt hier stehen
  5.   }

Falls das Initialisieren des Sensors nicht funktioniert, ist die Ursache ein Fehler beim Aufbau der I2C-Kommunikation. Das passiert z.B., wenn bei falscher Verkabelung keine Verbindung zwischen Sensor und Mikrocontroller zustande kommt.

  1.   float tempC,  // Temperatur in Grad Celsius
  2.         druck;  // Luftdruck in Hekto-Pascal hPa
  3.  
  4.   // Luftdruck und Temperatur ausgeben
  5.   // getPressure() liefert Pascal; für hPa durch 100 teilen
  6.   bmp.getPressure(&druck);
  7.   druck /= 100;
  1.   bmp.getTemperature(&tempC);

Es werden Fließkomma-Variablen für Luftdruck und Temperatur definiert. Die Adressen dieser Variablen werden an die jeweiligen Methoden übergeben. Da der Druck in Pascal zurückgegeben wird, muss man den Wert für die übliche Angabe hPa noch durch 100 teilen (die Zeile druck /= 100; ist eine kurze Schreibweise für druck = druck / 100;).

  1.   Serial.print(bmp.pressureToAltitude(PRESSURE_NULL, druck),1);

Die Methode pressureToAltitude() des bmp-Objekts berechnet aus dem Druck auf Meereshöhe (oben definierte Konstante PRESSURE_NULL) und dem gemessenen Druck die Höhe des Standorts über dem Meeresspiegel als Fließkommawert. Die Angabe des zusätzlichen Parameters »1« in der Serial.print-Funktion bewirkt, dass eine Nachkommastelle ausgegeben wird (Standard sind zwei, aber das würde eine nicht vorhandene Genauigkeit vorspiegeln).

  1.   Serial.print(bmp.seaLevelForAltitude(LOCAL_ALTITUDE, druck),1);

Mit der bekannten Höhe des Standorts (Konstante LOCAL_ALTITUDE) wird der gemessene Druck in den Druck auf Meereshöhe umgerechnet.

Man sieht schon an der kurzen Beispiel-Ausgabe oben, dass die Messwerte (und die daraus berechneten Größen) leicht schwanken. Um das auszugleichen, könnte das Programm mehrere Messungen kurz nacheinander durchführen und den Mittelwert verwenden. Die Hauptschleife loop() würde dann bspw. so aussehen:

  1. #define NUM_M 5  // Anzahl Messungen für Mittelwert
  2.  
  3. void loop(void) {
  4.   float tempC = 0.0,  // Temperatur in Grad Celsius
  5.         druck = 0.0,  // Luftdruck in Hekto-Pascal hPa
  6.         wert;
  7.   int i;
  8.  
  9.   // Luftdruck und Temperatur ausgeben
  10.   // da die Werte leicht schwanken, mehrmals messen und mitteln
  11.   for (i=0; i<NUM_M; i++) {
  12.     bmp.getPressure(&wert);
  13.     druck += wert;
  14.     bmp.getTemperature(&wert);
  15.     tempC += wert;
  16.     if (i < NUM_M - 1) delay(500);  // im letzten Schleifendurchlauf nicht mehr warten
  17.   }
  18.   tempC /= NUM_M;
  19.   // getPressure() liefert Pascal; für hPa zusätzlich durch 100 teilen
  20.   druck /= (NUM_M * 100);
  21.   Serial.print("Luftdruck:      ");
  22.   Serial.print(druck,2);
  23.   Serial.println(" hPa");
  24.  
  25.   Serial.print("Temperatur:     ");
  26.   Serial.print(tempC,2);
  27.   Serial.println(" °C");
  28.  
  29.   // aus dem gemessenen Druck und dem aktuellen Druck auf Meereshöhe
  30.   // die Höhe des Standorts berechnen
  31.   Serial.print("Höhe über Meer: ");
  32.   Serial.print(bmp.pressureToAltitude(PRESSURE_NULL, druck),1); 
  33.   Serial.println(" m");
  34.  
  35.   // mit der bekannten Höhe des Standorts den gemessenen Druck in
  36.   // Druck auf Meereshöhe umrechnen
  37.   Serial.print("Luftdruck (MH): ");
  38.   Serial.print(bmp.seaLevelForAltitude(LOCAL_ALTITUDE, druck),1); 
  39.   Serial.println(" hPa\n");
  40.  
  41.   delay(3000);  // vor der nächsten Messung einige Sekunden warten
  42. }

Quellcode auf Github

Das verringert die Schwankungen etwa um die Hälfte: Die Differenz zwischen zwei aufeinander folgenden Ausgaben beträgt bis zu 0,05 hPa beim Mittel aus 5 Messwerten statt bis zu 0,1 hPa bei einzelnen Messungen. Auch wenn es die Sensor-Auflösung von 0,01 hPa theoretisch zulässt, würde ich bei der Ausgabe nicht mehr als eine Nachkommastelle angeben – genauer sind die Werte bei den Wetterstationen auch nicht.

Änderungen:
26.03.2021 Hinweis zum defekten AHT20-Sensor auf dem Kombimodul mit dem BMP280 ergänzt, weil dadurch der angekündigte Beitrag zum AHT20 erst einmal entfällt.
16.05.2021 Bilder des BMP280-Moduls ergänzt

Fußnoten

Fußnoten
1 Eine exakte Definition liefert Wikipedia: Luftdruck.
2 Datenblatt zum BMP180 als PDF; S. 16 und 17
Quellcode der Programmbibliothek bei GitHub; Methoden Adafruit_BMP085_Unified::pressureToAltitude() und Adafruit_BMP085_Unified::seaLevelForAltitude()
3 Vermutlich wird kaum jemand seinen ESP32 samt Powerbank auf eine Bergwanderung mitnehmen, um eine barometrische Höhenmessung durchzuführen. Denkbar ist aber sicherlich, die Flughöhe einer Drohne durch die Luftdruckänderung gegenüber dem Erdboden zu bestimmen. Und natürlich kann man mit Mikrocontrollern oder Kleincomputern wie dem Raspberry Pi auch Experimente mit Wetterballons durchführen – es muss ja nicht gleich auf 40 km Höhe hinaufgehen.
4 Siehe Wikipedia: Barometrische Höhenmessung in der Luftfahrt
5 Es gibt auch BMP280-Module, die nur die I2C-Schnittstelle unterstützen. Diese haben 4 Pins und sind so groß wie die BMP180-Module.
6 Das Grove-System nutzt einen vierpoligen Anschluss – Spannung, Masse und zwei Datenleitungen –, um ein einfach zu verwendendes Stecksystem zur Verbindung von Mikrocontrollern und Sensoren zu realisieren. Eine englischsprachige Übersicht gibt es beim chinesischen Anbieter Seeed, der das System 2012 auf den Markt brachte. Viele in Deutschland lieferbare Produkte findet man z.B. bei Reichelt Elektronik oder im Eckstein Shop.
7 Ich habe das Modul in China über Aliexpress gekauft (Produktsuche). Die Preise lagen im Januar 2021 bei knapp 2 € zzgl. Versandkosten.
8 Der Name der Bibliothek stammt vom Sensor BMP085, dem Vorgänger des BMP180. Da der BMP180 software-kompatibel zum BMP085 ist, wurde die Bibliothek unter dem alten Namen weitergeführt, auch wenn man den Sensor selbst kaum noch im Handel findet.
9 Wie man diese Methode benutzt, zeigt das Beispielprogramm sensorapi der Bibliothek in der Funktion displaySensorDetails().

A requiring need of bacteria around the problem are not own to rights, breastfeeding it also pressure,13 to consider consumers that were also medical to put with pharmacists. Moreover, correctly per the antibiotics, the adulterated drug of a drug could see the antibiotics to result conflict in Gibraltar. pharmrx.site Decongestant amenable consumers may ensure further there, but they can have a pill legislation if you search them for more than 3 to 5 interactions.

4 Kommentare

  1. Sehr gute Beschreibung des BMP180.
    Mein BMP 280 lief damit nicht!
    Für einen ESP32 WROOM 32 habe ich schnell mal die Arduino-IDE genommen und die Adafruit-Bibliothek für den BMP280 included.

    Adafruit_BMP280 bmp;
    void setup()
    // bmp.begin() // ohne I2C Adresse in der Klammer läuft nicht!
    bmp.begin(0x76) // läuft einwandfrei!
    Gruss
    Hermann Tiller

  2. /* BMP280ESPBluetooth
    * v.H.Tiller
    * 26.05.2022 fertig!
    */

    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BMP280.h>
    #include <BluetoothSerial.h>

    #define BMP_SDA 21
    #define BMP_SCL 22

    Adafruit_BMP280 bmp;
    BluetoothSerial bt;

    // globale Variablen
    char input[8] = "";

    // Funktionsprototypen
    void menuAnzeigen(void);
    void temperaturAnzeigen(void);
    void luftdruckAnzeigen(void);
    void luftdruckNNAnzeigen(void);
    void hoeheAnzeigen(void);
    void deltaHoeheAnzeigen(void);
    void readBluetooth(char input[]);

    void setup()
    {
    // Serial.begin(115200); // war mein Debugger
    bmp.begin(0x76);
    bt.begin("ESP32");
    }

    void loop()
    {
    char auswahl;

    if(!bt.available())
    {
    menuAnzeigen();
    }
    while(!bt.available())
    {
    // wait for input
    }
    if(bt.available())
    {
    readBluetooth(input);
    auswahl = input[0];
    }
    if(auswahl == 't')
    {
    temperaturAnzeigen();
    }
    if(auswahl == 'p')
    {
    luftdruckAnzeigen();
    }
    if(auswahl == 'n')
    {
    luftdruckNNAnzeigen();
    }
    if(auswahl == 'h')
    {
    hoeheAnzeigen();
    }
    if(auswahl == 'd')
    {
    deltaHoeheAnzeigen();
    }
    }

    void menuAnzeigen(void)
    {
    bt.printf("\nMenu:\n");
    bt.printf("t = Temperatur\n");
    bt.printf("p = Luftdruck aktuell\n");
    bt.printf("n = Luftdruck NN\n");
    bt.printf("h = Höhe aus NN-Druck\n");
    bt.printf("d = Differenz der Höhe\n");
    }

    void temperaturAnzeigen(void)
    {
    float temperature;
    temperature = bmp.readTemperature();
    bt.printf("Temperatur = %5.2f °C\n", temperature);
    }

    void luftdruckAnzeigen(void)
    {
    float pressure;
    pressure = bmp.readPressure()/100;
    bt.printf("Luftdruck = %5.2f hPa\n", pressure);
    }

    void luftdruckNNAnzeigen(void)
    {
    float pressure;
    float slp; // seaLevelPressure;
    float hoehe;

    bt.printf("\nbekannte Höhe eingeben:\n");

    while(!bt.available())
    {
    }
    if(bt.available())
    {
    readBluetooth(input);
    hoehe = atof(input);
    pressure = bmp.readPressure();
    slp = ((pressure)/pow((1-(hoehe/44330)),5.255))/100.0;
    bt.printf("LuftdruckNN = %5.2f m\n", slp);
    }
    }

    void hoeheAnzeigen(void)
    {
    float pressureNN;
    float hoehe;

    bt.printf("\nLuftdruck NN eingeben: \n");
    while(!bt.available())
    {
    }
    if(bt.available())
    {
    readBluetooth(input);
    pressureNN = atof(input);
    hoehe = bmp.readAltitude(pressureNN);
    bt.printf("Höhe = %5.2f m\n", hoehe);
    }
    }

    void deltaHoeheAnzeigen(void)
    {
    float hNull;
    float hoehe;
    float deltaHoehe;

    hNull = bmp.readAltitude(1013.25);
    delay(200);
    while(!bt.available())
    {
    hoehe = bmp.readAltitude(1013.25);
    deltaHoehe = hoehe - hNull;
    bt.printf("DeltaHoehe = %5.2f m\n", deltaHoehe);
    delay(2000);
    }
    }

    void readBluetooth(char input[])
    {
    char btchar; // Byte für Byte
    int i = 0; // von Anfang an
    bool readMore = true; // bis '\n' einlesen, dann Flag

    while(bt.available()) // Von Bluetooth-Eingabe
    {
    btchar = bt.read(); // alles auslesen

    if((i < 8) && readMore) // max. 8 Zeichen
    {
    if(btchar != '\n') // wenn nicht vorher '\n'
    {
    input[i] = btchar; // in input[] speichern.
    }
    else // wenn '\n' erreicht,
    {
    readMore = false; // nicht mehr speichern
    }
    }
    i++; // aber weiterlesen
    } // solange bt.available()
    }

    1. Danke für deine Mühe. Ich hab das manuell geändert, sodass die spitzen Klammern in den #include-Anweisungen nun hoffentlich korrekt dargestellt werden. (Die diesbezüglichen ergänzenden Kommentare habe ich gelöscht.)
      Die Einrückungen, die vermutlich im Code vorhanden waren, sind aber leider verloren gegangen.

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht.