Frage zu Übungscode

Hallo an alle.
Da ich gerade meine Programmierkenntnisse ein bisschen ausbauen will um die zuverlässigkeit meiner Programme zu verbessern , habe ich mal eine Datenlogger mit eingebunden. Um die Programmabläufe mal mitzuloggen.
Das geht auf so weit ganz gut. Aber wenn ich im Logger die Funktion mit Signal mit einbinde (Der ausgeklammerte Text) geht gar nichts mehr.Hat jemand eine erklärung dafür.
Danke Stefan

#include <LiquidTWI2.h>
LiquidTWI2 lcd(0);
#include "DHT.h"
#define DHTTYPE DHT22
#define DHTTYPE_1 DHT22 // DHT 22 
#define DHTTYPE_2 DHT22 // DHT 22 
#include <DS3231.h>
DS3231  rtc(SDA, SCL);
#define RTC_I2C_ADDRESS 0x68
#include <SoftwareSerial.h>
#include <SD.h>
#define DHTPIN_1 6 // Datenleitung für den DHT-Sensor 1 (innen)
#define DHTPIN_2 7 // Datenleitung für den DHT-Sensor 2 (außen)
DHT dht1(DHTPIN_1, DHTTYPE_1); //Der Innensensor wird ab jetzt mit dht1 angesprochen
DHT dht2(DHTPIN_2, DHTTYPE_2); //Der Außensensor wird ab jetzt mit dht2 angesprochen
int Relay_Pin01 = 2;
int LedAufz = 4;
int Sirene = 9;
int chipSelect = 10;
char Nummer[6];
File myFile;
int i = 1;
Time  time;
int Hor;
int Min;


void setup() {
  Serial.begin(9600);
  lcd.setMCPType(LTI_TYPE_MCP23017);
  lcd.begin(20, 4);
  dht1.begin(); // Sensoren starten DHT22 I
  dht2.begin(); // Sensoren starten DHT22 A
  rtc.begin();//
  rtc.setTime(23, 44, 50);//
  rtc.setDate(11, 9, 2024);//
  pinMode(Relay_Pin01, OUTPUT);
  pinMode(Sirene, OUTPUT);
  pinMode(LedAufz, OUTPUT);
  pinMode(chipSelect, OUTPUT);
  Serial.println("KARTE SUCHEN");
  delay(1000);
  if (!SD.begin(chipSelect)) {
    Serial.println("KARTE FEHLT");
    delay(1000);
    return;
  }
  Serial.println ("GEFUNDEN");
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i / 10 + '0';
    filename[7] = i % 10 + '0';
    if (! SD.exists(filename)) {
      myFile = SD.open(filename, FILE_WRITE);
      break;
    }
  }
  Serial.println(filename);
  delay(1000);

}

void loop()
{
  Sensor01();
  Sensor02();
  Zeitschaltuhr_Uhr();
  Zeitschaltuhr_Hum();
  Zeitschaltuhr_Sig();
  Aufzeichnung();
}

void Sensor01()
{
  float t2 = dht2.readTemperature();//AUSSEN
  float h2 = dht2.readHumidity(); //AUSSEN

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SENSOR 1     (DHT A)");

  lcd.setCursor(0, 1);
  lcd.print("TEMP A");
  lcd.setCursor(0, 2);
  lcd.print("LUFT A");

  lcd.setCursor(7, 1);//neu
  lcd.print(t2);
  lcd.setCursor(13, 1);
  lcd.print("C");

  lcd.setCursor(7, 2);
  lcd.print(h2);
  lcd.setCursor(13, 2);
  lcd.print("%");

  delay(1000);
  lcd.clear();
}

void Sensor02()
{
  float t1 = dht1.readTemperature();//INNEN
  float h1 = dht1.readHumidity();//INNEN

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SENSOR 2     (DHT I)");

  lcd.setCursor(0, 1);
  lcd.print("TEMP I");
  lcd.setCursor(0, 2);
  lcd.print("LUFT I");

  lcd.setCursor(7, 1);//neu
  lcd.print(t1);
  lcd.setCursor(13, 1);
  lcd.print("C");

  lcd.setCursor(7, 2);
  lcd.print(h1  );
  lcd.setCursor(13, 2);
  lcd.print("%");

  delay(1000);
  lcd.clear();
}

