Wet­ter­sta­ti­on mit UNO R4 WiFi und BME280

Lese­zeit: 8 Minu­ten

Lösung
Seite als PDF

Die Hard­ware

Der Sen­sor BME280 misst Tem­pe­ra­tur, Luft­feuch­tig­keit und Luft­druck. Der Luft­druck kann ver­wen­det wer­den, um die unge­fäh­re Höhe des Stand­orts zu berechnen. 

BME280 mit QWIIC-Anschluss

Der Ardui­no UNO R4 WiFi ver­fügt über ein WiFi-Modul und über einen QWI­IC-Anschluss.
Die­ser Anschluss wur­de von Spark­fun ent­wi­ckelt und fasst die Anschlüs­se für 3,3 V, GND, SCL und SDA in einem Ste­cker zusam­men. Selbst­ver­ständ­lich kann für die­se Anlei­tung auch das Modul mit vier sepa­ra­ten Anschlüs­sen ver­wen­det werden.

QWI­IC-Anschluss am UNO R4 WiFi

Die Schal­tung

Ardui­no R4 WiFi mit BME280 am QWIIC-Anschluss
Ardui­no R4 WiFi Betrieb mit einem Batteriepack

Vor­be­rei­tung

Zunächst musst du über den Board­ver­wal­ter das Board installieren:

Wenn das Board ange­schlos­sen ist, kann der USB-Anschluss aus­ge­wählt wer­den. Der Name des Anschlus­ses unter­schie­det sich je nach ver­wen­de­tem Betriebssystem.

Linux
Win­dows

Wet­ter­sta­ti­on im Seri­el­len Monitor

I2C-Bus­sys­te­me

Der UNO R4 Wifi ver­fügt über zwei I2C-Bussysteme:

  • den ers­ten I2C-Bus, er wird über vier Lei­tungs­dräh­te (3,3V, GND, SCL und SDA) ange­schlos­sen (Wire)
  • den zwei­ten I2C-Bus, er wird über QWIIC ver­bun­den (Wire1)

Ein Test­pro­gramm zeigt die ver­wen­de­te Adres­se an. Wenn du den ers­ten I2C-Bus abfra­gen willst, musst du jeweils Wire1 durch Wire ersetzen.

Das dazu­ge­hö­ri­ge Pro­gramm. Wenn du den ers­ten I2C-Bus abfra­gen willst, musst du jeweils Wire1 durch Wire ersetzen.

#include "Wire.h"

void setup()
{
  // Wire1 → QWICC
  Wire1.begin();
  Serial.begin(9600);
  delay(500);
  Serial.print("I2C Scanner QWIIC");
}

void loop()
{
  byte Fehler, Adresse;
  int Geraete = 0;
  Serial.println("Starte Scanvorgang");

  for (Adresse = 1; Adresse < 127; Adresse++ )
  {
    // Übertragung starten
    Wire1.beginTransmission(Adresse);

    // wenn die Übertragung beendet wird
    Fehler = Wire1.endTransmission();

    if (Fehler == 0)
    {
      Serial.print("I2C Gerät gefunden - Adresse: 0x");
      if (Adresse < 16) Serial.print("0");
      Serial.print(Adresse, HEX);
      Serial.println("");
      Geraete++;
    }
  }
  if (Geraete == 0) Serial.println("Keine I2C Geräte gefunden\n");
  else Serial.println("Scanvorgang abgeschlossen");

  delay(10000);
}

Benö­tig­te Bibliothek

Funk­tio­nen der Biblio­thek BME280

Schlüs­sel­wortAkti­on
begin()BME280 star­ten
read­Tem­pe­ra­tu­re()Tem­pe­ra­tur messen
read­Hu­mi­di­ty()Luft­feuch­tig­keit messen
read­Pres­su­re()Luft­druck messen
readAltitude(LuftdruckMeeresHoehe)Höhe ermit­teln

Das Pro­gramm

Das Pro­gramm ermit­telt die Mess­wer­te für die Tem­pe­ra­tur, Luft­feuch­tig­keit, Luft­druck und die unge­fäh­re Höhe. Die­se wird aus der Gewichts­kraft der Luft­säu­le, die auf einem Gegen­stand steht, berech­net. Der Luft­druck auf Mee­res­hö­he beträgt 1013,25 Hek­to­p­as­cal (hPa). Je höher der Ort der Mes­sung, des­to nied­ri­ger ist der Luftdruck.

So sieht es aus:

#include "Wire.h"
#include "SPI.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"

// Luftdruck auf Meereshöhe
#define LuftdruckMeeresHoehe (1013.25)

// Name des Sensors
Adafruit_BME280 bme;

int Wartezeit = 5000;

