Luftdrucksensor BMP280

Wie schon seine Vorgänger BMP085 und BMP180 (siehe Luftdrucksensor BMP180) gibt auch der Luftdrucksensor BMP280 von Firma Bosch den gemessenen Luftdruck (Stationsluftdruck) und die Umgebungstemperatur als Rohwerte aus, wobei die Ausgabe nun wahlweise über I2C- oder über SPI-Schnittstelle erfolgen kann. Aber auch sonst wartet der BMP280 gegenüber dem BMP180 mit einigen Verbesserungen auf, z.B.:

  • Geringere Abmessungen des Sensors
  • Geringerer Stromverbrauch
  • Höhere Auflösung bei Druck und Temperatur
  • Höhere Messrate
  • Filtermöglichkeit
  • etc.

Mit Hilfe von 12 im Sensor gespeicherten Kompensationsparametern kann aus den Rohwerten der Luftdruck am Standort (Stationsniveauluftdruck) und die Umgebungstemperatur ermittelt werden.

                

Bild 1: Luftdrucksensor BMP280 auf einem Mini Breakout Board (Abmessg. ca 10 x 13 mm), mit Pegelwandler für Versorgungs- und Logik-spannung von 5 V.

             

Bild 2: Größenvergleich Mini-BMP280-Modul mit  1 EURO Münze

BMP280-Breakout Boards sind in verschiedenen Ausführungen erhältlich, z.B. mit oder ohne Pegelwandler für die Versorgungs- und Logikspannung oder mit ausgeführter I2C- und SPI-Schnittstelle oder nur mit I2C-Schnittstelle. Da der Sensor selbst, sowohl was die Versorgungspannung, als auch die Logikspannung betrifft, laut Datenblatt für maximal 4,25 V ausgelegt ist, sind bei Verwendung von Mikrocontroller mit 5 V - Versorgungs- und Logikspannung (wie z.B. beim Arduino Uno, Nano oder Mega) unbedingt Pegelwandler einzusetzen.

Das von mir eingesetzte Mini-Breakout-Board hat sowohl die Pegelwandler für beide Spannungen integriert, als auch die Pullup-Widerstände für die I2C-Schnittstelle, hat aber keine SPI-Schnittstelle auf die Stiftleiste herausgeführt.


Testaufbau mit I2C-Schnittstelle:

Hier geht's zum Testaufbau mit SPI-Schnittstelle und zum Testaufbau mit Attiny

I2C-Adresse:

Die Standard-I2C-Adresse des abgebildeten Moduls ist 0x76 und kann mit einer Lötbrücke am Modul auf 0x77 geändert werden. Das habe ich aber nicht ausprobiert! Laut Bosch-Datenblatt ist der SDO-Pin am Sensor das Adressbit 0 der I2C-Adresse, der entweder auf GND oder auf VDD gelegt werden muss.

Inzwischen habe ich auch das Breakout Board von Adafruit getestet. Dort ist ohne Beschaltung des SDO-Pin die I2C-Adresse 0x77, da der SDO-Pin auf dem Breakout Board über einen Widerstand auf "High" gelegt ist. Legt man den SDO-Pin auf Masse, ist die I2C Adresse 0x76.

Des Weiteren habe ich noch Billigst-Module aus China im Testeinsatz (Stückpreis EUR 2,64 inkl. Versandt). Bei diesen Modulen ist wiederum die Standardadresse (ohne Beschaltung des SDO-Pins) 0x76 und kann durch "High"-legen des SDO-Pin auf 0x77 verändert werden.

Verwendete Bauteile:

  • 1 Arduino Nano
  • 1 BMP280-Luftdrucksensor Mini Breakout Board (siehe Bild 1)

Optional:

  • 2 Widerstände 10 kOhm (I2C-Pullup-Widerstände, falls diese nicht am BMP280 Breakout Board vorhanden sind)



Library MyBMP280 für Arduino und Attiny85:

