Wetterstation mit Arduino UNO

Hallo Forum,

dies ist mein erster Beitrag in einem großen Forum also bitte etwas Nachsicht, wenn ich Informationen vergessen habe.

Ich möchte eine Wetterstation mit einem Arduino UNO aufbauen. Ich nutze dafür einen DHT22, ein LCD1602, eine DS3231 und ein Micro-SD karten Modul von CATALEX (mehr steht leider nicht auf dem Modul).

Ich bin, was den Arduino angeht, ein ziemlicher Anfänger.

Die Wetterstation soll nacheinander die Temperatur, Luftfeuchtigkeit, Uhrzeit und Datum auf dem LCD anzeigen. Außerdem soll sie 3 mal am Tag die Werte auf die SD Karte schreiben.

Das Anzeigen funktioniert problemlos und auch das beschreiben der SD Karte habe ich geschafft. Dies allerdings nur als Test, d.h. ich habe NUR die SD Karte einbezogen.

Jetzt zu meinem eigentlichen Problem,

beziehe ich die SD Karte mit in den Aufbau und das Programm ein, so habe ich kein Bild mehr oder nur Hieroglyphen auf dem LCD. Außerdem scheint etwas mit meiner Abfrage der Uhrzeit nicht richtig zu sein.

Hat jemand von euch erfahreneren vielleicht einen Tipp für mich?

Ich hoffe das Einfügen von meinem Sketch habe ich richtig gemacht :confused:

Danke schon einmal im Voraus

Dominik

#include  <DHT.h>
#include  <Wire.h>
#define   DHTPIN A0     //Pin an welchen die Daten von dem DHT22 gehen
#define DHTTYPE DHT22   //DHT Typ auswählen
DHT dht(DHTPIN, DHTTYPE);

#include  <DS3231.h>
DS3231 clock;
RTCDateTime dt;

#include  <LiquidCrystal.h>
LiquidCrystal lcd (5, 6, 7, 8, 9, 10);   //Pins die von dem LCD verwendet werden

#include  <SD.h>
#include  <SPI.h>
File Daten;


void setup()
{
  lcd.clear();      //LCD einmal löschen
  lcd.begin(16, 2); // verfügbare Spalten und Reihen angeben

  dht.begin();
  
  clock.begin();
  clock.setDateTime(__DATE__, __TIME__);

  SD.begin(10);
  //Serial.begin(9600);
  //Serial.println("Warten auf SD Karte...");
}

void schreiben(float h, float t)
{
  Daten = SD.open("Daten.txt", FILE_WRITE);

  if(Daten)
  {
    Serial.println("Daten werden gespeichert...");
    
    Daten.print("Datum: ");
    Daten.println(clock.dateFormat("d m Y", dt));
    Daten.print("Uhrzeit: ");
    Daten.println(clock.dateFormat("H:i", dt));
    Daten.print("Temperatur: ");
    Daten.print(t);
    Daten.println("°C");
    Daten.print("Luftfeuchtigkeit: ");
    Daten.print(h);
    Daten.println("%");

    Daten.close();
  }
}


void loop()
{
  dt = clock.getDateTime();
  String zeit = clock.dateFormat("H:i", dt);
  
  //Einlesen der Werte vom DHT22 in Variablen
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  //Überprüfen, ob die Daten auch Zahlenwerte sind
  if (isnan(t) || isnan(h))     //nan = not a number 
  {
    lcd.setCursor(0,0);
    lcd.print("Fehler beim");
    lcd.setCursor(0,1);
    lcd.print("Lesen der Daten!");
  }
  else
  {
    //Ausgabe auf dem LCD
    lcd.setCursor(3,0);      
    lcd.print("Temperatur");
    lcd.setCursor(5,1);
    lcd.print(t);
    lcd.print("\xDF");
    lcd.print("C");
    delay (2500);
    lcd.clear();
    lcd.setCursor(0,0);      
    lcd.print("Luftfeuchtigkeit");
    lcd.setCursor(5,1); 
    lcd.print(h);
    lcd.print("%");
    delay (2500);
    lcd.clear();
    lcd.setCursor(4,0);
    lcd.print("Uhrzeit");
    lcd.setCursor(5,1);
    lcd.print(clock.dateFormat("H:i", dt));
    delay (2500);
    lcd.clear();
    lcd.setCursor(5,0);
    lcd.print("Datum");
    lcd.setCursor(3,1);
    lcd.print(clock.dateFormat("d m Y", dt));
    delay (2500);
    lcd.clear(); 
  }

  if(zeit == "18:50" || "19:00" || "19:05")
  {
    schreiben(h, t);
  } 
}