void setup() 
{
  Serial.begin(9600);
  while (!Serial);
  delay(1000);
  
  // I2C über SCL/SDA oder A5/A4
  // if (!bme.begin()

  // I2C über QWIIC-Verbindung
  // Adresse und Wire1-Bus
  if (!bme.begin(0x77, &Wire1)) 
  {
    Serial.println("Kein BME280-Modul gefunden");
    while (true)
      ;
  } 
  else Serial.println("BME280-Modul gefunden");

  Serial.println();
}

void loop() 
{
  String Temperatur = String(bme.readTemperature());
  Temperatur.replace(".", ",");
  Serial.println("Temperatur: " + Temperatur + " °C");

  String Luftfeuchtigkeit = String(bme.readHumidity());
  Luftfeuchtigkeit.replace(".", ",");
  Serial.println("Luftfeuchtigkeit: " + Luftfeuchtigkeit + " %");

  String Luftdruck = String(bme.readPressure() / 100.0);
  Luftdruck.replace(".", ",");
  Serial.println("Luftdruck: " + Luftdruck + " hPa");

  String Hoehe = String(bme.readAltitude(LuftdruckMeeresHoehe));
  Hoehe.replace(".", ",");
  Serial.println("Ungefähre Höhe: " + Hoehe + " m");

  Serial.println();
  delay(Wartezeit);
}

Wet­ter­sta­ti­on im Brow­ser anzeigen

Jetzt sol­len die gemes­se­nen Daten, Datum und Zeit in einem Brow­ser ange­zeigt wer­den.

So sieht es aus:

Das Pro­gramm

Zusätz­lich benö­tig­te Bibliothek

Im Seri­el­len Moni­tor wird die ver­wen­de­te IP-Adres­se ange­zeigt. Die­se Adres­se musst du in einem Brow­ser dei­ner Wahl eingeben.

Biblio­the­ken und Variable

#include "Wire.h"
#include "SPI.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"
#include "WiFiS3.h"
#include "NTP.h"

// Luftdruck auf Meereshöhe
#define LuftdruckMeeresHoehe (1013.25)

// Name des BME280
Adafruit_BME280 bme;

// SSID und Passwort des Routers
char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";

WiFiServer WiFiServer(80);

WiFiClient WiFiClient;
WiFiUDP wifiUdp;
NTP ntp(wifiUdp);

Der set­up-Teil

void setup() 
{
  Serial.begin(9600);
  while (!Serial);
  delay(1000);

  // Verbindung aufbauen
  WiFi.begin(Router, Passwort);

  while(WiFi.status() != WL_CONNECTED)
  {
    delay(500); 
    Serial.print(".");
  }

  Serial.print("Verbindung aufbauen mit ");
  Serial.println(Router);
  

  // Webserver starten
  WiFiServer.begin();

  // IP des Servers/des verbundenen Computers anzeigen
  Serial.print("Server: ");
  Serial.println(WiFi.SSID());

  // IP des Arduinos anzeigen
  Serial.print("IP Adresse Arduino DHCP: ");
  Serial.println(WiFi.localIP());

  /*
    Zeitzone
    CEST: Central European Summertime
    Beginn europäische Sommerzeit letzter Sonntag im März 2 Uhr GMT + 2 Stunden
  */
  ntp.ruleDST("CEST", Last, Sun, Mar, 2, 120);

  // CET: Central European Time
  // Beginn Normalzeit letzter Sonntag im Oktober 3 Uhr GMT + 1 Stunde
  ntp.ruleSTD("CET", Last, Sun, Oct, 3, 60);

  // ntp starten
  ntp.begin();

  // Zeit aktualisieren
  ntp.update();

  // Zeit mit formatedTime() anzeigen:
  // %d = Tag, %m = Monat, %Y = Jahr, %T = Zeit in Stunden, Minuten, Sekunden
  Serial.println(ntp.formattedTime("%d.%m.%Y Uhrzeit: %T"));

  // I2C über SCL/SDA oder A5/A4
  // if (!bme.begin()

  // I2C über QWIIC-Verbindung
  // Adresse und Wire1-Bus
  if (!bme.begin(0x77, &Wire1)) 
  {
    Serial.println("Kein BME280-Modul gefunden");
    while (true);
  } 
  else Serial.println("BME280-Modul gefunden");

  Serial.println();
}

Der loop-Teil

