Aquarien Steuerung einfach

Hallo,

ich verzweifel gerade so ein bisschen an meiner Aquariensteuerung.
Vieles läuft schon aber bei so ein paar Sachen weiß ich einfach ned was es bedeutet und kann darauf ned erschliessen welche Funktion dahinter verbirgt oder ws es macht. Vielleicht könnt ihr mich ja mal bisschen aufklären.
Folgende Sachen laufen schonmal:
Tempertursensoren Auslesen und werte nutzen und Anzeigen lassen.
Temperaturwerte nutzen um damit ein Relais An und Auszuschallten.
Ich habe keine Probleme oder nur sehr wenig mit verkabelung nur das Coden fällt mir sehr schwer da ich ein Blutiger Anfänger bin. Folgenden Code habe ich mir aus Programm-Schnippseln zusammenkopiert hier und da ne änderung vorgenommen Zusatzfunktionen eingefügt oder geändert.

#include <U8glib.h> //OLED Bibliothek
#include <U8x8lib.h> //OLED Bibliothek
#include <U8g2lib.h> //OLED Bibliothek
#include <DallasTemperature.h> //Digitale Temperaturfühler Bibliothek
#include <OneWire.h> // 1-KabelBus Bbliothek


U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0,/* clock=*/ 4, /* data=*/ 2, /* reset=*/ U8X8_PIN_NONE); //OLED TYP
static char outstr[15];
 const int Luefter = 5; //Relais Lüfter für Aquarium Temperatur
 const int Heiss = 6; //Relais Lüfter Steuerungselektronik und Netzteil

#define ONE_WIRE_BUS 3 //PIN Eingang für Digitale TemperaturSensoren
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

int numberOfDevices;
 DeviceAddress tempDeviceAddress;
void setup(void)
{
  pinMode(Luefter, OUTPUT); //Setze PIN Lüfter auf Ausgang
  pinMode(Heiss, OUTPUT); // Setze PIN Elektronik auf Ausgang

sensors.begin(); //BEginne start des Auslesens der Thermometer
numberOfDevices = sensors.getDeviceCount(); //Zähle die Anzahl der Digitalen Temperaturfühler
for(int i=0;i<numberOfDevices; i++)
if(sensors.getAddress(tempDeviceAddress, i))
Serial.print(numberOfDevices, DEC);
u8g2.begin();


delay(1000);
}
 
void loop(void)
{
sensors.requestTemperatures();
Serial.print("Temperature is: ");
Serial.println(sensors.getTempCByIndex(0));
if (sensors.getTempCByIndex(0) <25)
{digitalWrite(Luefter, HIGH);
}
else 
if (sensors.getTempCByIndex(0) >24)
  {digitalWrite(Luefter, LOW) ;
  }
dtostrf(sensors.getTempCByIndex(0),7, 1, outstr);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_profont22_tf);  //Fonts here https://github.com/olikraus/u8g2/wiki/fntlistall
u8g2.drawStr(30,14, "Wasser");
u8g2.drawStr(4,30,outstr);
u8g2.sendBuffer();
delay(1000);


sensors.requestTemperatures();
Serial.print("Temperature is: ");
Serial.println(sensors.getTempCByIndex(1));
if (sensors.getTempCByIndex(1) <25)
{digitalWrite(Heiss, HIGH);
}
else 
if (sensors.getTempCByIndex(1) >24)
  {digitalWrite(Heiss, LOW) ;
  }
dtostrf(sensors.getTempCByIndex(1),7, 1, outstr);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_profont22_tf);  //Fonts here https://github.com/olikraus/u8g2/wiki/fntlistall
u8g2.drawStr(0,14, "Elektronik");
u8g2.drawStr(4,30,outstr);
u8g2.sendBuffer();
delay(1000);
}