Der Code enthält meiner Meinung nach diverse "logische Bomben", die ein einwandfreies funktionieren verhindern.

Zum Beispiel scheint im setup() die Reihenfolge für "LCD-Befehl ausführen" und "LCD initialisieren" vertauscht zu sein:

  lcd.clear();      //LCD einmal löschen
  lcd.begin(16, 2); // verfügbare Spalten und Reihen angeben

Natürlich muss es genau anders herum sein:

Zuerst ,uß das Display mit LCD.begin initialisiert werden, bevor man Befehle wie LCD.clear() ausführen kann.

Die nächste logische Bombe steckt in der Uhrzeiteinstellung bei jedem Programmstart:

  dht.begin();
  
  clock.begin();
  clock.setDateTime(__DATE__, __TIME__);

Damit stellst Du BEI JEDEM PROGRAMMSTART das Uhrenmodul neu ein, und zwar immer wieder auf dieselbe Uhrzeit, und zwar Datum und Ihrzeit, zu dem das Programm auf dem PC kompiliert worden ist.

Soll die Uhr wirklich bei jedem Power-On und jedem Reset wieder zurückgestellt werden auf das Datum und die Uhrzeit, zu dem das Programm auf dem PC kompiliert wurde?

Das scheint mir völliger Unsinn zu sein.

Ich würde bei so einem Programm eher erwarten, dass es eine Möglichkeit gibt, die Uhrzeit und das Datum irgendwie frei einzustellen, zum Beispiel über Serial mit Hilfe des seriellen Monitors. Aber von der Möglichkeit einer Datums- und Uhrzeiteinstellung sehe ich nichts. Immer nur die Rückstellung auf den Zeitpunkt der Kompilierung.

Das Problem liegt vermutlich daran, da du den SPI-CS der SD-Karte auch auf dem Pin 10 gelegt hast.
Du müsstest das umstellen, entweder den CS der SD-Karte oder den Pin 10 vom Display.

Da du schon I2C für die RTC verwendest, warum nimmst du nicht auch I2C für das Display ?
Du sparst dadurch Pins am Arduino.

Das Problem liegt vermutlich daran, da du den SPI-CS der SD-Karte auch auf dem Pin 10 gelegt hast.
Du müsstest das umstellen, entweder den CS der SD-Karte oder den Pin 10 vom Display.

Ja das habe ich nach erstellen des Threads auch gesehen und wurde von mir direkt behoben.

Da du schon I2C für die RTC verwendest, warum nimmst du nicht auch I2C für das Display ?
Du sparst dadurch Pins am Arduino.

Um ganz ehrlich zu sein, weil ich keine Ahnung habe wie. Sowohl in der Verdrahtung als auch in dem Sketch.

Soll die Uhr wirklich bei jedem Power-On und jedem Reset wieder zurückgestellt werden auf das Datum und die Uhrzeit, zu dem das Programm auf dem PC kompiliert wurde?

Mh natürlich nicht. Ich habe mir versucht mit Beispielen die Funktion der einzelnen Komponenten beizubringen. Hat wohl leider nicht so gut funktioniert wie ich gehofft habe :frowning:

Do0m3:
Um ganz ehrlich zu sein, weil ich keine Ahnung habe wie. Sowohl in der Verdrahtung als auch in dem Sketch.

Das ist nicht kompliziert, da brauchst du folgendes Modul: I2C-Adapter

Und hier kannst du einiges darüber nachlesen. Auch wie es angeschlossen wird und der Sketch aussieht.