void loop() 
{
  WiFiClient = WiFiServer.available();

  if (WiFiClient) {
    // Seite aufbauen wenn SeiteAufbauen true ist
    boolean SeiteAufbauen = true;

    while (WiFiClient.connected()) 
    {
      if (WiFiClient.available()) 
      {
        char Zeichen = WiFiClient.read();
        if (Zeichen == '\n' && SeiteAufbauen) 
        {
          // HTTP-Anforderung senden
          WiFiClient.println("HTTP/1.1 200 OK");
          WiFiClient.println("Content-Type: text/html");

          // Leerzeile zwingend erforderlich
          WiFiClient.println();

          /*
            HTML-Seite aufbauen
            die folgenden Anweisungen müssen mit print oder println gesendet werden
            println "verschönert" den Quelltext
            " muss mit \" maskiert werden
          */
          WiFiClient.println("<!doctype html>");
          WiFiClient.println("<html>");
          WiFiClient.println("<body>");

          // alle 60 Sekunden aktualisieren mit meta-Tag
          WiFiClient.println("<meta http-equiv=\"refresh\" content=\"60\">");
          WiFiClient.println("<h1> Temperatur und Luftfeuchtigkeit messen</h1>");
          WiFiClient.println("<hr />");
          WiFiClient.print("<h2>Letzte Messung: ");
      
         // Zeit aktualisieren
         ntp.update();

          // formatedTime() zeigt Wochentage in englischer Sprache
          // -> müssen einzeln abgefragt werden
          switch (ntp.weekDay()) 
          {
            case 0:
              WiFiClient.print("Sonntag");
              break;
            case 1:
              WiFiClient.print("Montag");
              break;
            case 2:
              WiFiClient.print("Dienstag");
              break;
            case 3:
              WiFiClient.print("Mittwoch");
              break;
            case 4:
              WiFiClient.print("Donnerstag");
              break;
            case 5:
              WiFiClient.print("Freitag");
              break;
            case 6:
              WiFiClient.print("Samstag");
              break;
          }
          WiFiClient.print(", ");
          WiFiClient.print(ntp.formattedTime("%d.%m.%Y Uhrzeit: %T"));

          WiFiClient.println("</h2>");
          WiFiClient.println("<hr />");

          // Temperatur
          String Temperatur = String(bme.readTemperature());
          Temperatur.replace(".", ",");
          WiFiClient.print("<b>Temperatur:</b><blockquote>");
          WiFiClient.println(Temperatur + " &deg;C</blockquote>");
          WiFiClient.println("<br>");

          // Luftfeuchtigkeit
          String Luftfeuchtigkeit = String(bme.readHumidity());
          Luftfeuchtigkeit.replace(".", ",");
          WiFiClient.print("<b>Luftfeuchtigkeit:</b><blockquote>");
          WiFiClient.println(Luftfeuchtigkeit + " %</blockquote>");
          WiFiClient.println("<br>");

          // Luftdruck
          String Luftdruck = String(bme.readPressure() / 100);
          Luftdruck.replace(".", ",");
          WiFiClient.print("<b>Luftdruck:</b><blockquote>");
          WiFiClient.println(Luftdruck + " hPa</blockquote>");
          WiFiClient.println("<br>");

          // Höhe
          String Hoehe = String(bme.readAltitude(LuftdruckMeeresHoehe));
          Hoehe.replace(".", ",");
          WiFiClient.println("<b>Ungef&auml;hre H&ouml;he:</b><blockquote>");

          WiFiClient.println(Hoehe + " m</blockquote>");
          WiFiClient.println("<hr>");

          WiFiClient.println("<form>");

          // Button formatieren
          WiFiClient.print("<input style=\"font-size:16pt; font-weight:bold;");
          WiFiClient.print("background-color:#55A96B;");
          WiFiClient.print("display:block; cursor:pointer;\"type=\"button\"");
          WiFiClient.println(" onClick=\"location.href='WiFi.localIP()'\" value=\"aktualisieren\">");
          WiFiClient.println("</form>");
          WiFiClient.println("<hr />");

          // IPs anzeigen
          WiFiClient.print(F("<b>Eigene IP: "));
          WiFiClient.print(WiFiClient.remoteIP());
          WiFiClient.print(F("</b>"));
          WiFiClient.print(F("<br><b>IP Klient: "));
          WiFiClient.print(WiFi.localIP());
          WiFiClient.print(F("</b>"));
          WiFiClient.println("</b>");
          WiFiClient.println("</body>");
          WiFiClient.print("</html>");

          // HTTP-Antwort endet mit neuer Zeile
          WiFiClient.println();

          // Seite vollständig geladen -> loop verlassen
          break;
        }

        if (Zeichen == '\n') SeiteAufbauen = true;
        else if (Zeichen != '\r') SeiteAufbauen = false;
      }
    }
    delay(1);

    // Seitenaufbau stoppen
    WiFiClient.stop();
  }
}

Startseite
Aufgaben A-Z
Suchen
Downloads
Fehlermeldungen
Seite als PDF

Letzte Aktualisierung: 4. Okt 2023 @ 10:12