Soweit funktioniert das schonmal folgenden String verstehe ich nur noch nicht so ganz :
static char outstr[15]; 
Ich weiss das es eine dauerhafte Variable ist die nur von einer Funkton gesehen oder Verändert werden darf aber was hat es mit er klammer auf sich? Und wieso kann ich in diesem teil:
dtostrf(sensors.getTempCByIndex(1),7, 1, outstr);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_profont22_tf);  //Fonts here https://github.com/olikraus/u8g2/wiki/fntlistall
u8g2.drawStr(0,14, "Elektronik");
u8g2.drawStr(4,30,outstr);
u8g2.sendBuffer();
delay(1000);

Keine zusatzausgabe machen das er mir das C von Celsius anzeigt?

Habe noch vor eine kleine Zeitsteuerung einzubauen aber ich weiß noch ned so ganz wie man das “einfach” realisieren kann. Ich möchte einfach nur das der Arduino einen RTC ausliest und dann sagen wir mal Morgens 7:00 Uhr ein relais Anschaltet und Abends um 20 Uhr aus. Wenn ich mir da so Beispiele Anschaue dann Sind das ja teilweise über 150 Zeilen nur um ein Relais um eine Uhrzeit zu Schalten geht das ned bissel “einfacher”? Denn aktuell sind schon mit dem Bissel Code der da Oben steht ca 69% des Speichers belegt.

Freue mich schon über eure Kommentare.

P.S. Genutzte Hardware
Arduino Nano
4-fach Relais
Univision Oled 128x32

Hi

Mir ist nicht bekannt, ob Lib's, Die Du nicht benutzt, aktiv Speicherplatz brauchen.
Du bindest DREI Lib's für Dein OLED ein - verwendet wird davon wohl nur Eine.
Drücke auch bitte Mal STRG+T in der IDE - Das rückt den Code der Ebene entsprechend ein - lässt sich gleich viel besser lesen.
Dein Kommentar im Code soll so?

Die Klammer [15] besagt, daß das CHAR-Element 15 Zeichen lang ist - also Platz für maximal 14 Zeichen + Null-Terminator.
Ist ein C-String (string mit kleinem s) und bietet einem String (mit großem S) den Vorteil, daß der Speicher nicht fragmentiert, da nur 1x angelegt und direkt in der passenden Länge.

Wo Dein C ist? kA, ist mir nicht unter gekommen.

MfG

Hallo,

also konnte zwei OLED Libs entfernen, leider hat es keinen Platz frei gemacht aber gut ist logisch.
Danke für den Tipp mit STRG+T sieht definitiv besser aus.
Ehm ja mit den Kommentaren habe ich mal angefangen aber so ganz Richtig sind die noch nicht.
Daran sieht man aber auch wie ich versuche die Zeilen zu verstehen.

Okay also wenn ich es richtig verstanden habe dann ist dieses Static Char ein fest definierter Speicherplatz wo ich 14 buchstaben oder zahlen drin abspeichern kann? Und diese Zeile bzw die Code Stücke die damit Verbunden sind sorgen dafür das er die ausgelesenen Werte vom Temp-Fühler dort hineinschreibt und bei der OLED ausgabe in der zweiten Zeile wieder einfügt?

Ehm Das C habe ich noch nicht eingefügt ich habe schon verschiedene sachen Probiert aber ich kam dann nur noch auf Fehlermeldungen hinaus mt denen ich nichts anfangen kann. Deswegen ist die Frage wo soll ich in den Code den Teil einfügen das er mir dann im Display z.b anzeigt:


| Wasser |

25.5C

?

Genau so mit u8g2.drawStr(x,y,"C");

Gruß Tommy

Deswegen ist die Frage wo soll ich in den Code den Teil einfügen

Am einfachsten da, wo du auch den anderen Text erzeugst

u8g2.drawStr(30,14, "Wasser");
u8g2.drawStr(4,30,outstr);
u8g2.drawStr (38,30, "C");