void Zeitschaltuhr_Uhr()
{
  time = rtc.getTime();
  Hor = time.hour;
  Min = time.min;

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("ZEIT : ");
  lcd.print(rtc.getTimeStr());
  lcd.setCursor(0, 1);//
  lcd.print("DATUM: ");//
  lcd.print(rtc.getDateStr());
  delay(1000);
  lcd.clear();
}

void Zeitschaltuhr_Hum()
{
  float h1 = dht1.readHumidity();//INNEN
  float h2 = dht2.readHumidity();//AUSSEN

  int minhum_on = 30;
  int maxhum_on = 38;

  if (isnan(h1) || (isnan(h2)))
  {
    return;
  }

  if ( h2 > minhum_on && (h2 < maxhum_on))
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RELAY 01");
    lcd.setCursor(0, 2);
    lcd.print(" >>>>  AN-HUM");
    digitalWrite(Relay_Pin01, HIGH);
    delay(1000);
    lcd.clear();
  }
  else
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RELAY 01");
    lcd.setCursor(0, 2);
    lcd.print(" >>>> AUS-HUM");
    digitalWrite(Relay_Pin01, LOW);
    delay(1000);
    lcd.clear();
  }
}

void Zeitschaltuhr_Sig()
{
  time = rtc.getTime();
  Hor = time.hour;
  Min = time.min;

  if ( Hor == 23 &&  (Min == 45))
  {
    Serial.println("Sirene an SIG");
    digitalWrite( Sirene, HIGH);//9
    lcd.setCursor(0, 0);
    lcd.print("SIRENE EIN");
    delay(1000);
    lcd.clear();
  }

  if ( Hor == 23 &&  (Min == 46))
  {
    Serial.println("Sirene aus SIG");
    digitalWrite( Sirene, LOW);//9
    lcd.setCursor(0, 0);
    lcd.print("SIRENE AUS");
    delay(1000);
    lcd.clear();
  }
}

void Aufzeichnung()
{
  time = rtc.getTime();
  Hor = time.hour;
  Min = time.min;

  int minhum_on = 30;
  int maxhum_on = 48;
  int minhum_off = 50 ;   //50
  int maxhum_off = 99 ;   //99

  float h2 = dht2.readHumidity();
  
  String dataString = "";
  digitalWrite(LedAufz, HIGH);//8
  myFile.print("MESSUNG");
  myFile.print(" ");
  sprintf(Nummer, "%05d", i);
  i++;
  myFile.print(Nummer);
  myFile.print(" ");
  myFile.print(rtc.getDateStr());
  myFile.print(" ");
  myFile.print(rtc.getTimeStr());
  myFile.println();
  myFile.print(dht1.readHumidity ());
  myFile.print(" % LUFTF. I");
  myFile.println();
  myFile.print(dht2.readHumidity());
  myFile.print(" % LUFTF. A");
  myFile.println();
  /*
    if ( Hor == 23 &&  (Min == 45))
    {
      myFile.print("SIGNAL_EIN");
      myFile.println();
      myFile.println();
    }

    if ( Hor == 23 &&  (Min == 46))
    {
      myFile.print("SIGNAL_AUS");
      myFile.println();
      myFile.println();
    }
  */

 if ( h2 > minhum_on && (h2 < maxhum_on))
  {
    myFile.print("RELAY_EIN");
    myFile.println();
    myFile.println();
  }

  if ( h2 > minhum_off && (h2 < maxhum_off))
  {
    myFile.print("RELAY_AUS");
    myFile.println();
    myFile.println();
  }

  myFile.flush();
  lcd.setCursor(0, 0);
  lcd.print("AUFZEICHNUNG:");
  delay(1000);
  lcd.clear();
  digitalWrite(LedAufz, LOW);
}