Für Arduino und Attiny habe ich für diesen Sensor Libraries mit folgenden Funktionen geschrieben:


  • Verwendung der I2C- oder SPI-Schnittstelle (SPI nur für Arduino)
  • Abfrage, ob der Baustein ansprechbar ist (Auslesen der Chip-Identifikationsnummer, welche 0x58 ist)
  • Setzen von einzelnen Parameter, wenn andere Parameter als die Voreingestellten erforderlich sind  1)
  • Setzen von definierten Parametersätzen  2)
  • Initialisieren der Parameter und Einlesen der Kalibrierungskoeffizienten
  • Ermittlung der Umgebungstemperatur
  • Ermittlung des Luftdrucks am Standort (Stationsluftdruck)
  • Ermittlung des reduzierten Luftdrucks bezogen auf Meereshöhe (Reduzierter Luftdruck)


1)  Die in der Library voreingestellten Parameter sind:

  • NORMAL_MODE
  • P_OVERSAMPLING_x8
  • T_OVERSAMPLING_x2
  • STANDBY_TIME_1000
  • FILTER_COEFF_4

Die einzelnen Parameter werden im Control- und Configregister des BMP280 gespeichert (siehe Register). Was die einzelnen Parameter bedeuten und welche Änderungsmöglichkeiten es gibt, habe ich nachfolgend zusammengefasst:

Setzen des Modus

Beim BMP280 gibt es drei Betriebsmoden:

  • SLEEP_MODE: Im Sleep-Modus erfolgen keine Messungen
  • NORMAL_MODE: Im Normal-Modus erfolgen die Messungen zyklisch. Die Zykluszeit ist abhängig von der "Standby Time" und den Oversampling-Einstellungen.
  • FORCED_MODE: Wenn der Forced-Modus gesetzt wird, führt der Sensor genau eine Messung durch und wechselt anschließend in den Sleep-Modus, solange bis der Forced-Modus für eine nächste Messung erneut gesetzt wird.

Setzen von Temperatur-Oversampling:

Info: In der digitalen Signalverarbeitung spricht man von Oversampling (Überabtastung), wenn ein Signal mit einer höheren Abtastrate bearbeitet wird, als es für die Darstellung der Signalbandbreite benötigt wird, was z.B. bei Analog/Digitalwandler Vorteile bringen kann -> siehe z.B. de.wikipedia.org/wiki/%C3%9Cberabtastung

Mit dem Parameter wird die Auflösung der Temperaturmessung vorgegeben oder ausgeschaltet.

  • T_OVERSAMPLING_x0:   Keine Temperaturmessung
  • T_OVERSAMPLING_x1:   Auflösung 16 Bit
  • T_OVERSAMPLING_x2:   Auflösung 17 Bit
  • T_OVERSAMPLING_x4:   Auflösung 18 Bit
  • T_OVERSAMPLING_x8:   Auflösung 19 Bit
  • T_OVERSAMPLING_x16: Auflösung 20 Bit

Jeder Erhöhungsschritt reduziert das Rauschen und erhöht die Auflösung um 1 Bit.

Die gemessene Temperatur ist auch für die Genauigkeit der Berechnung des Drucks aus den Rohwerten erforderlich.

Allerdings ist eine Vorgabe von größer als 17 Bit (T_OVERSAMPLING_x2) nicht erforderlich, da dadurch die Genauigkeit der Druckmessung nicht signifikant erhöht wird. (Quelle: Fa. Bosch, BMP280 Datenblatt Rev.1.18, Seite 13)

Setzen von Druck-Oversampling:

Mit dem Parameter wird die Auflösung der Druckmessung vorgegeben oder ausgeschaltet:

  • P_OVERSAMPLING_x0:   Keine Druckmessung
  • P_OVERSAMPLING_x1:   Auflösung 16 Bit -> Ultra geringe Stromaufnahme
  • P_OVERSAMPLING_x2:   Auflösung 17 Bit -> geringe Stromaufnahme
  • P_OVERSAMPLING_x4:   Auflösung 18 Bit -> Standardauflösung
  • P_OVERSAMPLING_x8:   Auflösung 19 Bit -> Hohe Auflösung
  • P_OVERSAMPLING_x16: Auflösung 20 Bit -> Ultra hohe Auflösung