Fummeliger ist es, die schönsten Koordinaten für den Text zu finden.

Boah sehr geil okay jetzt hab ich das system verstanden :grin: .
Ich habe das so ein wenig vertauscht mit den ZeilenDisplays und habe nicht dran gedacht das das OLED
wie ein Koordinatensystem benutzt wird.
Geil Danke das Funktioniert.
Hat denn jemand vielleicht noch eine Idee wie ich eine einfache Zeitschaltung integrieren kann?

Schau Dir BlinkWithoutDelay in den Beispielen Deiner IDE an und verstehe es.

Gruß Tommy

Hallo,

mit viel Gedudel habe ich jetzt einen relativ gut lauffähigen Sketch.
Ich habe sogar Uhrzeit Einbinden können Via GPS was hier noch rumflog und mir keinen nutzen mehr brachte.
Nun wollte ich aber eigentlich noch versuchen Die Zeitschaltuhr zu Integrieren aber ich laufe jetzt schon im Speicherlimit. Wie kann ich den ganzen Sketch noch etwas verkleinern oder muss ich jetzt zu einem anderen Arduino greifen?

#include <U8g2lib.h> //OLED Bibliothek
#include <DallasTemperature.h> //Digitale Temperaturfühler Bibliothek
#include <OneWire.h> // 1-KabelBus Bbliothek
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#include <SPI.h>
#include <U8g2lib.h>
#include <Timezone.h>
#define ONE_WIRE_BUS 3 //PIN Eingang für Digitale TemperaturSensoren
int numberOfDevices;
static char outstr[15];
const int Luefter = 5; //Relais Lüfter für Aquarium Temperatur
const int Heiss = 6; //Relais Lüfter Steuerungselektronik und Netzteil
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0,/* clock=*/ 4, /* data=*/ 2, /* reset=*/ U8X8_PIN_NONE); //OLED TYP
// GPS handle  
TinyGPSPlus gps;  
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;
// Serial handle
SoftwareSerial softSerial(10, 11);
// Central European Time
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};   // Central European Standard Time
Timezone CE(CEST, CET);
TimeChangeRule *tcr;
void setup(void)
{
  pinMode(Luefter, OUTPUT); //Setze PIN Lüfter auf Ausgang
  pinMode(Heiss, OUTPUT); // Setze PIN Elektronik auf Ausgang
  softSerial.begin(9600);
  sensors.begin(); //BEginne start des Auslesens der Thermometer
  numberOfDevices = sensors.getDeviceCount(); //Zähle die Anzahl der Digitalen Temperaturfühler
  for (int i = 0; i < numberOfDevices; i++)
    if (sensors.getAddress(tempDeviceAddress, i))
      Serial.print(numberOfDevices, DEC);
  setTime(00, 00, 00, 01, 01, 1970);
  u8g2.begin();


  delay(1000);
}

void loop(void)
{
  sensors.requestTemperatures();
  Serial.print("Temperature is: ");
  Serial.println(sensors.getTempCByIndex(0));
  if (sensors.getTempCByIndex(0) < 25)
  { digitalWrite(Luefter, HIGH);
  }
  else if (sensors.getTempCByIndex(0) > 24)
  { digitalWrite(Luefter, LOW) ;
  }
  dtostrf(sensors.getTempCByIndex(0), 7, 1, outstr);
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_profont22_tf);  //Fonts here https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(30, 14, "Wasser");
  u8g2.drawStr(4, 30, outstr);
  u8g2.drawStr(90, 30, "C");
  u8g2.sendBuffer();
  delay(1000);


  sensors.requestTemperatures();
  Serial.print("Temperature is: ");
  Serial.println(sensors.getTempCByIndex(1));
  if (sensors.getTempCByIndex(1) < 25)
  { digitalWrite(Heiss, HIGH);
  }
  else if (sensors.getTempCByIndex(1) > 24)
  { digitalWrite(Heiss, LOW) ;
  }
  dtostrf(sensors.getTempCByIndex(1), 7, 1, outstr);
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_profont22_tf);  //Fonts here https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(0, 14, "Elektronik");
  u8g2.drawStr(4, 30, outstr);
  u8g2.drawStr(90, 30, "C");
  u8g2.sendBuffer();
  delay(1000);

  //GPS ZEIT ANZEIGE
  readGPSData(100);  
  updateTime();  
  displayTime();  
  delay(1000);
}
static void readGPSData(unsigned long timeoutMs)  
{  
  unsigned long start = millis();  
  do  
  {  
    while (softSerial.available())  
      gps.encode(softSerial.read());  
  } while (millis() - start < timeoutMs);  
}  
  