Zu diesen gleichen Stunden und Minuten löscht man den Bildschirm. Gilt der leere Bildschirm als "geht gar nichts mehr"? Werden Daten in Dateien geschrieben?

  if ( Hor == 23 &&  (Min == 45))
  {
    Serial.println("Sirene an SIG");
    digitalWrite( Sirene, HIGH);//9
    lcd.setCursor(0, 0);
    lcd.print("SIRENE EIN");
    delay(1000);
    lcd.clear();
  }

  if ( Hor == 23 &&  (Min == 46))
  {
    Serial.println("Sirene aus SIG");
    digitalWrite( Sirene, LOW);//9
    lcd.setCursor(0, 0);
    lcd.print("SIRENE AUS");
    delay(1000);
    lcd.clear();
  }

@xfpd
Hallo
den Teil wo du gepostet hast der geht (Das sieht man auf dem Display).
Aber nicht der in der Aufzeichnung.
Dann wird nichts mehr auf die SD Karte geschrieben. Aber ich muss mir mal eine andre SD Karte hohlen und dann mal testen. Was mir jetzt schon oft passiert ist wenn ich die Karte aus dem Logger rausnehme und am PC ansehen will ist. Das ich die SD Karte immer wieder erst Reparieren muss.
Vielleicht liegt es auch nur an der SD Karte.
Danke Stefan

Oder das Kartenlesemodul.

Das ist ja klar du legst den Nahmen der Datei in Setup an und öffnest die, die Datei bleibt ganze zeit offen.
Windows und nicht nur Windows bei Reparieren schlisst die. Dir kann Passieren das die Datei verloren geht, wird nicht mehr gefunden.
Schau dir das Beispiel in der SD Lib an, oder andere DataLog Beispiele, zu dem wo zu bei jedem durchlauf der Loop schreiben? so schnell ändern sich die Werte nicht, du hast in einer Sekunde minimum10mall das gleiche drauf.

1 Like

Ich seit über 3J Datalog auf SD es werden 10 Parameter uf SD geschrieben alle 20Min. mir ist noch nie passiert das Windows musste die Karte reparieren, Alle 2 Monate wird die Katre getauscht Werte analysiert und als Excel gespeichert auf Rechner, die Data wird auf der Karte umbenannt, somit habe alles noch auf der Karte

was bedeutet das genau? Was siehst du auf der Seriellen Schnittstelle, was siehst du am LCD?

Weiters, poste mal die Zusammenfassung vom Kompilieren - wie viel Progmem wird benötigt, wie viel globaler Memory?

Welchem Microcontroller verwendest du?

Da offenbar noch nicht geschehen, lies dich ein zum Thema Arduino F-Makro und verwende es für deine Serial.print, lcd.print und file.print mit Fixtext!

Was für DS3231.h nutzt du? Habe zwei nur nicht die was du nutzt.
In der
Library.PROPERTIES steht die Version, oder genauen Link zu der DS3231 bitte,
Bekomme dein Sketch nicht zum Laufen.
Es bringt nicht wenn ich das auf meine RTC Lib umbaue, wird bei mir funktionieren bei dir nicht.

Dein RAM Speicher enthält zu viel Text. Darum stürzt dein Controller ab, sobald Du die zusätzlichen Ausgaben "aktivierst".

Abhilfte:

  • das F() Makro bei der Ausgabe verwenden,
  • sparsamere Libraries verwenden
  • weniger Text.

Davon abgesehen kostet es auch Speicher, wenn man Funktionen stumpf kopiert obwohl das gar nicht notwendig ist. Beispiel Sensor01() und Sensor02(). Das kann eine Funktion erledigen.

Ich habe den Code beispielhaft mal umgestellt:

#include <Streaming.h>           // https://github.com/janelia-arduino/Streaming.git
#include <DHT.h>                 // https://github.com/adafruit/DHT-sensor-library
#include <LiquidCrystal_I2C.h>   // https://github.com/johnrickman/LiquidCrystal_I2C
#include <RTClib.h>              // https://github.com/adafruit/RTClib
#include <SD.h>