Jeder Erhöhungsschritt reduziert das Rauschen und erhöht die Auflösung um 1 Bit.

Setzen der Standby-Zeit: Das ist jene Zeit, wo im Normal-Modus der Sensor nach einer Messung nicht aktiv ist, also keine Messungen durchführt werden:

  • STANDBY_TIME_0p5:   Standby Zeit = 0,5 ms
  • STANDBY_TIME_62p5: Standby Zeit = 62,5 ms
  • STANDBY_TIME_125:   Standby Zeit = 125 ms
  • STANDBY_TIME_250:   Standby Zeit = 250 ms
  • STANDBY_TIME_500:   Standby Zeit = 500 ms
  • STANDBY_TIME_1000: Standby Zeit = 1000 ms
  • STANDBY_TIME_2000: Standby Zeit = 2000 ms
  • STANDBY_TIME_4000: Standby Zeit = 4000 ms

Setzen des Filter-Koeffizienten:

Gibt an, wie viele Abtastungen (samples) erforderlich sind, bis - bei einer sprunghaften Änderung des Messwertes - die Datenausgabe mindestens 75 % der Änderung gefolgt ist:

  • FILTER_COEFF_0:    1 Abtastung (Filter ausgeschaltet)
  • FILTER_COEFF_2:    2 Abtastungen
  • FILTER_COEFF_4:    5 Abtastungen
  • FILTER_COEFF_8:   11 Abtastungen
  • FILTER_COEFF_16: 22 Abtastungen

Je höher die Filter-Koeffizient, desto langsamer nähert sich der Messwert dem tatsächlichen Druck an und umso geringer wird das Rauschen.

Achtung: Die Zusammenhänge der einzelnen Parameter in Bezug auf Stromverbrauch, Signalauflösung, Messzeiten, Signalrauschen, etc. kann im Datenblatt des Sensors ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-19.pdf nachgelesen werden!


2)  Für 3 Szenarien können die Parameter als Parametersätze gesetzt werden. Die Werte der Parametersätze entsprechen den vorgeschlagenen Werten des Bosch-Datenblattes des Sensors:

Weathermonitoring: Ultra geringe Leistungsaufnahme, Messrate: z.B. 1/60 Hz

  • SLEEP_MODE (Aufruf des Forced_Modus im Anwenderprogramm mit der Funktion "startSingleMeas()", z.B. 1 mal pro Minute)
  • P_OVERSAMPLING_x1
  • T_OVERSAMPLING_x1
  • FILTER_COEFF_0
  • STANDBY_TIME_xxxx (Standby time im Forced Mode ohne Bedeutung)

Handheld device low power: Ultra hohe Auflösung, Messrate: 10 Hz

  • NORMAL_MODE
  • P_OVERSAMPLING_x16
  • T_OVERSAMPLING_x2
  • FILTER_COEFF_4
  • STANDBY_TIME_62p5

Handheld device dynamic: Standardauflösung, Messrate: 83 Hz

  • NORMAL_MODE
  • P_OVERSAMPLING_x4
  • T_OVERSAMPLING_x1
  • FILTER_COEFF_16
  • STANDBY_TIME_0p5


Die Library kann hier heruntergeladen werden:

Sollte die Library jemand verwenden oder testen, würde ich mich über eine Rückmeldung sehr freuen!


Version 4.1 (mit I2C und SPI-Schnittstelle)

MyBMP280.cpp.txt

MyBMP280.h.txt

keywords.txt

Leider kann ich hier keine "cpp"- oder "h"-Files hochladen, daher zum Verwenden der Library das Suffix ".txt" aus diesen Dateinamen entfernen und in einem neuen Verzeichnis mit dem Namen "MyBMP280" im Sketchbook-Ordner im Ordner "libraries" speichern.


Zur Auflistung der Funktionen der Library geht es hier: Funktionen

Programmbeispiele MyBMP280 mit I2C-Schnittstelle:

Verwendete Libraries:

Neben der zu testenden Library MyBMP280 verwende ich für die Programmbeispiele noch die Library Metro, womit ich die zyklische Wiederholung von Vorgängen steuere. Einen Link zu Metro gibt es hier: Fremd-Libraries


