DHT22 - Wet­ter­da­ten auf­zeich­nen

Lese­zeit: 6 Minu­ten
Navi­ga­ti­on

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

So soll es aus­se­hen:

Benö­tig­te Bau­tei­le:

  • RTC-Modul DS3231
  • Temperatur-/Feuchtigkeitssensor DHT22
  • SD-Kartenleser
  • Lei­tungs­dräh­te

Der Sen­sor DHT22 misst die Tem­pe­ra­tur und die Luft­feuch­tig­keit. Das hier ver­wen­de­te Bau­teil besitzt drei Anschlüs­se.
Die Ver­si­on mit vier Pins muss in der Rei­hen­fol­ge 5V → Daten (Pin) → leer → GND geschal­tet wer­den.

Die Ver­si­on mit vier Pins muss in der Rei­hen­fol­ge 5V → Daten (Pin) → leer → GND geschal­tet wer­den.

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

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 aus­ge­ge­ben.

Der phy­si­sche Spei­cher 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 wer­den.

Der Ardui­no ver­fügt über drei Spei­cher­plät­ze:

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 wer­den
der gespei­cher­te Inhalt bleibt nach dem Aus­schal­ten erhal­ten

SRAM 2 KB
(2048 Bytes)
(sta­tic ran­dom access memo­ry) hier wer­den die Variablen/Arrays erstellt u ver­än­dert
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 Aussch noch zur Ver­fü­gung ste­hen sol­len

In den meis­ten Pro­gram­men wer­den print-Anweisungen 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 not­wen­dig.

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 Ver­fü­gung.

Bei­spie­le:

Serial.println(F("Initialisierung abgeschlossen")); 
Serial.println(F("Schreibe Messdaten in die Datei Messung.csv: ")); 
Serial.println(F("-----------------------------------"));

Benö­tig­te Biblio­the­ken:
Sketch → Biblio­thek ein­bin­den → Biblio­the­ken ver­wal­ten

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 Kom­men­ta­re:

// Bibliothek für die SD-Karte 
# include <SdFat.h> 

// Bezeichnung der SD-Karte 
SdFat SD; 

// Bibliothek für die Kommunikation des Arduino mit Peripheriegeräten # 
include <SPI.h> 

// Bibliothek für den DHT22 
# include <SimpleDHT.h> 

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

// Bezeichnung der Textdatei 
File Temperaturmessung; 

// Datenpin für das SD-Kartenmodul 
int CSPIN = 4; 
int SENSOR_DHT22 = 8; 

// Namen des Sensors (dht22) 
SimpleDHT22 dht22(SENSOR_DHT22); 
int SensorLesen; 

// Trennzeichen für die CSV-Datei 
const String TrennZeichen = ";"; 
String AktuellesDatum; 
String AktuelleZeit; 

// Bezeichnung der Wochentage für das RTC-Modul 
char daysOfTheWeek[7][12] = {"Sonntag", "Montag", "Dienstag", "Mittwoch",  "Donnerstag", "Freitag", "Samstag"};

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

void setup() 
{ 
  pinMode(SENSOR_DHT22, INPUT); 
  Serial.begin(9600); 
  Serial.println(F("Initialisiere SD-Karte")); 
  if (!SD.begin(CSPIN)) 
  {  
    Serial.println(F("Initialisierung fehlgeschlagen!")); 
  } 
  else Serial.println(F("Initialisierung abgeschlossen"));
  rtc.begin(); 

  /*  
    wenn Datum und Zeit nicht korrekt → Datum/Zeit setzen
    Jahr, Monat, Tag, Stunde, Minute, Sekunde
    rtc.adjust(DateTime(2018, 10, 25, 17, 28, 30)); 
  */
}

Der loop-Teil. Beach­te die Kom­men­ta­re.

void loop() 
{ 
  DateTime aktuell = rtc.now(); 
  float Temperatur; 
  float Luftfeuchtigkeit;  

  // Daten lesen 
  dht22.read2(&Temperatur, &Luftfeuchtigkeit, NULL);   

  // Methode 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); 

  /*  
    Datei zum Schreíben (FILE_WRITE) öffnen   
    wenn sie noch nicht existiert, wird sie erstellt 
    wenn Schreiben nicht möglich → Fehlermeldung 
  */ 
  if (!Temperaturmessung.open("Messung.csv", FILE_WRITE)) 
  { 
    Serial.print(F("Datei kann nicht geöffnet 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 
    // Methode aufrufen
    schreibeUeberschrift(); 
    Temperaturmessung.print(AktuellesDatum + TrennZeichen); 
    Temperaturmessung.print(AktuelleZeit + TrennZeichen); 
    Temperaturmessung.print(AnzeigeTemperatur + TrennZeichen); 
    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 
  delay(60000); 
}

Im loop-Teil wer­den zwei Metho­den auf­ge­ru­fen:

void ZeitAusgeben(DateTime aktuell) 
{ 
  AktuellesDatum = ""; 
  AktuelleZeit = ""; 
  
  // dayOfWeek ist ein Array → muss in String umgewandelt werden 
  AktuellesDatum = String(daysOfTheWeek[aktuell.dayOfTheWeek()]) + " " + aktuell.day() + "." + aktuell.month() + "." + aktuell.year() + " "; 
  AktuelleZeit = AktuelleZeit + aktuell.hour() + ":"; 

  // wenn Minuten < 10 → führende 0 setzen
  if (aktuell.minute() < 10) AktuelleZeit = AktuelleZeit + "0" +    aktuell.minute() + ":"; 
  else AktuelleZeit = AktuelleZeit + aktuell.minute() + ":"; 

  // wenn Sekunden < 10 → führende 0 setzen 
  if (aktuell.second() < 10) AktuelleZeit = AktuelleZeit + "0" + aktuell.second() + " Uhr";  
  else AktuelleZeit = AktuelleZeit + aktuell.second() + " Uhr";
  Serial.println(AktuellesDatum + AktuelleZeit); 
} 

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

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


Ver­wand­te Auf­ga­ben:



Letzte Aktualisierung: 27. Sep 2020 @ 22:35