Ich habe es jetzt zwar geschafft, dass ich auch mit dem SD Modul ein bild auf dem LCD habe. Allerdings ist es nun so, dass ich entweder nach 2-3 Minuten Betrieb plötzlich kein Bild mehr habe oder die Daten vom DHT22 wohl nicht mehr ankommen (meine selbst geschriebene Überprüfung mit dem Meldetext "Fehler beim Lesen der Daten!").

Die Abfrage der aktuellen Uhrzeit scheint auch nicht zu funktionieren, da nichts auf die Karte geschrieben wurde :confused:

#include  <DHT.h>
#include  <Wire.h>
#define   DHTPIN A0     //Pin an welchen die Daten von dem DHT22 gehen
#define DHTTYPE DHT22   //DHT Typ auswählen
DHT dht(DHTPIN, DHTTYPE);

#include  <DS3231.h>
DS3231 clock;
RTCDateTime dt;

#include  <LiquidCrystal.h>
LiquidCrystal lcd (4, 5, 6, 7, 8, 9);   //Pins die von dem LCD verwendet werden

#include  <SD.h>
#include  <SPI.h>
File Daten;


void setup()
{
  lcd.begin(16, 2); // verfügbare Spalten und Reihen angeben
  lcd.clear();      //LCD einmal löschen

  dht.begin();
  
  clock.begin();
  //clock.setDateTime(__DATE__, __TIME__);

  SD.begin(10);
  //Serial.begin(9600);
  //Serial.println("Warten auf SD Karte...");
}

void schreiben(float h, float t)
{
  Daten = SD.open("Daten.txt", FILE_WRITE);

  if(Daten)
  {
    Serial.println("Daten werden gespeichert...");
    
    Daten.print("Datum: ");
    Daten.println(clock.dateFormat("d m Y", dt));
    Daten.print("Uhrzeit: ");
    Daten.println(clock.dateFormat("H:i", dt));
    Daten.print("Temperatur: ");
    Daten.print(t);
    Daten.println("°C");
    Daten.print("Luftfeuchtigkeit: ");
    Daten.print(h);
    Daten.println("%");

    Daten.close();
  }
}


void loop()
{
  dt = clock.getDateTime();
  String zeit = clock.dateFormat("H:i", dt);
  
  //Einlesen der Werte vom DHT22 in Variablen
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  //Überprüfen, ob die Daten auch Zahlenwerte sind
  if (isnan(t) || isnan(h))     //nan = not a number 
  {
    lcd.setCursor(0,0);
    lcd.print("Fehler beim");
    lcd.setCursor(0,1);
    lcd.print("Lesen der Daten!");
  }
  else
  {
    //Ausgabe auf dem LCD
    lcd.setCursor(3,0);      
    lcd.print("Temperatur");
    lcd.setCursor(5,1);
    lcd.print(t);
    lcd.print("\xDF");
    lcd.print("C");
    delay (2500);
    lcd.clear();
    lcd.setCursor(0,0);      
    lcd.print("Luftfeuchtigkeit");
    lcd.setCursor(5,1); 
    lcd.print(h);
    lcd.print("%");
    delay (2500);
    lcd.clear();
    lcd.setCursor(4,0);
    lcd.print("Uhrzeit");
    lcd.setCursor(5,1);
    lcd.print(clock.dateFormat("H:i", dt));
    delay (2500);
    lcd.clear();
    lcd.setCursor(5,0);
    lcd.print("Datum");
    lcd.setCursor(3,1);
    lcd.print(clock.dateFormat("d m Y", dt));
    delay (2500);
    lcd.clear(); 
  }

  if(zeit == "15:25" || "15:30" || "15:35")
  {
    schreiben(h, t);
  } 
}

Übersehe ich einfach einen groben Fehler oder bin ich tatsächlich einfach zu doof um etwas so simples richtig zu programmieren? Hat das eventuell etwas damit zu tun, das ich beim Kompilieren die Warnung bekomme, dass nur noch wenig Arbeitsspeicher vorhanden ist?