Beispiel 1:

Im Beispiel 1 werden die Messwerte im Normal-Modus mit den in der Library voreingestellten Parametern zyklisch berechnet und ausgegeben. Nur der Parameter für Druck-Oversampling wird geändert. Der voreingestellte Wert für die Standby-Zeit ist 1000 ms. Das heißt, dass ca. einmal pro Sekunde eine neue Messung vom Sensor durchgeführt wird und Temperatur und Druck als Rohwerte gespeichert werden. Daher lese ich auch nur einmal pro Sekunde die Werte aus.


//Testprogramm 1 für Luftdrucksensor BMP280
//Code fuer Arduino
//Author Retian
//Version 1.1


#include <MyBMP280.h>
#include <Metro.h>


MyBMP280 BMP(0x76);
Metro leseZyklus = Metro(1000); //Zykluszeit in ms für Auslesen des Sensors


int hoehe = 460; //Messort: 460 m über dem Meer
float luftTemp, luftDruck, redLuftDruck;


void setup() {
  Serial.begin(115200);
  if (BMP.isReady()) Serial.println("BMP280 Ok!");
  else
  {
    Serial.println("BMP280 Fehler!");
    while (1); //Im Fehlerfall geht's hier nicht weiter!
  }

  BMP.setPressOversampling(BMP280_P_OVERSAMPLING_x2); //Ändere Druck-Oversampling Parameter
  BMP.init();
}


void loop() {
  if (leseZyklus.check())
  {
    luftTemp = BMP.readTemp();
    Serial.print("Lufttmperatur  : ");
    Serial.print(luftTemp);
    Serial.println(" Grad C");

    luftDruck = BMP.readPress();
    Serial.print("Luftdruck      : ");
    Serial.print(luftDruck);
    Serial.println(" hPa");

    redLuftDruck = BMP.readReducedPress(hoehe);
    Serial.print("Reduz.Luftdruck: ");
    Serial.print(redLuftDruck);
    Serial.println(" hPa");

    Serial.println();
  }
}


Beispiel 2:

Im Beispiel 2 werden die Parameter des Sensors auf "Weather Monitoring" gesetzt und mit der Funktion startSingleMeas() wird alle 60 Sekunden eine neue Messung gestartet und die Messergebnisse angezeigt.


//Testprogramm 2 für Luftdrucksensor BMP280
//Code fuer Arduino
//Author Retian
//Version 1.0


//Prototypen
void zeigeMesswerte(void);


#include <MyBMP280.h>
#include <Metro.h>


MyBMP280 BMP(0x76);
Metro messZyklus = Metro(60000); //Zyklus = 60000 ms = 1 min


float luftTemp, luftDruck;


void setup() {
  Serial.begin(115200);
  if (BMP.isReady()) Serial.println("BMP280 Ok!");
  else
  {
    Serial.println("BMP280 Fehler!");
    while (1); //Im Fehlerfall geht's hier nicht weiter!
  }


  BMP.setWeatherMonitoring(); //Setze Parametersatz für Wetterbeobachtung

  //Beim Initialisieren des Parametersatzes für Wetterbeobachtung (Forced-Mode)
  //wird bereits eine Messung vom Sensor durchgeführt und als Rohwerte gespeichert
  BMP.init();

 
  //Erstes Einlesen der Messwerte, dann zyklisch im loop alle 60 s
  luftTemp = BMP.readTemp();
  luftDruck = BMP.readPress();
  zeigeMesswerte();
}


void loop() {
  if (messZyklus.check()) //Prüfe Zykluszeit
  {
    BMP.startSingleMeas(); //Starte eine "Einzelmessung"
    luftTemp = BMP.readTemp();
    luftDruck = BMP.readPress();
    zeigeMesswerte();
  }
}


void zeigeMesswerte(void)
{
  Serial.print("Lufttmperatur  : ");
  Serial.print(luftTemp);
  Serial.println(" Grad C");
  Serial.print("Luftdruck      : ");
  Serial.print(luftDruck);
  Serial.println(" hPa");
  Serial.println();
}