//
// defines
//
#define SHOW_FILE_CONTENT   // If not commented out, then display your file content on the serial console

//
// Global constants
//
constexpr byte DHTTYPE {DHT22};
constexpr byte DHTPIN_1 {6};   // Datenleitung für den DHT-Sensor 1 (inner)
constexpr byte DHTPIN_2 {5};   // Datenleitung für den DHT-Sensor 2 (außen)
constexpr byte LEDPIN_AUFZEICHNUNG {4};
constexpr byte RELAISPIN {2};
constexpr byte SIRENPIN {9};
constexpr byte CSPIN {10};

//
// Data definitions
//
enum DHTDescription : byte { inner, outer, end };

struct DHT22Data {
  float temperature;
  float humidity;
};

//
// Global variables/objects
//
char filename[] {"LOGGER00.CSV"};
bool isFileReadyForOpen {false};

RTC_DS1307 rtc;                       // RTC Clock Object
LiquidCrystal_I2C lcd(0x27, 20, 4);   // LCD I2C Adresse 0x27 für 20 Zeichen und 4 Zeilen Darstellung
DHT dht[2] {
    {DHTPIN_1, DHTTYPE},
    {DHTPIN_2, DHTTYPE}
};   // Zwei DHT Sensoren initialisieren 0 inner 1 outer

//
// Functions
//
bool checkFilename(SDClass card, char *filename) {
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i / 10 + '0';
    filename[7] = i % 10 + '0';
    if (!card.exists(filename)) {
      Serial.println(filename);
      return true;
      break;
    }
  }
  return false;
}

void readDHT22Data(DHT sensor, DHT22Data &data) {
  data.temperature = sensor.readTemperature();
  data.humidity = sensor.readHumidity();
}

void Sensor(DHT22Data data, byte sensorNum) {
  const char *location[] {"Innen", "Aussen", "x"};
  if (sensorNum > DHTDescription::outer) { sensorNum = DHTDescription::end; }

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("SENSOR DHT"));
  lcd.print(sensorNum + 1);
  lcd.print(' ');
  lcd.print(location[sensorNum]);

  lcd.setCursor(0, 1);
  lcd.print(F("TEMP"));
  lcd.setCursor(0, 2);
  lcd.print(F("LUFT"));

  lcd.setCursor(7, 1);   // neu
  lcd.print(data.temperature);
  lcd.setCursor(13, 1);
  lcd.print('C');

  lcd.setCursor(7, 2);
  lcd.print(data.humidity);
  lcd.setCursor(13, 2);
  lcd.print('%');

  delay(1000);
  lcd.clear();
}

void Zeitschaltuhr_Uhr(DateTime &time) {
  char dateFormat[11] {"DD.MM.YYYY"};
  char timeFormat[9] {"hh:mm:ss"};

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("ZEIT : "));
  lcd.print(time.toString(timeFormat));
  lcd.setCursor(0, 1);
  lcd.print(F("DATUM: "));
  lcd.print(time.toString(dateFormat));
  delay(1000);
  lcd.clear();
}

bool Zeitschaltuhr_Hum(DHT22Data *data, bool isRelaisOn) {
  int minhum_on = 30;
  int maxhum_on = 38;

  if (isnan(data[DHTDescription::inner].humidity) || (isnan(data[DHTDescription::outer].humidity))) { return false; }
  if (data[DHTDescription::outer].humidity > minhum_on && (data[DHTDescription::outer].humidity < maxhum_on)) {
    if (!isRelaisOn) {
      digitalWrite(RELAISPIN, HIGH);
      isRelaisOn = true;
      delay(1000);
      lcd.clear();
    }
  } else if (isRelaisOn) {
    digitalWrite(RELAISPIN, LOW);
    isRelaisOn = false;
  }

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("RELAY 01"));
  if (!isRelaisOn) {
    lcd.setCursor(0, 2);
    lcd.print(F(" >>>>  AUS-HUM"));
  } else {
    lcd.setCursor(0, 2);
    lcd.print(F(" >>>> AN-HUM"));
  }
  delay(1000);
  return isRelaisOn;
}

