habe mal mit der Ki zusammen ein Script für die 1/3 Phasen Umschaltung der Wallboxen gebastelt.
Wallbox Phasenumschaltung
🎛️ Belegung der Ein- und Ausgänge am Script-Baustein
Eingänge (Inputs):
* AI1 (In1): Soll-Leistung in Watt (vom PV-Energiemanager / Überschuss).
* AI2 (In2): Schwelle 3-Phasen in Watt (z. B. 4150).
* AI3 (In3): Schwelle 1-Phase in Watt (z. B. 3500).
* AI4 (In4): EV-Status vom Phoenix (Modbus Register 100).
* AI5 (In5): Spannung L1 vom Phoenix (Modbus Register 104).
* AI6 (In6): Mindestlaufzeit in Minuten (z. B. 10 oder 15).
* AI7 (In7): Freigabe Wallbox Manager (Vom Loxone Baustein, z. B. Ausgang Cp oder Ladestart-Logik).
* AI8 (In8): Gemessene Ist-Leistung (L1) vom Phoenix in Watt (vom Modbus-Zähler).
* AI9 (In9): Zählertyp (0 = 1-phasiger Zähler, 1 = 3-phasiger Zähler).
Ausgänge (Outputs):
* AQ1: Schütz 1-Phase (Digital-Ausgang an Loxone Relais).
* AQ2: Schütz 3-Phasen (Digital-Ausgang an Loxone Relais).
* AQ3: Modbus-Enable für Phoenix Controller (Holding Register 400 / 100).
* AQ4: Modbus-Ladestrom in Ampere (Holding Register 300).
* AQ5: Errechnete Ist-Leistung in Watt (Direkt für den Loxone Wallbox Manager Eingang Pe / Wirkleistung).
* AQ6: Fehlerausgang (Digital-Ausgang: 0 = Alles OK, 1 = Fehler Status E oder F aktiv).
* AQ7: Fahrzeug lädt (Digital-Ausgang: 1 = Lädt aktiv, 0 = Standby/Pause/Warten).
* AQ8: Fahrzeug angesteckt (Digital-Ausgang: 1 = Status B, C oder D).
und hier das Script
// Loxone PicoC Script mit ZOE-Anlaufverzögerung, Status-Auswertungen und Steck-Erkennung (AQ8)
int aktuellePhase = 1;
int umschaltPhase = 0;
float zielStrom = 0.0;
int phasenZeitZaehler = 0;
int ladeAnlaufZaehler = 0;
while(1) {
float sollLeistung = getinput(0);
float schwelle3p = getinput(1);
float schwelle1p = getinput(2);
float evStatus = getinput(3);
float netzSpannung = getinput(4);
int mindestLaufzeitMin = (int)getinput(5);
int managerFreigabe = (int)getinput(6);
float istLeistungModbus = getinput(7);
int zaehlerTyp = (int)getinput(8);
// Sicherheits-Fallback für Netzspannung
if (netzSpannung < 180.0 || netzSpannung > 260.0) {
netzSpannung = 230.0;
}
// Sekundenzähler für die aktuelle Phase hochzählen 30 Sekunden
if (phasenZeitZaehler < 30000) {
phasenZeitZaehler++;
}
// Ermittlung der gewünschten Zielphase basierend auf der Leistung
int zielPhase = aktuellePhase;
if (sollLeistung >= schwelle3p) {
zielPhase = 3;
} else if (sollLeistung < schwelle1p) {
zielPhase = 1;
}
int mindestLaufzeitSek = mindestLaufzeitMin * 60;
// --- FEHLERPRÜFUNG (Status E = 69 oder Status F = 70) ---
if (evStatus == 69 || evStatus == 70) {
setoutput(2, 0); // Modbus Enable AUS
setoutput(3, 0.0); // Ladestrom auf 0A
setoutput(0, 0); // 1p Schütz AUS
setoutput(1, 0); // 3p Schütz AUS
setoutput(4, 0.0); // Ist-Leistung auf 0W
setoutput(5, 1); // Fehlerausgang AQ6 auf 1
setoutput(6, 0); // Lade-Indikator AQ7 auf 0
setoutput(7, 0); // Angesteckt-Indikator AQ8 auf 0 bei Fehler
sleep(1000);
continue;
} else {
setoutput(5, 0); // Kein Fehler aktiv
}
// Umschaltung triggern unter Einhaltung der ZOE-Sicherheitszeiten & Mindestlaufzeit
if (zielPhase != aktuellePhase && umschaltPhase == 0 && evStatus > 65 && evStatus < 69 && phasenZeitZaehler >= mindestLaufzeitSek) {
umschaltPhase = 1;
setoutput(3, 0.0);
setoutput(2, 0);
setoutput(0, 0);
setoutput(1, 0);
setoutput(4, 0.0);
setoutput(6, 0);
// AQ8 bleibt während der Umschaltung auf 1, da das Auto physisch angesteckt bleibt
setoutput(7, 1);
sleep(10000); // Beruhigungszeit für die ZOE 10Sekunden
aktuellePhase = zielPhase;
if (aktuellePhase == 1) {
setoutput(0, 1);
} else {
setoutput(1, 1);
}
sleep(3000); // Schützkontakte stabilisieren 3Sekunden
phasenZeitZaehler = 0;
ladeAnlaufZaehler = 0;
umschaltPhase = 0;
}
// Regelbetrieb und Leistungsberechnung
if (umschaltPhase == 0) {
// --- 1. LADESTEUERUNG ---
if (managerFreigabe == 1 && evStatus > 65 && evStatus < 69) {
if (aktuellePhase == 1) {
zielStrom = sollLeistung / netzSpannung;
} else {
zielStrom = sollLeistung / (netzSpannung * 3.0);
}
if (zielStrom < 6.0) {
setoutput(2, 0);
setoutput(3, 0.0);
ladeAnlaufZaehler = 0;
} else {
if (zielStrom > 32.0) zielStrom = 32.0;
setoutput(3, zielStrom);
setoutput(2, 1);
if (ladeAnlaufZaehler < 100) {
ladeAnlaufZaehler++;
}
}
} else {
setoutput(2, 0);
setoutput(3, 0.0);
ladeAnlaufZaehler = 0;
if (evStatus <= 65) {
setoutput(0, 0);
setoutput(1, 0);
}
}
// --- 2. IST-LEISTUNGSBERECHNUNG & DYNAMISCHE AUSGÄNGE ---
float gesamteIstLeistung = 0.0;
int istAmLaden = 0;
int istAngesteckt = 0;
// AQ8 Steuerung: Angesteckt bei Zustand B (66), C (67) oder D (68)
if (evStatus >= 66 && evStatus <= 68) {
istAngesteckt = 1;
}
if (evStatus == 67 || evStatus == 68) {
if (istLeistungModbus > 10.0 || ladeAnlaufZaehler < 20) {
if (istLeistungModbus > 10.0) {
istAmLaden = 1;
}
if (zaehlerTyp == 1) {
gesamteIstLeistung = istLeistungModbus;
} else {
if (aktuellePhase == 1) {
gesamteIstLeistung = istLeistungModbus;
} else {
gesamteIstLeistung = istLeistungModbus * 3.0;
}
}
}
}
setoutput(4, gesamteIstLeistung); // Gesamtleistung an AQ5
setoutput(6, istAmLaden); // Lade-Indikator an AQ7
setoutput(7, istAngesteckt); // Angesteckt-Indikator an AQ8 (HIER NEU)
}
sleep(1000);
}
ich bin gespannt ob das funktioniert ![]()