DHT11/DHT22 - Wet­ter­da­ten aufzeichnen

Lese­zeit: 6 Minu­ten

Lösung
Seite als PDF

Das Pro­gramm soll die Wet­ter­da­ten im Seri­el­len Moni­tor anzei­gen und gleich­zei­tig auf einer SD-Kar­te im CSV-For­mat auf­zeich­nen.
Die­se Datei kann dann von einer Tabel­len­kal­ku­la­ti­on geöff­net werden.

So soll es aussehen:

Benö­tig­te Bauteile:

  • RTC-Modul DS3231
  • Tem­pe­ra­tur-/Feuch­tig­keits­sen­sor DHT11 oder DHT22
  • SD-Kar­ten-Modul (Daten­log­ger-Shield oder Ethernet-Shield)
  • Lei­tungs­dräh­te

Wenn du ein ➨Ether­net-Shield hast, kannst du das Pro­gramm ohne Ände­rung mit dem dort ver­bau­ten SD-Kar­ten-Modul ver­wen­den.
Mit einem ➨Daten­log­ger-Shield musst du den Wert für den Daten­pin auf 10 setzen.

Bei­spie­le für DHT11/DHT22 Sensoren

Die Pin­be­le­gung kann sich von der hier gezeig­ten unter­schei­den. Ach­te auf die Beschrif­tung auf dem Modul!

Beach­te die Pin­be­le­gung!
Die SD-Kar­te muss mit FAT32 for­ma­tiert sein!

RTC-Modul

SD-Kar­ten-Modul

Baue die Schal­tung auf.
(Fah­re mit der Maus über das Bild, um die Bezeich­nun­gen der Bau­tei­le zu sehen)

Je grö­ßer die Pro­gram­me wer­den, je mehr Varia­ble ver­wen­det wer­den, des­to grö­ßer ist der Spei­cher­be­darf im RAM. Über­steigt er die Gren­ze von 75%, wird eine War­nung ausgegeben.

Der phy­si­sche Spei­cher des UNO R3 kann nicht ver­grö­ßert wer­den, es gib aber Stra­te­gien, den Spei­cher­be­darf des Pro­gramms zu ver­rin­gern. Eine soll hier vor­ge­stellt werden.

Der Ardui­no UNO R3 ver­fügt über drei Speicherplätze:

Spei­cherBeschrei­bung
Flash 32 KB
(32256 Bytes)
5 kB sind für den Boot­loa­der reser­viert, der Rest kann für das Pro­gramm ver­wen­det werden
der gespei­cher­te Inhalt bleibt nach dem Aus­schal­ten erhalten

SRAM 2 KB
(2048 Bytes)
(sta­tic ran­dom access memo­ry) hier wer­den die Variablen/Arrays erstellt und verändert
der Inhalt wird beim Aus­schal­ten gelöscht
EEPROM 1 KB
(1024 Bytes)
der Inhalt wird beim Aus­schal­ten gelöscht
hier kön­nen Infor­ma­tio­nen gespei­chert wer­den, die auch nach dem Aus­sch noch zur Ver­fü­gung ste­hen sollen

Spei­cher­aus­stat­tung ver­schie­de­ner Arduinos

In den meis­ten Pro­gram­men wer­den print-Anwei­sun­gen aus­ge­führt. Jede die­ser Anwei­sun­gen belegt Spei­cher­platz im Pro­gramm­spei­cher. Da es sich aber nicht um Varia­ble han­delt, ist die dau­er­haf­te Spei­che­rung nicht notwendig.

Das ➨ F-Makro sorgt dafür, dass der Text nicht im Pro­gramm­spei­cher ver­bleibt, er wird viel­mehr im SRAM abge­legt und stellt so Spei­cher­platz im Pro­gramm­spei­cher zur Verfügung.

Bei­spie­le:

Serial.println(F("Initialisierung abge­schlos­sen"));
Serial.println(F("Schreibe Mess­da­ten in die Datei Messung.csv: "));
Serial.println(F("-----------------------------------"));

Sketch → Biblio­thek ein­bin­den → Biblio­the­ken verwalten

Im Kopf des Pro­gramms wer­den die benö­tig­ten Biblio­the­ken ein­ge­bun­den und die Varia­blen defi­niert.
Beach­te die Kommentare:

# include "SdFat.h"
# include "DHT.h"

// Bezeichnung der SD-Karte
SdFat SD;

// Pin des DHT-Sensors
int SENSOR_DHT = 8;

// Sensortyp festlegen
// DHT22 oder DHT11
# define SensorTyp DHT11

// Sensor DHT einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

// Bibliothek für das RTC-Modul
# include <RTClib.h>
RTC_DS3231 rtc;