bool Zeitschaltuhr_Sig(DateTime &time, bool isSignalOn) {
  byte hour = time.hour();
  byte minute = time.minute();

  if (hour == 23 && minute == 45 && !isSignalOn) {
    Serial.println(F("Sirene an SIG"));
    isSignalOn = true;
    digitalWrite(SIRENPIN, HIGH);   // 9
    lcd.setCursor(0, 0);
    lcd.print(F("SIRENE EIN"));
    delay(1000);
    lcd.clear();
  }

  if (hour == 23 && minute == 46 && isSignalOn) {
    Serial.println(F("Sirene aus SIG"));
    isSignalOn = false;
    digitalWrite(SIRENPIN, LOW);
    lcd.setCursor(0, 0);
    lcd.print(F("SIRENE AUS"));
    delay(1000);
    lcd.clear();
  }
  return isSignalOn;
}

void Aufzeichnung(DateTime &time, const DHT22Data *data, bool signalFlag = false, bool relaisFlag = false) {
  static unsigned long counter {0};
  File myFile;
  Print &fCout {myFile};
  if (isFileReadyForOpen) {
    myFile = SD.open(filename, FILE_WRITE);
    if (!myFile) {
      Serial.println(F("error opening file"));
      return;
    }
  }
  digitalWrite(LEDPIN_AUFZEICHNUNG, HIGH);
  fCout << _WIDTHZ(++counter, 10) << ' ' << _WIDTHZ(time.day(), 2) << '.' << _WIDTHZ(time.month(), 2) << '.'
        << _WIDTH(time.year(), 4) << ' ' << _WIDTHZ(time.hour(), 2) << ':' << _WIDTHZ(time.minute(), 2) << ':'
        << _WIDTHZ(time.second(), 2) << ' ' << F("Humidity: I: ") << data[DHTDescription::inner].humidity << F("% A: ")
        << data[DHTDescription::outer].humidity << F("% Signal: ");

  (signalFlag == true) ? fCout << F("EIN ") : fCout << F("AUS ");
  fCout << "RELAIS: ";
  (relaisFlag == true) ? fCout << F("EIN ") : fCout << F("AUS ");
  fCout << endl;
  myFile.close();

#ifdef SHOW_FILE_CONTENT
  // re-open the file for reading:
  myFile = SD.open(filename);
  if (myFile) {
    // read from the file until there's nothing else in it:
    while (myFile.available()) { Serial.write(myFile.read()); }
    // close the file:
    myFile.close();
    Serial.println(F("---"));
  } else {
    // if the file didn't open, print an error:
    Serial.println(F("error opening file"));
  }
#endif

  lcd.setCursor(0, 0);
  lcd.print(F("AUFZEICHNUNG:"));
  delay(1000);
  lcd.clear();
  digitalWrite(LEDPIN_AUFZEICHNUNG, LOW);
}

//
// Main Program
//
void setup() {
  Serial.begin(9600);
  pinMode(RELAISPIN, OUTPUT);
  pinMode(SIRENPIN, OUTPUT);
  pinMode(LEDPIN_AUFZEICHNUNG, OUTPUT);
  pinMode(CSPIN, OUTPUT);

  lcd.init();
  lcd.backlight();
  dht[DHTDescription::inner].begin();   // Sensoren starten DHT22 I
  dht[DHTDescription::outer].begin();   // Sensoren starten DHT22 A
  if (!rtc.begin()) {
    Serial.println(F("Couldn't find RTC"));
    Serial.flush();
    abort();
  }

  Serial.println(F("KARTE SUCHEN"));
  delay(1000);
  if (!SD.begin(CSPIN)) {
    Serial.println(F("KARTE FEHLT"));
    delay(1000);
    return;
  }
  Serial.println(F("GEFUNDEN"));
  isFileReadyForOpen = checkFilename(SD, filename);
  if (!isFileReadyForOpen) {
    Serial.println(F("The number of 100 files has been reached. No new file has been created!"));
    while (1) {}
  }
  rtc.adjust(DateTime(2024, 9, 14, 23, 44, 45));
}

