// Solar Warmwasserboiler Regent 1500W Stufen 240W / 360W / 480W #include #include #include // A4=SDA, A5=SCL https://arduinogetstarted.com/tutorials/arduino-lcd-i2c // Messeingänge - Aanalog #define phasedpin A0 #define phaseapin A1 #define phasebpin A2 #define phasecpin A3 #define phaselpin A6 #define phaseipin A7 // Digitalpins #define relxpin 2 #define relypin 3 #define relzpin 4 #define resetoutpin 7 #define netzpin 8 #define inselpin 9 #define testpinniedrig 10 #define testpinmittel 11 #define testpinhoch 12 // Testausgang #define boardledpin 13 // Display Objekt LiquidCrystal_I2C lcd(0x27, 16, 2); //Brabander I2C address 0x27, 16 column and 2 rows unsigned long startreset; unsigned long tagezaehler; bool netzeingang; unsigned long netzeingangist; unsigned long netzeingangstart; unsigned long netzentprellt; // Insel bool inselbetrieb; // Multivibrator / Taktgeber unsigned long mvstart; unsigned long mvist; const unsigned long mvinterval = 5000; // alle 5Sek. ein Takt bool mv; bool mvvorher; bool mvpuls; int werta; int wertb; int wertc; int wertd; int werti; int wertl; int wertp; int pa; // rechtes Solar-Panel int pb; // mittleres Solar-Panel int pc; // linkes Solar-Panel int pd; // Eigenverbrauch Netzbetrieb int pi; // Eigenverbtauch Inselbetrieb int pl; // Belastung int p; // Leistung allgemein int pges; // Leistung aller Solar-Panele zusammen int plast; // berechneter maximalwert für die Last int ertrag; int stufe; // eingestellte Leistung des Heizgerätes // constante Variablen const int richtwertniedrig = 240; const int richtwertmittel = 360; const int richtwerthoch = 480; int niedrig; int mittel; int hoch; // Relais bool last; bool relz; // hohe Last bool relzvorher; bool rely; // mittlere Last bool relyvorher; bool relx; // Freigabe für Last allgemein, kleine Last bool relxvorher; bool umschalten; bool wartenyz; bool wartenyzvorher; unsigned long startwyz = 0; unsigned long istwyz; bool wartenx; unsigned long startwx; unsigned long istwx; // hanfun für FritzT Dect int zahl; int hanfun; bool debugg = 1; // Funktionsprototypen ** Brauch ich für meine IDE ** void strommessen(void); void leistung(void); void displaybeschreiben(void); void listep(void); void ini_IO(void); void defult_IO(void); void ini_display(void); void setup() { Serial.begin(115200); if(debugg){Serial.println("ini-display");} ini_display(); if(debugg){Serial.println("ini-display done.");} plast = 0; if(debugg){Serial.println("ini-IO");} ini_IO(); if(debugg){Serial.println("ini-IO done.");} if(debugg){Serial.println("ini-defult IO");} defult_IO(); if(debugg){Serial.println("defult_IO done.");} niedrig = richtwertniedrig; mittel = richtwertmittel; hoch = richtwerthoch; Serial.println("Setup done."); } void loop() { // Reset alle 24h. Eine Sekunde vorher fällt Relais X ab. // Reset für arduino, nachts aktivieren. if (millis() > 86400000) { relx = LOW; } if (millis() > 86401000) { digitalWrite(resetoutpin, LOW); } // Reset Ende // Netz Frequenzmessung und Abwurf bei 51,5Hz netzeingang = digitalRead(netzpin); //Netzentprellung aktiv low if (netzeingang == HIGH) { netzeingangist = micros(); if (netzeingangist - netzeingangstart > 1000) { netzentprellt = LOW; } }else { netzeingangstart = micros(); netzentprellt = HIGH; } // Inselbetrieb inselbetrieb = !digitalRead(inselpin); /* Wieso kein Timer der alle 5 Sekunden ein Interrupt auslöst und eine Flag setzt? */ // Multivibrator mvist = millis(); // Multivibrator if (mvist - mvstart >= mvinterval) { mvstart = mvist; mv = mv^1; // if (mv == LOW) { // mv = HIGH; // }else { // mv = LOW; // } } // Multivibrator Ende if (mv != mvvorher) { // Multivibratorflanken mvpuls = HIGH; strommessen(); leistung(); displaybeschreiben(); }else { mvpuls = LOW; } mvvorher = mv; if (mvpuls == HIGH) { strommessen(); leistung(); displaybeschreiben(); } // Umschalten der Last auf fritz-dect-hanfun if ((last && mvpuls) == HIGH) { // Zählen der Taktimpulse zahl++; // zahl = (zahl + 1); } if (last == LOW) { zahl = 0; } if ((zahl > 2) && (pl < 100 )) { hanfun = HIGH; }else { hanfun = LOW; } // Relaissteuerung // Relais X fällt ab während die Relais Y und Z umschalten. if ((relx != relxvorher) || (rely != relyvorher) || (relz != relzvorher)) { umschalten = HIGH; }else { umschalten = LOW; } relxvorher = relx; relyvorher = rely; relzvorher = relz; if (umschalten == LOW) { istwyz = millis(); if (istwyz - startwyz > 200) { wartenyz = LOW; } }else { startwyz = millis(); wartenyz = HIGH; } if (umschalten == LOW) { istwx = millis(); if (istwx - startwx > 400) { wartenx = LOW; } }else { startwx = millis(); wartenx = HIGH; } digitalWrite(relxpin, (relx && !wartenx)); if ((wartenyz != wartenyzvorher) && (wartenyzvorher == HIGH)) { digitalWrite(relypin, rely); digitalWrite(relzpin, relz); } wartenyzvorher = wartenyz; // Testpin 13 boardled if (inselbetrieb == LOW) { digitalWrite(boardledpin, netzentprellt); }else { digitalWrite(boardledpin, LOW); } } // ?????? void strommessen() { werta = analogRead(phaseapin); wertb = analogRead(phasebpin); wertc = analogRead(phasecpin); wertd = analogRead(phasedpin); werti = analogRead(phaseipin); wertl = analogRead(phaselpin); } void leistung() { // für R=3K3 // 0,5A 0,47V // 0,5A*230V=115W // (0,47/5V)*1023=94 // 2,5A 4,20V // 2,5A*230V=575W // (4,20V/5V)*1023=859 if (werta >= 96 && werta <= 859) { pa = map(werta, 96, 859, 115, 575); }else { wertp = werta; listep(); pa = p; } if (wertb >= 96 && wertb <= 859) { pb = map(wertb, 96, 859, 115, 575); }else { wertp = wertb; listep(); pb = p; } if (wertc >= 96 && wertc <= 859) { pc = map(wertc, 96, 859, 115, 575); }else { wertp = wertc; listep(); pc = p; } if (wertd >= 96 && wertd <= 859) { pd = map(wertd, 96, 859, 115, 575); }else { wertp = wertd; listep(); pd = p; } if (wertl >= 96 && wertl <= 859) { pl = map(wertl, 96, 859, 115, 575); }else { wertp = wertl; listep(); pl = p; } if (werti >= 96 && werti <= 859) { pi = map(werti, 96, 859, 115, 575); }else { wertp = werti; listep(); pi = p; } // Anpassung der Stufen an die gemessenen Werte if ((stufe == niedrig) && (pl >= 190) && (pl < 300)) { niedrig = pl; }else { niedrig = richtwertniedrig; } if ((stufe == mittel) && (pl >= 300) && (pl < 420)) { mittel = pl; }else { mittel = richtwertmittel; } if ((stufe == hoch) && (pl >= 420) && (pl < 700)) { hoch = pl; }else { hoch = richtwerthoch; } pges = pa + pb + pc; // Gesamtscheinleistung der Solarpanele if (inselbetrieb == LOW) { ertrag = pges - pd; }else { ertrag = pges - pi; } if (digitalRead(testpinniedrig) == LOW){ relx = HIGH; rely = LOW; relz = LOW; stufe = niedrig; } else if (digitalRead(testpinmittel) == LOW){ relx = HIGH; rely = HIGH; relz = LOW; stufe = mittel; } else if (digitalRead(testpinhoch) == LOW){ relx = HIGH; rely = LOW; relz = HIGH; stufe = hoch; } else if (pd >= 700) { // schaltet nei großen Verbrauchern ab ertrag = 0; relx = LOW; rely = LOW; relz = LOW; stufe = 0; } else if (ertrag > niedrig && ertrag <= mittel){ relx = HIGH; rely = LOW; relz = LOW; stufe = niedrig; } else if (ertrag > mittel && ertrag <= hoch){ relx = HIGH; rely = HIGH; relz = LOW; stufe = mittel; } else if (ertrag > hoch){ relx = HIGH; rely = LOW; relz = HIGH; stufe = hoch; } else if (ertrag <= 0) { ertrag = 0; relx = LOW; rely = LOW; relz = LOW; stufe = 0; }else { relx = LOW; rely = LOW; relz = LOW; stufe = 0; } last = relx; } void displaybeschreiben() { // erste Zeile beschreiben lcd.setCursor(1, 0); // Stelle, Zeile lcd.print(" "); lcd.setCursor(1, 0); // Stelle, Zeile lcd.print(pc); // Links lcd.setCursor(6, 0); // Stelle, Zeile lcd.print(" "); lcd.setCursor(6, 0); // Stelle, Zeile lcd.print(pb); // Mitte lcd.setCursor(11, 0); // Stelle, Zeile lcd.print(" "); lcd.setCursor(11, 0); // Stelle, Zeile lcd.print(pa); // Rechts // zweite Zeile beschreiben if (inselbetrieb == LOW) { lcd.setCursor(0, 1); // Stelle, Zeile if (pd >= 700) { lcd.print("d> "); }else { lcd.print("d= "); } lcd.setCursor(2, 1); // Stelle, Zeile lcd.print(pd); }else { lcd.setCursor(0, 1); // Stelle, Zeile lcd.print("i= "); lcd.setCursor(2, 1); // Stelle, Zeile lcd.print(pi); } lcd.setCursor(6, 1); // Stelle, Zeile lcd.print(" "); lcd.setCursor(6, 1); // Stelle, Zeile if (relx && !rely && !relz) { lcd.print("n "); } else if (relx && rely && !relz) { lcd.print("m "); } else if (relx && !rely && relz) { lcd.print("h "); } else { lcd.print(" "); } lcd.setCursor(7, 1); // Stelle, Zeile if (hanfun == LOW) { lcd.print(stufe); // Leistung Regent Boiler }else { lcd.print(pl); } lcd.setCursor(11, 1); // Stelle, Zeile lcd.print(" "); lcd.setCursor(11, 1); // Stelle, Zeile lcd.print(pges); if (pges > 0) { lcd.backlight(); }else { lcd. noBacklight(); } } void listep() { if (wertp > 1022) { p = 700; } else if (wertp > 1013 && wertp < 1023) { p = 690; } else if (wertp > 999 && wertp < 1014) { p = 680; } else if (wertp > 985 && wertp < 1000) { p = 670; } else if (wertp > 972 && wertp < 986) { p = 660; } else if (wertp > 957 && wertp < 973) { p = 650; } else if (wertp > 942 && wertp < 958) { p = 640; } else if (wertp > 930 && wertp < 943) { p = 630; } else if (wertp > 915 && wertp < 931) { p = 620; } else if (wertp > 900 && wertp < 916) { p = 610; } else if (wertp > 892 && wertp < 901) { p = 600; } else if (wertp > 885 && wertp < 893) { p = 595; } else if (wertp > 874 && wertp < 886) { p = 590; } else if (wertp > 866 && wertp < 875) { p = 585; } else if (wertp > 859 && wertp < 867) { p = 580; } else if (wertp > 83 && wertp < 96) { p = 110; } else if (wertp > 75 && wertp < 84) { p = 105; } else if (wertp > 67 && wertp < 76) { p = 100; } else if (wertp > 59 && wertp < 68) { p = 95; } else if (wertp > 51 && wertp < 60) { p = 90; } else if (wertp > 44 && wertp < 52) { p = 85; } else if (wertp > 36 && wertp < 45) { p = 80; } else if (wertp > 29 && wertp < 37) { p = 75; } else if (wertp > 22 && wertp < 30) { p = 70; } else if (wertp > 16 && wertp < 23) { p = 65; } else if (wertp > 11 && wertp < 17) { p = 60; } else if (wertp > 6 && wertp < 12) { p = 55; } else if (wertp > 3 && wertp < 7) { p = 50; } else if (wertp > 1 && wertp < 4) { p = 45; }else { p = 0; } } void ini_IO(){ // Inputs pinMode(inselpin , INPUT_PULLUP); pinMode(testpinniedrig, INPUT_PULLUP); pinMode(testpinmittel , INPUT_PULLUP); pinMode(testpinhoch , INPUT_PULLUP); pinMode(netzpin , INPUT_PULLUP); // Outputs pinMode(relxpin, OUTPUT); pinMode(relypin, OUTPUT); pinMode(relzpin, OUTPUT); pinMode(boardledpin, OUTPUT); } void defult_IO(){ digitalWrite(relxpin, LOW); digitalWrite(resetoutpin, HIGH); } void ini_display(){ lcd.begin(); lcd.backlight(); // Beleuchtung an lcd.setCursor(0, 0); // Stelle, Zeile lcd.print("L M R "); // Solarpanel Links, Mitte, Rechts lcd.setCursor(0, 1); // Stelle, Zeile lcd.print(" "); }