BME280 Arduino: Temperatur, Luftfeuchtigkeit, Luftdruck & Höhe
BME280 und BMP280 am Arduino: I2C-Adresse 0x76/0x77, Adafruit-Bibliothek, Höhe aus dem Luftdruck, 3,3-V-Warnung, ESP32-Wetterstation und Pico-MicroPython.
Der BME280 ist ein digitaler Umweltsensor von Bosch, der Temperatur, relative Luftfeuchtigkeit und Luftdruck in einem winzigen Chip misst. Um ihn am Arduino zu nutzen, brauchst du nur vier Kabel (VCC, GND, SDA, SCL) und die Bibliothek Adafruit BME280; mit ein paar Zeilen Code siehst du °C-, %- und hPa-Werte im seriellen Monitor. Da er den Luftdruck misst, kann er auch deine Höhe über dem Meeresspiegel berechnen. Sein kleiner Bruder, der BMP280, sieht fast genauso aus, misst aber keine Luftfeuchtigkeit; er liefert nur Temperatur und Luftdruck.
In diesem Artikel lernst du den Unterschied zwischen beiden Sensoren kennen, warum die I2C-Adresse mal 0x76 und mal 0x77 ist, wie du sie an Arduino Uno, ESP32 und Raspberry Pi Pico anschließt, wie die Höhenformel funktioniert und wie du den richtigen Luftdruck auf Meereshöhe wählst. Danach baust du eine ESP32-Mini-Wetterstation, die du auf dem Handy öffnest, lässt auf dem Pico einen MicroPython-Treiber ganz ohne Bibliothek laufen und siehst, wie ein einziger Sketch das weit verbreitete Problem "BMP280 als BME280 verkauft" aufdeckt.