void loop() {
  static DHT22Data envData[2];
  static bool stateRelais {false};
  static bool stateSignal {false};

  DateTime now = rtc.now();
  for (byte i = DHTDescription::inner; i < DHTDescription::end; ++i) {
    readDHT22Data(dht[i], envData[i]);
    Sensor(envData[i], i);
  }
  Zeitschaltuhr_Uhr(now);
  stateRelais = Zeitschaltuhr_Hum(envData, stateRelais);
  stateSignal = Zeitschaltuhr_Sig(now, stateSignal);

  Aufzeichnung(now, envData, stateSignal, stateRelais);
}

Hier die Demo:

Der Code wird bei Dir nicht 1zu1 übertragbar sein, weil ich eine andere RTC- und LCD Lib verwendet habe. Zumindest die LCD Lib müsste auf Deine Umgebung angepasst werden (Header und Objekterstellung). Die RTC Lib kann auch einfach ausgetauscht werden. Wenn Du das nicht willst, musst Du das halt auch wieder ummoddeln.

Hallo an alle

Erst mal Danke an alle für euere schnelle Hilfe.
Das nichts Aufgezeichnet wurde war wirklich die SD Karte schuld.
Habe mir heute eine neu besorgt und jetzt geht es. Das Aufzeichen
vom Signal und vom Relay.

@ Kai-R
Ich habe jede menge Fragen. Was mir aufgefallen ist ist das dein Code so weich läuft. WARUM.

Kannst du mir mal bitte den Satz erklären

if (isnan(data[0].humidity) || (isnan(data[1].humidity))) { return false; }

Das sehe ich in Testcodes immer öffters.
Was mach dieser Satz
Danke Stefan

Weil er gut ist :wink:. Ne, keine Ahnung.

Wenn ein DHT Sensor aus irgendwelchen Gründen keine sinnvollen Daten liefern kann,
so wird der Wert "nan" ausgelesen... Das bedeutet soviel wie "Not a number".
Das ist ein Fehler und deshalb wird in diesem Fall ein "false" von der Funktion zurück gegeben. Das war aber in deinem ursprünglichen Code auch schon drin...

Hallo Kai-R
Noch eine Frage .Wie stelle ich die Uhrzeit.
Warum sehr ich jetzt immer mehr das void Setup unten steht.

Danke Stefan

Das siehst Du in den Beispielen Deiner RTC-Lib. Tipp: adjust(...) suchen

Gruß Tommy

Hallo Tommy56
Danke für die Antwort
Der Befehl "adjust" kenne ich . Aber wenn ich den Einfüge kommt immer

"class 3231 has no member named "adjust"

Ich habe doch geschrieben, dass ich eine andere RTCLib verwende. In deinem Code vom Eingangsposting kannst Du doch sehen, wie das bei der von Dir verwendeten Library geht.

Sollte ich das jetzt falsch verstanden haben und Du hast auf die Rtclib von Adafruit gewechselt, dann geht das so: rtc.adjust(DateTime(2024, 9, 14, 19, 08, 0));
Die ersten drei Ziffern beschreiben das Datum, der Rest beschreibt die Uhrzeit

Dann gib einen Link zu der Lib, die Du aktuell benutzt.

Gruß Tommy

Habe schon im Post #8 gefragt, keine Antwort ist für mich auch eine Antwort.

Wer keine Hilfe will, kann das auch dadurch ausdrücken, dass er keine Info gibt.

Gruß Tommy

@fony
Sorry habe ich überlesen.
Hier die Lib:

DS3231.zip (378,8 KB)

Danke dort ist volgendes

 // The following lines can be uncommented to set the date and time
  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014

Ich finde die RTCLib
besser nimmt sich PC Zeit

 rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

url=GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC Arduino library