// Bezeichnung der Textdatei
File Temperaturmessung;

// Datenpin für das SD-Kartenmodul/Ethernet-Shield
int DatenPin = 4;

// Datenpin für das Datenlogger-Shield
// int DatenPin = 10;


String AktuellesDatum;
String AktuelleZeit;

Der set­up-Teil initia­li­siert die SD-Kar­te, star­tet das RTC-Modul und legt den pin­Mo­de für den Sen­sor fest.

void setup()
{
  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial) {;}
  Serial.println(F("Initialisiere SD-Karte"));
  if (!SD.begin(DatenPin))
  {
    Serial.println(F("Initialisierung fehlgeschlagen!"));
  }
  else Serial.println(F("Initialisierung abgeschlossen"));

  // rtc starten
  rtc.begin();
  /*
    wenn Datum und Zeit nicht korrekt → Datum/Zeit setzen
    Jahr, Monat, Tag, Stunde, Minute, Sekunde
    rrtc.adjust(DateTime(2023, 5, 15, 10, 30, 30));
  */

  // Sensor DHT starten
  dht.begin();
}

Der loop-Teil. Beach­te die Kommentare.

void loop()
{
  DateTime aktuell = rtc.now();
 
  // Daten lesen
  float Temperatur = dht.readTemperature();
  float Luftfeuchtigkeit = dht.readHumidity();

  // Funktion aufrufen
  ZeitAusgeben(aktuell);

  // in Strings umwandeln, . durch , ersetzen
  String AnzeigeTemperatur = String(Temperatur);
  AnzeigeTemperatur.replace(".", ",");
  String AnzeigeLuftfeuchtigkeit = String(Luftfeuchtigkeit);
  AnzeigeLuftfeuchtigkeit.replace(".", ",");
  Serial.print(F("Temperatur:\t\t"));
  Serial.println(AnzeigeTemperatur);
  Serial.print(F("Luftfeuchtigkeit in %:\t"));
  Serial.println(AnzeigeLuftfeuchtigkeit);
  
  /*
    in Datei schreiben
    O_CREAT -> Datei erstellen, wenn sie nicht existiert
    O_WRITE -> in die Datei schreiben
    O_AT_END -> Startposition zum Schreiben an das Ende der Datei setzen
  */
  if (!Temperaturmessung.open("Messung.csv", O_CREAT | O_WRITE | O_AT_END))
  {
    Serial.print(F("Datei kann nicht ge\u00f6ffnet werden!"));
  }
  // wenn die Datei geöffnet werden konnte ...
  if (Temperaturmessung)
  {
    Serial.println(F("Schreibe Messdaten in die Datei Messung.csv ... "));
    Serial.println(F("-----------------------------------"));

    // Überschrift in Datei schreiben
    // Funktion aufrufen
    schreibeUeberschrift();
    Temperaturmessung.print(AktuellesDatum + ";");
    Temperaturmessung.print(AktuelleZeit + ";");
    Temperaturmessung.print(AnzeigeTemperatur + ";");
    Temperaturmessung.print(AnzeigeLuftfeuchtigkeit);
    Temperaturmessung.println();

    // Schreibfehler abfragen
    if (!Temperaturmessung.sync() || Temperaturmessung.getWriteError())
    {
      Serial.print(F("Schreibfehler!"));
    }
    else
    {
      // Datei schließen
      Temperaturmessung.close();
      Serial.println(F("Abgeschlossen."));
      Serial.println();
    }
  }

  // Zeit bis zur nächsten Messung (eine Minute)
  delay(60000);
}

Im loop-Teil wer­den zwei Funk­tio­nen aufgerufen:

void ZeitAusgeben(DateTime aktuell)
{
  char Datum[] = "DD.MM.YYYY";
  AktuellesDatum = aktuell.toString(Datum);
  char Zeit[] = "Uhrzeit: hh:mm:ss";
  AktuelleZeit = aktuell.toString(Zeit);
  Serial.println(AktuellesDatum + " " + AktuelleZeit);
}

void schreibeUeberschrift()
{
  Temperaturmessung.println();
  Temperaturmessung.print(F("Datum"));

  // ; als Trennzeichen für die CSV-Datei
  Temperaturmessung.print(";");
  Temperaturmessung.print(F("Zeit"));
  Temperaturmessung.print(";");
  Temperaturmessung.print(F("Temperatur in °C"));
  Temperaturmessung.print(";");
  Temperaturmessung.print(F("Luftfeuchtigkeit in %"));
  Temperaturmessung.println();
}

Startseite
Aufgaben A-Z
Suchen
Downloads
Fehlermeldungen
Seite als PDF

Ver­wand­te Aufgaben:



Letzte Aktualisierung: 23. Okt 2023 @ 8:45