static void updateTime(void) {  
  if (gps.time.isValid() && gps.date.isValid()) {  
    setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), gps.date.day(), gps.date.month(), gps.date.year());  
  }  
}  
  
static void displayTime(void)  
{  
  const unsigned timeLength = 6;  
  char timeValue[timeLength];  
  time_t utc = now();  
  time_t local = CE.toLocal(utc, &tcr);  
  snprintf(timeValue, timeLength, "%02d:%02d", hour(local), minute(local));  
  u8g2.firstPage();  
  do {  
    u8g2.setFont(u8g2_font_bubble_tr);  
    u8g2.drawStr(20, 30, timeValue);  
    } while (u8g2.nextPage());  
}

Der Sketch verwendet 30008 Bytes (97%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 1683 Bytes (82%) des dynamischen Speichers, 365 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.

Hi

Tragen Deine Fische Armbanduhren? Nein -> Zeitumstellung unnötig, Lib raus
Du bindest die u8g2lib 2x ein - das wird die Lib wohl verhindern (wenn's der Kompiler nicht schon tut), ist aber unschön.
Temperaturen von Sensor 0 und Sensor 1 haben identischen Code - bis auf 'Elektronik' und 'Wasser' bzw 'Heiss' und 'Luefter' - oder?
Könnte Dir ein paar Byte sparen, wenn Du die Funktionalität in eine Funktion stopfst und Der nur die Sensor-Nummer (0/1) übergibst und Diese dann den entsprechenden Sensor ausliest, den entsprechenden Text ausgibt und den entsprechenden Ausgang schaltet.

Du wirfst mehrere Datenströme vom GPS-Modul weg (ignorierst Diese, da Du im delay() wartest) - Du bekommst nur alle drei Sekunden (frühestens) einen Schwung eingelesen.
Ok, Datum/Uhrzeit ist so ziemlich in jedem der Datenpakete enthalten, denke, darauf baut Dein Sketch hier auf??
Da Du NUR Datum und Uhrzeit haben willst, könntest Du diese Datenströme auch von Hand parsen - wenn bei zwei nacheinander eingelesenen Strömen Datum und Uhrzeit identisch sind, dürfte diese Information soweit korrekt sein (Prüfsumme ect.pp. egal) - was welcher Sattelit wie sendet, weiß Wikipedia, bei der Suche nach GPS gibt's aber eh mannigfaltige Infos zum Aufbau.

Die Display-Lib müsste es hergeben, daß Du mit einem kleinerem Puffer arbeiten kannst - dann wird das Bild mehrfach (bei halbem Puffer 2 Mal) aufgebaut und die Lib schickt nur Das ans Display, was in diesem 'Bereich' im Puffer steht.

An Deiner Steppe würde ich das GPS-Zeug wieder raus nehmen und dafür eine RTC (DS3231 o.Ä.) verwenden - Der gibst Du 1x die aktuelle Zeit (per Beispiel-Sketch, Uhrzeit/Datum wird per Terminal eingestellt, danach kommt die RTC ans Aquarium und gut ist's). und das nächste Jahr wirst Du mit einer Ungenauigkeit von wenigen Sekunden leben müssen.

Für 'Mehr' habe ich den A*sch zu tief :wink:

MfG

Hi danke erstmal für die Antwort.

postmaster-ino:
Hi

Tragen Deine Fische Armbanduhren? Nein -> Zeitumstellung unnötig, Lib raus

Nein die tragen echt keine Armbanduhr es war lediglich Gedacht um zu prüfen ob ich so eine Zeit bekomme mit der ich Arbeiten kann was ja geklappt hat das dass GPS so viel Speicher braucht, dachte ich kann es alternative nutzen für die Zeitsteuerung.

Du bindest die u8g2lib 2x ein - das wird die Lib wohl verhindern (wenn's der Kompiler nicht schon tut), ist aber unschön.

Ohje da hab ich wohl beim Copy/pasten was übersehen.....

Temperaturen von Sensor 0 und Sensor 1 haben identischen Code - bis auf 'Elektronik' und 'Wasser' bzw 'Heiss' und 'Luefter' - oder?

Ehm also ich habe das so verstanden das der Script hingeht zählt die Anzahl der Sensoren DS18B20-1 nächster Ds18B20-2 und speichert die im outstring ab dort kannn ich dann die daten ja auch wieder abrufen oder sehe ich das Falsch und ich brauche diesen outstring garnicht? Ich möchte Eigentlich damit errichen das ich auf meinem Display nacheinander Angezeigt bekomme Welche Temp mein Wasser hat und welche die Elektronik. Mit Lüfter an und Heiss möchte ich meine Relais für die Temperaturüberwachung steuern.

Könnte Dir ein paar Byte sparen, wenn Du die Funktionalität in eine Funktion stopfst und Der nur die Sensor-Nummer (0/1) übergibst und Diese dann den entsprechenden Sensor ausliest, den entsprechenden Text ausgibt und den entsprechenden Ausgang schaltet.

Ehm Also soll ich es so deklarieren das ich statt "Luefter" eine Zahl habe?
int 1 //Luefter
?

Du wirfst mehrere Datenströme vom GPS-Modul weg (ignorierst Diese, da Du im delay() wartest) - Du bekommst nur alle drei Sekunden (frühestens) einen Schwung eingelesen.
Ok, Datum/Uhrzeit ist so ziemlich in jedem der Datenpakete enthalten, denke, darauf baut Dein Sketch hier auf??
Da Du NUR Datum und Uhrzeit haben willst, könntest Du diese Datenströme auch von Hand parsen - wenn bei zwei nacheinander eingelesenen Strömen Datum und Uhrzeit identisch sind, dürfte diese Information soweit korrekt sein (Prüfsumme ect.pp. egal) - was welcher Sattelit wie sendet, weiß Wikipedia, bei der Suche nach GPS gibt's aber eh mannigfaltige Infos zum Aufbau.
An Deiner Steppe würde ich das GPS-Zeug wieder raus nehmen und dafür eine RTC (DS3231 o.Ä.) verwenden - Der gibst Du 1x die aktuelle Zeit (per Beispiel-Sketch, Uhrzeit/Datum wird per Terminal eingestellt, danach kommt die RTC ans Aquarium und gut ist's). und das nächste Jahr wirst Du mit einer Ungenauigkeit von wenigen Sekunden leben müssen.

Okay also damit hat sich das dann ja erledigt mit GPS und Zeit dann werde ich mal versuchen mir solch ein Ds3231 zu Organisieren. Eigentlich wollte ich nur eine Uhrzeit damit ich Schalten kann zu gewissen vordefinierten Urhzeiten.

Die Display-Lib müsste es hergeben, daß Du mit einem kleinerem Puffer arbeiten kannst - dann wird das Bild mehrfach (bei halbem Puffer 2 Mal) aufgebaut und die Lib schickt nur Das ans Display, was in diesem 'Bereich' im Puffer steht.

Ich glaube ich habe sogar schon die kleine version genutzt bin mir aber nicht ganz sicher nur wollte ich nicht nur mit dem reinen U8x8 Protokoll arbeiten. Aber ich schaue da nochmal nach da ist irgendwo ein unterschied mit Buffer und Page

Für 'Mehr' habe ich den A*sch zu tief :wink:

MfG

Auch noch ned gehört aber trotzdem vielen Dank

Hi

Nur 'an den Haaren herbeigezogen':

dtostrf(sensors.getTempCByIndex(1), 7, 1, outstr);

Damit schreibst Du wohl 7 Stellen ab Stelle 1 in den c-String outstr.
Das machst Du bei beiden Sensoren, einzig die (1) ist vorher eine (0).
Das meinte ich mit 'Wasser' + 'Luefter' bzw 'Elektronik' + 'Heiss'.
Bei 0 nimmst Du den Text Wasser, sonst Elektronik.
Bei 0 schaltest Du Luefter, sonst Heiss.
Und klar, bei 0 liest Du den Sensor [0], sonst [1].
Die Texte bleiben Dir als Ballast erhalten, das Drum herum, also die Funktionalität, kannst Du 1x einsparen, erkauft mit zwei/drei IF-Abfragen für den einzulesenden Sensor, den auszugebenden Text und den zu schaltenden Ausgang.

MfG

outString ist einfach ein Puffer für die Text-Ausgabe. dtostrf() (double to string) dient zur Formatierung von Gleitkommazahlen, da printf() das auf AVR Prozessoren nicht unterstützt:

https://www.mikrocontroller.net/topic/86391
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

7, 1 bedeutet demnach minimal insgesamt 7 Zeichen mit einer Nachkommastelle

Du kannst damit Gleitkommazahlen auf eine konstante Breite formatieren. Der Rest wird mit Leerzeichen aufgefüllt. Das muss man bei LCDs machen weil sonst alte Zeichen stehen bleiben wenn der neue Text nicht die gleiche Breite hat

Huhu,

ich freue mich gerade wie ein Schnitzel.
Ich habe meinen Lauffähigen Skript nun Fertig Optimal ist anders das ist mir klar aber ich bin Stolz das es so Funktioniert und ich denke jetzt kann ich mich an die Feinheiten machen. Ich habe ein klitzekleines bisschen im Code aufgeräumt… Den Versuch mit millis() habe ich gewagt aber das ging völligst in die hose. Mein Display hat dann nur noch Random zwischen den Anzeigen herumgeswitcht und nicht mehr wie mit den Delays trotz das ich den Millis in den einzelnen “Aufgaben” eigene werte eingefügt hatte.

Ich habe mir auch mal die Nachtwächter Erklärung angeschaut aber ich bekomme sie ums verrecken ned für das Display eingebunden.

Wenn ihr möchtet schaut euch doch mal meine Alpha an:

#include <U8g2lib.h>           //OLED Bibliothek
#include <DallasTemperature.h> //Digitale Temperaturfühler DS18B20 Bibliothek
#include <OneWire.h>           // 1-KabelBus Bibliothek
#include <SPI.h>               //SPI/I2C Bibliothek
#include <DS3231.h>            /Bibliothek Echtzeituhr

#define ONE_WIRE_BUS 3 //PIN Eingang für Digitale TemperaturSensoren
static char outstr[15];//Speicherslot für gemessene aktuelle Temperaturen 
int numberOfDevices; //Speicherslot für DS18B20 Fühleranzahl
int TLstd = 18;      //einschaltzeit Taglicht Stunde
int TLmin = 05;      //einschaltzeit Taglicht Minute
int NLstd = 18;      //Umschaltzeit Nachtlicht Stunde
int NLmin = 30;      //Umschaltzeit Nachtlicht Minute 
int LR = 7;          //Lichtrelais PIN 7
int KAQ = 5;         //Relais Lüfter für Aquarium Temperatur senken
int PCBHot = 6;      //Relais Lüfter Steuerungselektronik und Netzteil wenn zu heiss
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);      //OLED TYP, Schnittstelle

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;
RTClib RTC;

void setup(void)
{
  pinMode(KAQ,    OUTPUT);                    //Setze PIN Lüfter auf Ausgang
  pinMode(PCBHot, OUTPUT);                    //Setze PIN Elektronik auf Ausgang
  pinMode(LR,     OUTPUT);                    //Setze PIN Lichtrelais auf Ausgang
  sensors.begin();                            //BEginne start des Auslesens der Thermometer
  numberOfDevices = sensors.getDeviceCount(); //Zähle die Anzahl der Digitalen Temperaturfühler
  for (int i = 0; i < numberOfDevices; i++)
    if (sensors.getAddress(tempDeviceAddress, i))
  u8g2.begin();
  Wire.begin();
digitalWrite(KAQ,HIGH);
digitalWrite(PCBHot,HIGH);
digitalWrite(LR,HIGH);
}

void loop(void)
{
  sensors.requestTemperatures();

  if (sensors.getTempCByIndex(0) < 25)
  { digitalWrite(KAQ, HIGH);
  }
  else if (sensors.getTempCByIndex(0) > 24)
  { digitalWrite(KAQ, LOW) ;
  }
  dtostrf(sensors.getTempCByIndex(0), 7, 1, outstr);
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_profont22_tf);  //Fonts here https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(30, 14, "Aquarium");
  u8g2.drawStr(4, 30, outstr);
  u8g2.drawStr(90, 30, "C");
  u8g2.sendBuffer();
  delay(2500);


  sensors.requestTemperatures();

  if (sensors.getTempCByIndex(1) < 25)
  { digitalWrite(PCBHot, HIGH);
  }
  else if (sensors.getTempCByIndex(1) > 24)
  { digitalWrite(PCBHot, LOW) ;
  }
  dtostrf(sensors.getTempCByIndex(1), 7, 1, outstr);
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_profont22_tf);  //Fonts here https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(0, 14, "Elektronik");
  u8g2.drawStr(4, 30, outstr);
  u8g2.drawStr(90, 30, "C");
  u8g2.sendBuffer();
  delay(2500);

  for (int i = 0; i < 3; i++) {
    delay(1000);
    DateTime now = RTC.now();
    u8g2.clearBuffer();
    u8g2.setFont( u8g2_font_timB24_tn);                     // Font
    u8g2.setCursor(0, 24);                            // Kursor
    if (now.hour() < 10)
      u8g2.print("0");
    u8g2.print(now.hour());                            // Write hour
    u8g2.print(":");
    if (now.minute() < 10)
      u8g2.print("0");
    u8g2.print(now.minute());                           // Write hour
    u8g2.print(":");
    if (now.second() < 10)
      u8g2.print("0");
    u8g2.print(now.second());
    u8g2.sendBuffer();
  }

//Licht relais
DateTime now = RTC.now();
 if(TLstd <= (now.hour()) && TLmin <= (now.minute())) {digitalWrite(LR, LOW);} // Taglicht AN Nachtlicht AUS
 if(NLstd <= (now.hour()) && NLmin <= (now.minute ())) {digitalWrite(LR,HIGH);} // NAchtlicht AN Taglicht AUS

}

Wenn ihr noch Ideen habt wie ich den Code etwas Optimieren kann oder wie ich z.b. das mit den Millis und dem Display zugeordnet bekomme gebt mir doch mal nen kleines beispiel. Musste halt wieder das Delay einfügen was jetzt noch ned so schlimm ist aber wenn ich die Steuerung erweiter komm ich bestimmt noch auf dumme Ideen wie “Vollautomatischer Wasser wechsel” oder so.

Auf jedenfall bin ich euch schonmal sehr Dankbar