Was ist der BME280 und wie funktioniert er?
Im BME280 stecken drei Messelemente. Der Drucksensor misst piezoresistiv, wie stark sich eine dünne Siliziummembran unter dem Luftdruck verformt. Der Feuchtesensor ist eine Polymerschicht, deren Kapazität sich ändert, wenn sie Feuchtigkeit aus der Luft aufnimmt. Der Temperatursensor liefert die Umgebungstemperatur und wird zugleich zur Korrektur der beiden anderen Messungen verwendet. Jeder Chip wird im Werk einzeln kalibriert, die Koeffizienten werden in seinem internen Speicher abgelegt; die Bibliothek liest sie beim Start aus und rechnet die Rohwerte mit den Formeln aus dem Datenblatt in echte Einheiten um. Das kleine Loch im Metalldeckel lässt die Luft an den Sensor; deck es also nie mit Klebeband oder Kleber ab.
| Eigenschaft | BME280 | BMP280 |
|---|---|---|
| Misst | Temperatur, Luftfeuchtigkeit, Luftdruck | Temperatur, Luftdruck |
| Temperatur | -40…+85 °C, ±1 °C (±0,5 °C bei 25 °C) | -40…+85 °C, ±1 °C (±0,5 °C bei 25 °C) |
| Relative Luftfeuchtigkeit | 0–100 %, ±3 % | Keine |
| Druckbereich | 300–1100 hPa | 300–1100 hPa |
| Druckgenauigkeit | Absolut ±1 hPa, relativ ±0,12 hPa (≈ ±1 m) | Absolut ±1 hPa, relativ ±0,12 hPa (≈ ±1 m) |
| Versorgungsspannung des Chips | 1,71–3,6 V | 1,71–3,6 V |
| Strom (1 Messung pro Sekunde) | 3,6 µA (alle drei Messungen) | 2,7 µA |
| Strom im Schlafmodus | 0,1 µA | 0,1 µA |
| Schnittstelle | I2C (bis 3,4 MHz) und SPI (bis 10 MHz) | I2C und SPI |
| Chip-ID (Register 0xD0) | 0x60 | 0x58 |
| Chipgröße | 2,5 × 2,5 mm (quadratisch) | 2,0 × 2,5 mm (rechteckig) |
Kurz gesagt ist der BMP280 ein etwas günstigerer BME280 ohne Feuchtesensor; Druck- und Temperaturmessung sind genauso gut. Wenn du nur Höhe oder Luftdruck brauchst, reicht ein BMP280. Für Projekte, bei denen die Luftfeuchtigkeit wichtig ist, etwa eine Wetterstation, ein Gewächshaus oder die Überwachung des Raumklimas, nimm den BME280. Eine Stufe darüber ergänzt der BME680/BME688 einen Gassensor, der flüchtige organische Verbindungen (VOC) in der Luft erkennt, kostet aber ein Mehrfaches.
BME280 oder DHT11/DHT22?
| Eigenschaft | DHT11 | DHT22 | BME280 |
|---|---|---|---|
| Temperaturbereich und Genauigkeit | 0–50 °C, ±2 °C | -40…+80 °C, ±0,5 °C | -40…+85 °C, ±1 °C |
| Genauigkeit Luftfeuchtigkeit | ±5 % | ±2–5 % | ±3 % |
| Luftdruck und Höhe | Nein | Nein | Ja |
| Schnellste Messung | 1-mal pro Sekunde | 1-mal alle 2 Sekunden | Dutzende pro Sekunde |
| Anschluss | Eine Datenleitung | Eine Datenleitung | I2C oder SPI |
| Strom (beim Messen) | ≈ 1 mA | ≈ 1,5 mA | Unter 1 mA |
DHT-Sensoren sind billig und einfach, aber langsam, liefern ab und zu Lesefehler und messen keinen Luftdruck. Der BME280 teilt sich denselben I2C-Bus mit anderen Geräten wie einem Display, zieht im Schlaf fast keinen Strom und ist ideal für Projekte, die monatelang mit Batterie laufen. Details zum DHT11 findest du im Artikel DHT11 Temperatur- und Feuchtigkeitssensor, alle Optionen nebeneinander im Vergleich der Temperatursensoren.
Modulvarianten und die 3,3-V-Warnung
Der nackte Chip ist so klein, dass er immer auf einem Breakout-Board verwendet wird, und zwei Varianten sind verbreitet. 6-polige Module (meist lila, verkauft als GY-BME280-3.3 oder GY-BMP280-3.3) haben die Pins VCC, GND, SCL, SDA, CSB und SDO; die meisten haben keinen Spannungsregler, und genau das sagt die 3.3 im Namen: Versorge sie nur mit 3,3 V. 4-polige Module (VIN, GND, SCL, SDA) haben meist einen kleinen 3,3-V-Regler und oft Pegelwandler-Transistoren für die I2C-Leitungen, sodass sie an den 5V-Pin des Arduino Uno dürfen. Wenn du nicht sicher bist, welche Variante du hast, such auf dem Board nach einem kleinen dreibeinigen Reglerchip; findest du keinen, nimm 3,3 V.
BME280 anschließen: Arduino Uno, ESP32 und Pico
| BME280-Pin | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC / VIN | 3.3V (6-polig) oder 5V (4-polig, mit Regler) | 3V3 | 3V3(OUT), Pin 36 |
| GND | GND | GND | GND, Pin 38 |
| SCL | A5 | GPIO 22 | GP5, Pin 7 |
| SDA | A4 | GPIO 21 | GP4, Pin 6 |
| CSB (6-polig) | 3.3V (wählt I2C) | 3V3 | 3V3 |
| SDO (6-polig) | Offen oder GND: 0x76, 3.3V: 0x77 | Offen oder GND: 0x76, 3V3: 0x77 | Offen oder GND: 0x76, 3V3: 0x77 |
An der Adresse scheitern die meisten. Liegt der SDO-Pin des Chips an GND, ist die Adresse 0x76, liegt er an 3,3 V, ist sie 0x77. Die meisten günstigen Module ziehen SDO über einen Widerstand auf GND und haben deshalb 0x76, Adafruits eigene Boards dagegen 0x77, und die Bibliothek probiert standardmäßig 0x77. Deshalb solltest du die Adresse im Code ausdrücklich angeben. Liegt der CSB-Pin beim Einschalten auf GND, wechselt der Chip in den SPI-Modus und antwortet nicht mehr über I2C; nutzt du I2C, verbinde CSB mit 3,3 V oder stell sicher, dass das Modul ihn bereits hochzieht. Die I2C-Pins deines Boards findest du im Tool Pinout, die Funktionsweise des Busses im Artikel Was ist I2C?.
Möchtest du zwei Sensoren am selben Bus betreiben, verbinde den SDO-Pin eines Sensors mit 3,3 V, damit er die Adresse 0x77 bekommt; bei 4-poligen Modulen geht das meist über eine Lötbrücke auf der Rückseite. Für mehr als zwei Sensoren ist SPI besser geeignet: SCL kommt an SCK (13 beim Uno), SDA an MOSI (11), SDO an MISO (12), und der CSB-Pin jedes Sensors an einen eigenen Digitalpin; im Code legst du das Objekt einfach mit Adafruit_BME280 bme(10); an. Da der 5-V-Uno die SPI-Leitungen direkt treibt, gehört zwischen ihn und ein 3,3-V-Modul unbedingt ein Pegelwandler.
Die Bibliothek Adafruit BME280 installieren
- Öffne in der Arduino IDE Werkzeuge > Bibliotheken verwalten und suche nach Adafruit BME280.
- Klickst du auf Installieren, wähle im Fenster mit den Abhängigkeiten Install all, damit auch Adafruit Unified Sensor und Adafruit BusIO installiert werden.
- Ist dein Sensor ein BMP280, installiere genauso die Bibliothek Adafruit BMP280; die BME280-Bibliothek erkennt den BMP280 nicht.
- Wenn du willst, öffne Datei > Beispiele > Adafruit BME280 Library > bme280test, aber vergiss nicht, die Adresse (0x76) in die begin()-Zeile zu schreiben.
Erster Sketch: Temperatur, Luftfeuchtigkeit und Luftdruck mit dem BME280 auslesen
1#include <Wire.h>
2#include <Adafruit_Sensor.h>
3#include <Adafruit_BME280.h>
4
5#define DENIZ_SEVIYESI_HPA 1013.25 // bugünkü deniz seviyesi basıncı / today's sea-level pressure
6
7Adafruit_BME280 bme;
8
9void setup() {
10 Serial.begin(9600);
11 // Önce 0x76, olmazsa 0x77 dene / try 0x76 first, then 0x77
12 if (!bme.begin(0x76) && !bme.begin(0x77)) {
13 Serial.println(F("BME280 bulunamadi! Kablolari ve adresi kontrol et."));
14 Serial.print(F("Chip ID: 0x"));
15 Serial.println(bme.sensorID(), HEX); // 0x58 ise bu bir BMP280 / 0x58 means BMP280
16 while (true) delay(10);
17 }
18 Serial.println(F("BME280 hazir"));
19}
20
21void loop() {
22 float sicaklik = bme.readTemperature(); // °C
23 float nem = bme.readHumidity(); // % bağıl nem / % relative humidity
24 float basinc = bme.readPressure() / 100.0F; // Pa -> hPa
25 float irtifa = bme.readAltitude(DENIZ_SEVIYESI_HPA); // metre / meters
26
27 Serial.print(F("Sicaklik: ")); Serial.print(sicaklik, 1); Serial.println(F(" C"));
28 Serial.print(F("Nem: ")); Serial.print(nem, 1); Serial.println(F(" %"));
29 Serial.print(F("Basinc: ")); Serial.print(basinc, 1); Serial.println(F(" hPa"));
30 Serial.print(F("Irtifa: ")); Serial.print(irtifa, 0); Serial.println(F(" m"));
31 Serial.println();
32 delay(2000);
33}| Funktion | Was sie tut |
|---|---|
| bme.begin(0x76) | Startet den Sensor; gibt true zurück, wenn an der Adresse ein Gerät antwortet und die Chip-ID 0x60 ist |
| readTemperature() | Temperatur, °C |
| readHumidity() | Relative Luftfeuchtigkeit, % |
| readPressure() | Luftdruck, Pa (durch 100 geteilt ergibt hPa) |
| readAltitude(P0) | Höhe bezogen auf den Luftdruck P0 (hPa) auf Meereshöhe, in Metern |
| seaLevelForAltitude(Höhe, P) | Luftdruck auf Meereshöhe aus einer bekannten Höhe, hPa |
| sensorID() | Die gelesene Chip-ID: 0x60 BME280, 0x58 BMP280 |
| setTemperatureCompensation(x) | Addiert x °C zu jeder Temperaturmessung; Feuchte und Druck werden entsprechend korrigiert |
Lädst du den Sketch hoch und öffnest den seriellen Monitor mit 9600 Baud, siehst du bei Raumbedingungen ungefähr 23,4 °C, 45 % Luftfeuchtigkeit und 1009,8 hPa. Der Luftdruck ändert sich langsam über Stunden; hauchst du den Sensor an, steigt die Feuchte innerhalb von Sekunden, berührst du ihn mit dem Finger, klettert die Temperatur. Standardmäßig misst die Bibliothek im Normal-Modus mit dem höchsten Oversampling (x16) ununterbrochen; für einen ersten Test ist das ideal, aber wie du unten siehst, liefert eine andere Einstellung bei Wettermessungen über lange Zeit genauere Werte.
Messmodi: Forced, Normal und die richtigen Einstellungen
Der BME280 hat drei Modi. Im Sleep-Modus misst er nicht und zieht 0,1 µA. Im Forced-Modus macht er eine einzige Messung und schläft dann wieder; für jeden neuen Wert rufst du takeForcedMeasurement() auf. Im Normal-Modus misst er selbstständig fortlaufend mit der eingestellten Standby-Zeit. Oversampling misst denselben Wert mehrmals und mittelt ihn, um das Rauschen zu senken, und der IIR-Filter glättet plötzliche Drucksprünge (eine zuschlagende Tür, ein Windstoß). Bosch empfiehlt im Datenblatt je nach Anwendung diese Einstellungen:
| Anwendung | Modus | Oversampling (Druck / Temperatur / Feuchte) | IIR-Filter | Mittlerer Strom |
|---|---|---|---|---|
| Wetterüberwachung | Forced, 1 Messung pro Minute | x1 / x1 / x1 | Aus | ≈ 0,16 µA |
| Feuchtemessung | Forced, 1 Messung pro Sekunde | Aus / x1 / x1 | Aus | ≈ 2,9 µA |
| Indoor-Navigation (Stockwerke, Aufzug) | Normal, 0,5 ms Standby | x16 / x2 / x1 | 16 | ≈ 633 µA |
Luftdruck auf Meereshöhe und Höhenberechnung
Der Luftdruck nimmt mit der Höhe ab, deshalb lässt sich die Höhe aus dem gemessenen Druck berechnen. Die Bibliothek nutzt diese barometrische Höhenformel: h = 44330 × (1 − (P / P0)^0,1903). Dabei ist P der gemessene Druck und P0 der aktuelle Luftdruck auf Meereshöhe (beide in hPa). Die Standardatmosphäre setzt P0 = 1013,25 hPa an, und in Meeresnähe entspricht 1 hPa Unterschied etwa 8,3 Metern.
Der Haken: P0 ist nicht konstant, sondern schwankt je nach Wetter grob zwischen 990 und 1035 hPa. Beträgt der echte Wert heute 1023 hPa und du lässt 1013,25 im Code stehen, zeigt der Sensor etwa 80 Meter zu wenig an. Für genaue Ergebnisse musst du P0 aktuell halten: Nimm den von Wetterdiensten angegebenen "auf Meereshöhe reduzierten Luftdruck" oder den Q-Wert aus dem METAR des nächsten Flughafens (zum Beispiel Q1018, also 1018 hPa). Es geht auch umgekehrt: Kennst du die Höhe deines Standorts, berechnest du P0 mit seaLevelForAltitude(Höhe, Druck). Misst der Sensor zum Beispiel in Ankara (etwa 938 m) 905 hPa, beträgt der auf Meereshöhe reduzierte Luftdruck etwa 1012,6 hPa, also genau die Zahl, die du in Wetter-Apps siehst.
Für die absolute Höhe bedeutet die absolute Genauigkeit von ±1 hPa eine Unsicherheit von etwa ±8 Metern. Bei relativen Messungen ist der Sensor aber viel besser: ±0,12 hPa ≈ ±1 m. Ein Stockwerk ist etwa 3 Meter hoch, also 0,36 hPa, deshalb erkennt der BME280 problemlos, in welchem Stock du bist oder ob ein Aufzug fährt. Der folgende Sketch nimmt beim Start den Mittelwert aus 20 Messungen als Referenz und gibt dann die Höhe relativ zu diesem Punkt sowie den aus einer bekannten Höhe berechneten Luftdruck auf Meereshöhe aus:
1#include <Wire.h>
2#include <Adafruit_Sensor.h>
3#include <Adafruit_BME280.h>
4
5#define BILINEN_IRTIFA 938.0 // bulunduğun yerin rakımı (m), örnek Ankara / your altitude (m), e.g. Ankara
6
7Adafruit_BME280 bme;
8float referansHpa; // açılıştaki basınç / pressure at start-up
9
10void setup() {
11 Serial.begin(9600);
12 if (!bme.begin(0x76)) {
13 Serial.println(F("BME280 bulunamadi!"));
14 while (true) delay(10);
15 }
16 // İç mekan navigasyonu ayarı: düşük gürültü / indoor navigation preset: low noise
17 bme.setSampling(Adafruit_BME280::MODE_NORMAL,
18 Adafruit_BME280::SAMPLING_X2, // sıcaklık / temperature
19 Adafruit_BME280::SAMPLING_X16, // basınç / pressure
20 Adafruit_BME280::SAMPLING_X1, // nem / humidity
21 Adafruit_BME280::FILTER_X16, // IIR filtre / IIR filter
22 Adafruit_BME280::STANDBY_MS_0_5);
23 delay(1000); // filtre otursun / let the filter settle
24
25 float toplam = 0;
26 for (int i = 0; i < 20; i++) { // 20 ölçümün ortalaması / average of 20 readings
27 toplam += bme.readPressure() / 100.0F;
28 delay(50);
29 }
30 referansHpa = toplam / 20;
31}
32
33void loop() {
34 float basinc = bme.readPressure() / 100.0F; // istasyon basıncı / station pressure
35 float denizSeviyesi = bme.seaLevelForAltitude(BILINEN_IRTIFA, basinc); // hPa
36 float bagilYukseklik = bme.readAltitude(referansHpa); // başlangıca göre / relative to start
37
38 Serial.print(F("Istasyon basinci: ")); Serial.print(basinc, 2); Serial.println(F(" hPa"));
39 Serial.print(F("Deniz seviyesi (QNH): ")); Serial.print(denizSeviyesi, 1); Serial.println(F(" hPa"));
40 Serial.print(F("Baslangica gore: ")); Serial.print(bagilYukseklik, 2); Serial.println(F(" m"));
41 Serial.println();
42 delay(1000);
43}Hebst du das Board vom Boden über deinen Kopf, steigt der Wert "Baslangica gore" (relativ zum Start) um etwa 2 Meter. Da sich der Luftdruck im Laufe des Tages um einige hPa ändert, driftet diese relative Messung nach ein paar Stunden; im Dauerbetrieb musst du die Referenz also gelegentlich erneuern. Noch ruhiger werden die Werte mit dem gleitenden Mittelwert aus dem Artikel Sensordaten filtern.
Mini-Wetterstation mit ESP32: eine Webseite, die du auf dem Handy öffnest
Dank des WLANs des ESP32 kannst du die BME280-Messwerte auf einer Webseite von jedem Handy oder Computer im selben Netz ansehen. Der Sketch unten nutzt die WebServer-Bibliothek, die mit dem ESP32-Core mitkommt, und braucht daher keine zusätzliche Bibliothek. Die Hauptseite lädt einmal, danach holt ein kleines JavaScript alle 5 Sekunden JSON von /veri und aktualisiert die Werte, ohne die Seite neu zu laden. Der Sensor läuft im Forced-Modus, misst also nur, wenn jemand die Seite anschaut, und der Luftdruck wird auf Meereshöhe reduziert angezeigt, damit du ihn mit Wettervorhersagen vergleichen kannst. Wenn du zum ersten Mal mit dem ESP32 arbeitest, lies zuerst Was ist der ESP32?.
- Schließe den BME280 wie in der Tabelle an: VCC an 3V3, SDA an GPIO 21, SCL an GPIO 22.
- Trag im Code bei WIFI_ADI (Netzwerkname) und WIFI_SIFRE (Passwort) deine WLAN-Daten ein und bei RAKIM_M die Höhe deines Standorts.
- Wähle als Board ESP32 Dev Module und lade den Sketch hoch.
- Öffne den seriellen Monitor mit 115200 Baud; sobald die Verbindung steht, erscheint die IP-Adresse.
- Gib diese Adresse (zum Beispiel 192.168.1.42) im Browser eines Handys im selben WLAN ein; Karten für Temperatur, Luftfeuchtigkeit und Luftdruck erscheinen.
1#include <WiFi.h>
2#include <WebServer.h>
3#include <Wire.h>
4#include <Adafruit_Sensor.h>
5#include <Adafruit_BME280.h>
6
7const char* WIFI_ADI = "WiFiAdin"; // kendi ağ adın / your network name
8const char* WIFI_SIFRE = "WiFiSifren"; // kendi şifren / your password
9const float RAKIM_M = 938.0; // bulunduğun yerin rakımı / your local altitude
10
11Adafruit_BME280 bme;
12WebServer server(80);
13
14// Telefonda açılan sayfa, 5 sn'de bir /veri'yi okur / phone page, reads /veri every 5 s
15const char SAYFA[] PROGMEM = R"rawliteral(
16<!DOCTYPE html><html><head><meta charset="utf-8">
17<meta name="viewport" content="width=device-width,initial-scale=1">
18<title>Mini Hava İstasyonu</title>
19<style>
20body{font-family:sans-serif;text-align:center;background:#0f172a;color:#e2e8f0;margin:0;padding:16px}
21.k{display:inline-block;min-width:140px;margin:8px;padding:16px;border-radius:14px;background:#1e293b}
22.d{font-size:2.2em;font-weight:bold;margin:6px 0}
23</style></head><body>
24<h2>Mini Hava İstasyonu</h2>
25<div class="k">Sıcaklık<div class="d" id="t">--</div>°C</div>
26<div class="k">Nem<div class="d" id="h">--</div>%</div>
27<div class="k">Basınç<div class="d" id="p">--</div>hPa</div>
28<script>
29async function guncelle() {
30 const v = await (await fetch('/veri')).json();
31 document.getElementById('t').textContent = v.t.toFixed(1);
32 document.getElementById('h').textContent = v.h.toFixed(0);
33 document.getElementById('p').textContent = v.p.toFixed(1);
34}
35guncelle();
36setInterval(guncelle, 5000);
37</script>
38</body></html>
39)rawliteral";
40
41void anaSayfa() {
42 server.send(200, "text/html", SAYFA);
43}
44
45void veriGonder() {
46 bme.takeForcedMeasurement(); // tek ölçüm al, sonra uyu / one measurement, then sleep
47 float p = bme.readPressure() / 100.0F;
48 String json = "{\"t\":" + String(bme.readTemperature(), 2) +
49 ",\"h\":" + String(bme.readHumidity(), 1) +
50 ",\"p\":" + String(bme.seaLevelForAltitude(RAKIM_M, p), 1) + "}";
51 server.send(200, "application/json", json);
52}
53
54void setup() {
55 Serial.begin(115200);
56 Wire.begin(21, 22); // SDA, SCL
57 if (!bme.begin(0x76)) {
58 Serial.println("BME280 bulunamadi!");
59 while (true) delay(10);
60 }
61 // Hava durumu izleme ayarı: kendi kendini ısıtmayı azaltır / weather monitoring preset: less self-heating
62 bme.setSampling(Adafruit_BME280::MODE_FORCED,
63 Adafruit_BME280::SAMPLING_X1, // sıcaklık / temperature
64 Adafruit_BME280::SAMPLING_X1, // basınç / pressure
65 Adafruit_BME280::SAMPLING_X1, // nem / humidity
66 Adafruit_BME280::FILTER_OFF);
67
68 WiFi.mode(WIFI_STA);
69 WiFi.begin(WIFI_ADI, WIFI_SIFRE);
70 while (WiFi.status() != WL_CONNECTED) {
71 delay(500);
72 Serial.print(".");
73 }
74 Serial.print("\nTarayicida ac / open in browser: http://");
75 Serial.println(WiFi.localIP());
76
77 server.on("/", anaSayfa);
78 server.on("/veri", veriGonder);
79 server.begin();
80}
81
82void loop() {
83 server.handleClient();
84}BME280 mit dem Raspberry Pi Pico (MicroPython)
MicroPython bringt kein fertiges Modul für den BME280 mit. Statt eine Treiberdatei herunterzuladen, enthält der Code unten einen kleinen Treiber: Er liest die Kalibrierkoeffizienten, lässt den Sensor im Forced-Modus eine einzelne Messung machen und berechnet das Ergebnis mit den Formeln aus dem Datenblatt. Da er die Chip-ID prüft, funktioniert er auch mit dem BMP280 und lässt die Feuchtezeile automatisch weg. Schließe den Sensor an GP4 (SDA), GP5 (SCL) und 3V3(OUT) an und speichere den Code in Thonny als main.py auf dem Pico. Ist der Pico neu für dich, helfen dir Was ist der Raspberry Pi Pico? und MicroPython-Grundlagen.
1from machine import Pin, I2C
2import struct, time
3
4i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
5ADR = 0x76 # olmazsa 0x77 dene / try 0x77 if it fails
6P0 = 1013.25 # deniz seviyesi basıncı (hPa) / sea-level pressure (hPa)
7
8def s8(x): # işaretli 8 bit / signed 8-bit
9 return x - 256 if x > 127 else x
10
11chip = i2c.readfrom_mem(ADR, 0xD0, 1)[0]
12BME = chip == 0x60 # 0x60 BME280, 0x58 BMP280
13print("Chip ID:", hex(chip), "BME280" if BME else "BMP280 (nem yok / no humidity)")
14
15# Fabrika kalibrasyon katsayıları / factory calibration coefficients
16T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9 = struct.unpack("<HhhHhhhhhhhh", i2c.readfrom_mem(ADR, 0x88, 24))
17if BME:
18 H1 = i2c.readfrom_mem(ADR, 0xA1, 1)[0]
19 e = i2c.readfrom_mem(ADR, 0xE1, 7)
20 H2 = struct.unpack("<h", e[0:2])[0]
21 H3 = e[2]
22 H4 = (s8(e[3]) << 4) | (e[4] & 0x0F)
23 H5 = (s8(e[5]) << 4) | (e[4] >> 4)
24 H6 = s8(e[6])
25 i2c.writeto_mem(ADR, 0xF2, b"\x01") # nem x1 (ctrl_meas'tan önce) / humidity x1 (before ctrl_meas)
26
27def oku():
28 i2c.writeto_mem(ADR, 0xF4, b"\x25") # sıcaklık x1, basınç x1, forced mod / temp x1, press x1, forced mode
29 time.sleep_ms(15) # ölçümün bitmesini bekle / wait for the measurement
30 d = i2c.readfrom_mem(ADR, 0xF7, 8 if BME else 6)
31 adc_p = (d[0] << 12) | (d[1] << 4) | (d[2] >> 4)
32 adc_t = (d[3] << 12) | (d[4] << 4) | (d[5] >> 4)
33
34 # Sıcaklık (datasheet formülü) / temperature (datasheet formula)
35 v1 = (adc_t / 16384 - T1 / 1024) * T2
36 v2 = (adc_t / 131072 - T1 / 8192) ** 2 * T3
37 t_fine = v1 + v2
38 t = t_fine / 5120
39
40 # Basınç, Pa / pressure, Pa
41 v1 = t_fine / 2 - 64000
42 v2 = v1 * v1 * P6 / 32768 + v1 * P5 * 2
43 v2 = v2 / 4 + P4 * 65536
44 v1 = (P3 * v1 * v1 / 524288 + P2 * v1) / 524288
45 v1 = (1 + v1 / 32768) * P1
46 p = 1048576 - adc_p
47 p = (p - v2 / 4096) * 6250 / v1
48 p = p + (P9 * p * p / 2147483648 + p * P8 / 32768 + P7) / 16
49
50 h = None
51 if BME: # nem, % / humidity, %
52 adc_h = (d[6] << 8) | d[7]
53 x = t_fine - 76800
54 x = (adc_h - (H4 * 64 + H5 / 16384 * x)) * (H2 / 65536 * (1 + H6 / 67108864 * x * (1 + H3 / 67108864 * x)))
55 x = x * (1 - H1 * x / 524288)
56 h = min(max(x, 0), 100)
57 return t, p / 100, h # °C, hPa, %
58
59while True:
60 t, p, h = oku()
61 irtifa = 44330 * (1 - (p / P0) ** 0.1903) # metre / meters
62 print("Sicaklik: %.1f C Basinc: %.1f hPa Irtifa: %.0f m" % (t, p, irtifa))
63 if h is not None:
64 print("Nem: %.1f %%" % h)
65 time.sleep(2)Ein paar Details im Code sind wichtig. Die Feuchte-Einstellung (Register 0xF2) wird erst nach einem Schreibzugriff auf 0xF4 wirksam, deshalb geht zuerst die Feuchte-Einstellung und danach der Messbefehl raus. Der Wert 0x25 in 0xF4 bedeutet "Temperatur x1, Druck x1, Forced-Modus"; mit diesen Einstellungen dauert eine Messung höchstens etwa 10 ms, also reichen 15 ms Wartezeit. Mit den Beispiel-Kalibrierwerten aus Boschs BMP280-Datenblatt getestet, liefert der Code 25,08 °C und 1006,5 hPa; die Berechnung stimmt also exakt mit Boschs Formeln überein.
Als BME280 verkaufter BMP280: Welcher Sensor ist es wirklich?
Weil beide Chips auf dasselbe Platinenlayout passen, verkaufen manche Händler BMP280-Module als BME280; manchmal steht auf dem Board nur "BME/BMP280". Das Symptom ist immer gleich: Die Bibliothek Adafruit BME280 meldet "Could not find a valid BME280 sensor, check wiring, address, sensor ID!" und direkt darunter SensorID was: 0x58. Andere Bibliotheken zeigen keinen Fehler, geben die Luftfeuchtigkeit aber immer als 0 oder nan aus. An deiner Verkabelung liegt es nicht; dein Chip ist ein BMP280, der keine Luftfeuchtigkeit misst.


- Schau dir die Form des Chips an: Ist der Metalldeckel quadratisch (2,5 × 2,5 mm), ist es ein BME280; ist er deutlich rechteckig (2,0 × 2,5 mm), ein BMP280. Mit dem Zoom der Handykamera ist der Unterschied gut zu erkennen.
- Lies die Chip-ID aus: Die zuverlässigste Methode ist der Sketch unten; er liest die Kennung im Register 0xD0 des Chips und sagt dir, welcher Sensor es ist.
- Achte auf den Preis: Ein echter BME280 kostet deutlich mehr als ein BMP280; sei misstrauisch bei "BME280"-Modulen, die weit unter dem Marktpreis verkauft werden.
1#include <Wire.h>
2
3void setup() {
4 Serial.begin(9600);
5 Wire.begin();
6 bool bulundu = false;
7
8 for (uint8_t adres = 0x76; adres <= 0x77; adres++) {
9 Wire.beginTransmission(adres);
10 if (Wire.endTransmission() != 0) continue; // bu adreste cihaz yok / no device at this address
11
12 Wire.beginTransmission(adres);
13 Wire.write(0xD0); // chip ID register'ı / chip ID register
14 Wire.endTransmission();
15 Wire.requestFrom(adres, (uint8_t)1);
16 uint8_t id = Wire.read();
17 bulundu = true;
18
19 Serial.print(F("Adres 0x"));
20 Serial.print(adres, HEX);
21 Serial.print(F(" Chip ID 0x"));
22 Serial.print(id, HEX);
23 if (id == 0x60) Serial.println(F(" -> BME280 (sicaklik + nem + basinc)"));
24 else if (id >= 0x56 && id <= 0x58) Serial.println(F(" -> BMP280 (nem olcmez)"));
25 else if (id == 0x61) Serial.println(F(" -> BME680 / BME688"));
26 else if (id == 0x55) Serial.println(F(" -> BMP180"));
27 else Serial.println(F(" -> bilinmeyen yonga / unknown chip"));
28 }
29
30 if (!bulundu) Serial.println(F("0x76 ve 0x77'de sensor yok: kablolari kontrol et"));
31}
32
33void loop() {
34}Kommt 0x58 heraus, kein Grund zur Sorge: Temperatur- und Druckmessung des BMP280 sind genauso gut wie beim BME280. Installiere die Bibliothek Adafruit BMP280 und nimm den Sketch unten; brauchst du die Luftfeuchtigkeit, ergänze einen separaten DHT22 oder schick das Produkt zurück. Gelegentlich tauchen auch BMP280-Muster mit der ID 0x56 oder 0x57 auf; für sie schreibst du die begin-Zeile als bmp.begin(0x76, 0x56).
1#include <Wire.h>
2#include <Adafruit_BMP280.h>
3
4Adafruit_BMP280 bmp;
5
6void setup() {
7 Serial.begin(9600);
8 if (!bmp.begin(0x76) && !bmp.begin(0x77)) {
9 Serial.println(F("BMP280 bulunamadi! Kablolari ve adresi kontrol et."));
10 while (true) delay(10);
11 }
12 // Datasheet'in önerdiği varsayılan ayarlar / default settings from the datasheet
13 bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,
14 Adafruit_BMP280::SAMPLING_X2, // sıcaklık / temperature
15 Adafruit_BMP280::SAMPLING_X16, // basınç / pressure
16 Adafruit_BMP280::FILTER_X16, // IIR filtre / IIR filter
17 Adafruit_BMP280::STANDBY_MS_500); // bekleme süresi / standby time
18}
19
20void loop() {
21 Serial.print(F("Sicaklik: ")); Serial.print(bmp.readTemperature(), 1); Serial.println(F(" C"));
22 Serial.print(F("Basinc: ")); Serial.print(bmp.readPressure() / 100.0F, 1); Serial.println(F(" hPa"));
23 Serial.print(F("Irtifa: ")); Serial.print(bmp.readAltitude(1013.25), 0); Serial.println(F(" m"));
24 Serial.println();
25 delay(2000);
26}Projektideen mit dem BME280
- Wetterstation für den Schreibtisch: Zeig Temperatur, Luftfeuchtigkeit und Luftdruck auf einem OLED-Display oder einem I2C-LCD am selben I2C-Bus.
- Wettervorhersage per Barometer: Speichere den Luftdruck jede Stunde; ein Abfall um mehr als 2 hPa in 3 Stunden kündigt meist schlechteres Wetter an, ein stetiger Anstieg dagegen klares Wetter.
- Taupunkt und Schimmelwarnung: Berechne den Taupunkt mit der Magnus-Formel (a = 17,62, b = 243,12 °C) und gib eine Warnung aus, wenn sich die Wandtemperatur ihm nähert.
- Smartes Gewächshaus: Steuere einen Lüfter oder eine Sprühpumpe nach Feuchte und Temperatur; Details im Artikel Smartes Gewächshaus mit Arduino.
- Datenlogger: Schreib die Messwerte auf ein SD-Kartenmodul oder mit dem ESP32 in Google Tabellen und erstelle ein Wochendiagramm.
- Smart-Home-Sensor: Schick die Werte mit einem ESP32 per MQTT an Home Assistant.
- Batteriebetriebene Außenstation: Weck den ESP32 alle 10 Minuten aus dem Deep Sleep; der BME280 zieht im Schlaf nur 0,1 µA.
- Stockwerkzähler: Zeig mit dem Sketch für die relative Höhe an, in welchem Stock du im Aufzug oder im Treppenhaus angekommen bist.
Häufige Fehler und ihre Lösungen
| Symptom | Mögliche Ursache | Lösung |
|---|---|---|
| "Could not find a valid BME280 sensor", SensorID 0x0 oder 0xFF | Falsche Adresse oder Verdrahtungsfehler | begin(0x76) verwenden, prüfen, ob SDA und SCL vertauscht sind und GND angeschlossen ist, I2C-Scanner laufen lassen |
| Gleicher Fehler, SensorID 0x58 | Der Chip ist in Wahrheit ein BMP280 | Bibliothek Adafruit BMP280 verwenden, für die Feuchte einen eigenen Sensor ergänzen |
| fatal error: Adafruit_Sensor.h: No such file or directory | Abhängige Bibliothek fehlt | Bibliothek Adafruit Unified Sensor installieren |
| Werte sind nan | Im Forced-Modus keine neue Messung angefordert oder begin() fehlgeschlagen | Vor jedem Auslesen takeForcedMeasurement() aufrufen, Rückgabewert von begin() prüfen |
| Temperatur 1–3 °C zu hoch | Eigenerwärmung durch Dauermessung, Wärme eines nahen ESP32 oder Reglers | In den Forced-Modus wechseln, Sensor vom Board absetzen, bei Bedarf setTemperatureCompensation() nutzen |
| Luftdruck nur etwa 900 hPa | Das ist der Stationsdruck; er sinkt mit steigender Höhe | Zum Vergleich mit Vorhersagen mit seaLevelForAltitude() auf Meereshöhe umrechnen |
| Höhe um Dutzende Meter falsch | Luftdruck auf Meereshöhe bei 1013,25 belassen | Aktuellen P0-Wert (QNH) eintragen oder mit bekannter Höhe kalibrieren |
| Zufällige Hänger bei langen Kabeln | Der I2C-Bus ist lang und gestört | Kabel unter 50 cm halten, I2C-Takt senken oder SPI verwenden |
Der BME280 erledigt auf einem kleinen Board alle Grundmessungen einer Wetterstation: Prüf zuerst Adresse und Chip-ID, wähl dann den Messmodus passend zu deinem Ziel und halte für die Höhe den Luftdruck auf Meereshöhe aktuell. In der BlueGrays-App findest du Projekte, die du mit diesem Artikel kombinieren kannst, etwa Temperatur- und Feuchtemessung mit DHT11 und DHT22, ESP32-Wetteranzeigen, einen Temperaturlogger und einen ESP32-Webserver, jeweils mit Schaltplänen und Code Schritt für Schritt.
Häufige Fragen
Was ist der Unterschied zwischen BME280 und BMP280?
Der BME280 misst Temperatur, relative Luftfeuchtigkeit und Luftdruck; der BMP280 misst nur Temperatur und Luftdruck und hat keinen Feuchtesensor. Druck- und Temperaturgenauigkeit sind gleich. Auch die Chips unterscheiden sich: Der BME280 ist quadratisch (2,5 × 2,5 mm), der BMP280 rechteckig (2,0 × 2,5 mm), und ihre Chip-IDs lauten 0x60 und 0x58.
Ist die I2C-Adresse des BME280 0x76 oder 0x77?
Sie ist 0x76, wenn der SDO-Pin an GND liegt, und 0x77, wenn er an 3,3 V liegt. Die meisten günstigen Module nutzen 0x76, Adafruit-Boards 0x77. Die Adafruit-Bibliothek probiert standardmäßig 0x77, deshalb musst du eventuell bme.begin(0x76) in den Code schreiben; im Zweifel lässt du einen I2C-Scanner laufen.
Funktioniert der BME280 mit 5 V?
Der Chip selbst verträgt höchstens 3,6 V. Die meisten 4-poligen Module mit VIN-Pin haben einen Regler und dürfen an 5V. 6-polige 3,3-V-Module ohne Regler versorgst du nur mit 3,3 V; 5 V können den Sensor beschädigen.
Wie behebe ich "Could not find a valid BME280 sensor"?
Schau zuerst auf den SensorID-Wert unter der Fehlermeldung. Bei 0x58 ist dein Sensor ein BMP280, und du brauchst die Bibliothek Adafruit BMP280. Bei 0x0 oder 0xFF liegt ein Adress- oder Verdrahtungsproblem vor: Versuch begin(0x76) und stell sicher, dass SDA und SCL nicht vertauscht sind und der CSB-Pin an 3,3 V liegt.
Wie genau misst der BME280 die Höhe?
Relative Höhenänderungen misst er auf etwa ±1 m genau, was reicht, um einen Stockwerkwechsel zu erkennen. Die absolute Höhe hängt vom eingegebenen Luftdruck auf Meereshöhe ab; ein Fehler von 1 hPa verschiebt das Ergebnis um etwa 8 m. Mit dem aktuellen QNH-Wert oder einer Kalibrierung auf eine bekannte Höhe kommst du auf wenige Meter heran.
Warum zeigt mein BME280 eine zu hohe Temperatur?
Die häufigsten Ursachen sind Eigenerwärmung durch Dauermessung und die Wärme naher Bauteile wie ESP32 oder Spannungsregler. Wechsle in den Forced-Modus, miss ein paarmal pro Minute und setz den Sensor per Kabel vom Board ab. Bleibt ein fester Versatz, vergleich mit einem zuverlässigen Thermometer und korrigiere ihn mit setTemperatureCompensation().
Projekte, die du danach bauen kannst
Alle Projekte ansehen
Temperatur und Luftfeuchtigkeit mit DHT11
Wie warm ist dein Zimmer, und ist die Luft feucht oder trocken? Der DHT11-Sensor misst Temperatur und Luftfeuchtigkeit, und der Arduino schreibt die Werte auf ein zweizeiliges LCD und aktualisiert sie

ESP32 DHT22 Temperatur und Luftfeuchtigkeit (mit LCD-Display)
Bei diesem Projekt werden die Umgebungstemperatur und die Luftfeuchtigkeit mit einem DHT22-Sensor gemessen und in Echtzeit auf einem 16x2 I2C-LCD angezeigt. Mithilfe der Adafruit-DHT-Bibliothek werden die Daten über das One-Wire-Protokoll vom Sensor ausgelesen. Dieses Projekt bildet die Grundlage für IoT-Wetterstationen, Smart-Home-Automatisierung oder Umgebungsüberwachungssysteme in Gewächshäusern. Die Kommunikation mit dem DHT22 erfolgt über den GPIO-4-Pin des ESP32.

Punktmatrix-Uhr, Kalender und Wetterstation (MAX7219, DS1307)
Eine Laufschrift-Tafel für Tisch oder Wand, die abwechselnd Uhrzeit, Datum und das Raumklima zeigt. Auf dem 8x32-LED-Display erscheint zuerst die Temperatur in Celsius und Fahrenheit, dann die Luftfeu

ESP32 Temperatur-Datenlogger (DHT22 + DS1307 RTC + microSD + OLED)
Baue einen zeitgestempelten Temperaturlogger mit ESP32! Lese Temperatur/Feuchtigkeit vom DHT22 jede Minute, hole die aktuelle Zeit vom DS1307 RTC und protokolliere auf microSD-Karte als CSV. Das OLED zeigt live Temperatur (große Schrift), Luftfeuchtigkeit, Zeitstempel und Logzähler. Die `/temp_log.csv`-Datei auf der SD-Karte öffnet sich in Excel, Google Sheets oder Python pandas zur Analyse — perfekt für Gewächshausüberwachung, Raumtemperaturverfolgung, Laboraufzeichnung, Lebensmittellageru

ESP32 HTTPClient + Wetter-API (mit SSD1306-OLED-Display)
In diesem Projekt führen wir mit dem ESP32 über das Internet mithilfe von `HTTPClient.h` einen REST-API-Aufruf an die Wetter-API (wttr.in) durch. Im Gegensatz zur vorherigen I2C-LCD-Version verwenden wir hier ein SSD1306-OLED-Display (128×64) – dies ermöglicht große Schriftarten, Vektor-Symbole und eine reichhaltige visuelle Darstellung auf einem einzigen Bildschirm. Für die Wetteranzeige werden 7 verschiedene Vektor-Symbole (sonnig, teilweise bewölkt, bewölkt, regnerisch, schneereich, stürmisch

ESP32 Async-Webserver (mit IP-Anzeige auf dem LCD)
In diesem Projekt verwandeln wir den ESP32 in einen **asynchronen Webserver**, den Sie über Ihr Smartphone oder Ihren Computer im selben WLAN-Netzwerk steuern können. Dank der ESPAsyncWebServer-Bibliothek kann der Server mehrere Anfragen gleichzeitig bearbeiten (im Gegensatz zum klassischen `WebServer.h`, der bei einer einzigen Anfrage blockiert). Sie können über den Browser die IP-Adresse des ESP32 öffnen und durch Drücken der ON/OFF-Schaltflächen (Routen `/on` und `/off`) die an GPIO 5 anges

ESP32 HTTPClient + Wetter-API (mit LCD-Display)
In diesem Projekt führen wir mit dem ESP32 über das Internet mithilfe von `HTTPClient.h` einen REST-API-Aufruf an die Wetter-API (wttr.in) durch. Mit ArduinoJson v7 analysieren wir die zurückgegebenen JSON-Daten und zeigen Informationen zu Stadt, Temperatur, Luftfeuchtigkeit, Wetter und Wind sowohl auf Türkisch als auch auf Englisch auf einem I2C-LCD-Display an. wttr.in ist kostenlos und erfordert keinen API-Schlüssel – Sie können den aktuellen Wetterbericht einer beliebigen Stadt abrufen, indem

ESP32 I2C-LCD-Display (16×2)
In diesem Projekt zeigen wir Text an, indem wir ein 16x2-Zeichen-LCD-Display über das I2C-Protokoll an den ESP32 anschließen. Dank I2C können wir das Display mit nur zwei Datenpins (SDA und SCL) steuern; die Verschwendung von 6+ Pins bei einer klassischen parallelen Verbindung entfällt. Der Code schreibt in die erste Zeile eine feste Meldung und in die zweite Zeile einen Zähler, der sich jede Sekunde erhöht. Außerdem lassen wir zu Beginn den I2C-Scanner laufen und geben die Adresse des Displays
Weitere Artikel
BlueGrays-App
Diese Schaltung Schritt für Schritt auf dem Handy nachbauen
Schaltplan, Code und Teileliste auf einem Bildschirm. Über 160 Arduino-, ESP32- und Pico-Projekte zum Nachbauen.
Mit dem Handy scannen
Richte die Kamera auf den Code, dann öffnet sich der App-Store deines Handys.
oder im Store öffnen

