Repository navigation
Description
Umgebung
- openWB series2 mit interner Phasenumschaltung (EVSE DIN an /dev/ttyUSB0, Modbus-ID 1)
- Release 2.3.0 (
8c58e4b84), Betrieb als "primary" mit internem Ladepunkt (LP3) - Fahrzeug: Audi A6 e-tron (2025, PPE-Plattform), 1-/3-phasig, Lademodus PV mit automatischer Phasenumschaltung
- Unter 2.2.1 (
82510a223) lief die Phasenumschaltung mit demselben Fahrzeug über Monate ohne Auffälligkeiten.
Beschreibung
Seit dem Update auf 2.3.0 scheitert die Phasenumschaltung regelmäßig, mit zwei verschiedenen Symptomen:
- Fahrzeug meldet "Ladenetz Fehler" und nimmt die Ladung nicht wieder auf. Die Wallbox zeigt danach dauerhaft
"Strom freigegeben, warten auf Fahrzeug". Nach Ablauf der Wartezeit löst 2.3.0 eine CP-Unterbrechung aus
(neue Logik "Auto lädt trotz Freigabe nicht"), die ebenfalls nichts bringt. Erst Ent- und Verriegeln des
Fahrzeugs setzt den Fehler im Auto zurück. - Umschaltung bricht mit Modbus-Fehler ab, Phasenzahl bleibt falsch.
perform_phase_switchwirft
Modbus Error: [Invalid Message] No response receivedbeim Rücklesen der EVSE, die GPIO-Aktion findet nicht
statt, das Relais bleibt auf der alten Phasenzahl, die Regelung gibt mit der neuen Soll-Phasenzahl wieder
Strom frei. Ladung kommt nicht zustande.
Beide Symptome lassen sich auf 1e41b2080 (#3326, "EVSE-Ruecklesen vor Phasenumschaltung") zurückführen,
siehe Abschnitt Ursache.
Ablauf am 06.11.2026 (Log-Auszüge)
Die Logs lagen bis 13:14 auf WARNING, daher ist für die erste Umschaltung nur der Zeitstempel und das
Verhalten dokumentiert; ab 13:14:05 DEBUG.
13:10:34 Umschaltung 1 → 3 Phasen (Wechsel PV → Sofortladen, Auto lud 1-phasig mit ca. 3,4 kW):
timestamp_last_phase_switch = 1793967034(= 13:10:34)- Auto zeigt sofort "Ladenetz Fehler", Wallbox "Strom freigegeben, warten auf Fahrzeug", keine Ladung.
- 13:14:05 greift die neue CP-Unterbrechungs-Logik von 2.3.0:
2026-11-06 13:14:05,658 - {modules.internal_chargepoint_handler.internal_chargepoint_handler:44} - {DEBUG:Internal Chargepoint} - Values from parentWB: InternalChargepointData(cp_interruption_duration=5, parent_cp='3', phases_to_use=3, ...
2026-11-06 13:14:05,784 - {modules.internal_chargepoint_handler.internal_chargepoint_handler:80} - {DEBUG:Internal Chargepoint} - Thread zur CP-Unterbrechung an LP0 gestartet.
2026-11-06 13:14:07,113 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 0, Status: 1, Modbus-ID: 1
2026-11-06 13:14:13,517 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 600, Status: 2, Modbus-ID: 1
Das Auto bleibt in Status 2 (angesteckt, lädt nicht). Daraufhin Wechsel zurück auf PV (1-phasig):
2026-11-06 13:14:24,947 - {control.chargepoint.chargepoint:74} - {INFO:MainThread} - LP 3: Die Ladung wird gestartet, sobald in 29 Sek. die Wartezeit abgelaufen ist.
2026-11-06 13:14:34,150 - {control.chargepoint.chargepoint:74} - {INFO:MainThread} - LP 3: Die Ladung wird gestartet, sobald in 20 Sek. die Wartezeit abgelaufen ist.
2026-11-06 13:14:45,398 - {control.chargepoint.chargepoint:74} - {INFO:MainThread} - LP 3: Die Ladung wird gestartet, sobald in 9 Sek. die Wartezeit abgelaufen ist.
13:15:07 Umschaltung 3 → 1 Phasen, Abbruch durch Modbus-Fehler:
2026-11-06 13:15:07,031 - {control.phase_switch:17} - {DEBUG:MainThread} - Starte Thread zur Phasenumschaltung an LP3
2026-11-06 13:15:07,036 - {control.chargepoint.chargepoint:432} - {DEBUG:MainThread} - start phase switch phases_to_use 3 control_parameter phases 1
2026-11-06 13:15:09,820 - {modules.internal_chargepoint_handler.internal_chargepoint_handler:44} - {DEBUG:Internal Chargepoint} - Values from parentWB: InternalChargepointData(cp_interruption_duration=0, parent_cp='3', phases_to_use=1, set_current=0, trigger_phase_switch=True)
2026-11-06 13:15:09,966 - {modules.internal_chargepoint_handler.internal_chargepoint_handler:59} - {DEBUG:Internal Chargepoint} - Switch Phases from 0 to 1
2026-11-06 13:15:09,978 - {modules.internal_chargepoint_handler.internal_chargepoint_handler:73} - {DEBUG:Internal Chargepoint} - Thread zur Phasenumschaltung an LP0 gestartet.
2026-11-06 13:15:11,198 - {modules.common.modbus:91} - {DEBUG:perform phase switch 0} - Close Modbus TCP connection
2026-11-06 13:15:11,209 - {modules.common.fault_state:47} - {ERROR:perform phase switch 0} - Ladepunkt 0: FaultState FaultStateLevel.ERROR, FaultStr modules.common.modbus <class 'Exception'> modules.common.modbus Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 2 bytes (0 received), Traceback:
Traceback (most recent call last):
File "/var/www/html/openWB/packages/modules/common/modbus.py", line 121, in __read_registers
raise Exception(__name__+" "+str(response))
Exception: modules.common.modbus Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 2 bytes (0 received)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/var/www/html/openWB/packages/modules/internal_chargepoint_handler/chargepoint_module.py", line 150, in perform_phase_switch
_, _, evse_current = evse.get_plug_charge_state()
File "/var/www/html/openWB/packages/modules/common/evse.py", line 53, in get_plug_charge_state
raw_set_current, _, state_number = self.client.read_holding_registers(
File "/var/www/html/openWB/packages/modules/common/modbus.py", line 153, in read_holding_registers
return self.__read_registers(
File "/var/www/html/openWB/packages/modules/common/modbus.py", line 136, in __read_registers
raise Exception(__name__+" "+str(type(e))+" " + str(e)) from e
Exception: modules.common.modbus <class 'Exception'> modules.common.modbus Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 2 bytes (0 received)
Danach: keine GPIO-Aktion, Relais bleibt auf 3 Phasen, Soll-Phasenzahl 1, Regelung gibt 6 A frei, Auto bleibt
im Fehlerzustand:
2026-11-06 13:15:13,363 - ... get=Get(charge_state=False, currents=[0.0, 0.0, 0.0], evse_current=0.0, ... fault_str="modules.common.modbus <class 'Exc...
2026-11-06 13:15:18,066 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 600, Status: 2, Modbus-ID: 1
2026-11-06 13:15:15,990 - {helpermodules.changed_values_handler:138} - {DEBUG:MainThread} - Topic openWB/set/chargepoint/3/get/state_str, Payload Strom freigegeben, warten auf Fahrzeug. ...
2026-11-06 13:15:25,129 - ... Payload Strom freigegeben, warten auf Fahrzeug. ...
2026-11-06 13:15:35,462 - ... Payload Strom freigegeben, warten auf Fahrzeug. ...
(wiederholt sich alle 10 s)
Ursache
Vergleich perform_phase_switch in packages/modules/internal_chargepoint_handler/chargepoint_module.py:
2.2.1 (82510a223):
with SingleComponentUpdateContext(self.fault_state, update_always=False):
self._client.evse_client.set_current(0)
time.sleep(5)
GPIO.output(gpio_cp, GPIO.HIGH) # CP off2.3.0 (8c58e4b84, seit 1e41b2080 / #3326):
with SingleComponentUpdateContext(self.fault_state, update_always=False, reraise=True):
evse.set_current(0)
for _ in range(20): # poll up to 10s (20 × 0.5s) for EVSE to confirm 0 A
_, _, evse_current = evse.get_plug_charge_state()
if evse_current == 0:
break
time.sleep(0.5)
evse.set_current(0)
else:
raise Exception("Ladung konnte nicht gestoppt werden - Phasenumschaltung abgebrochen.")
GPIO.output(gpio_cp, GPIO.HIGH) # CP offZwei Probleme:
- Die Wartezeit zwischen 0 A und CP-Trennung ist faktisch entfallen.
get_plug_charge_state()liefert den
EVSE-Sollwert (Register 1000), nicht den Iststrom. Der steht unmittelbar nachset_current(0)auf 0, die
Schleife bricht beim ersten Durchlauf ab, und CP wird innerhalb von ca. 0,3 s nach dem 0-A-Befehl getrennt.
Das Fahrzeug hat zu diesem Zeitpunkt die Ladung noch nicht beendet und die Schütze noch nicht geöffnet.
Nach IEC 61851 darf das EV bis zu 3 s brauchen, um auf eine PWM-Änderung zu reagieren. In 2.2.1 deckten die
festen 5 s das ab. Fahrzeuge, die einen CP-Abriss unter Last tolerieren, zeigen nur einen Neustart der
Ladung; der Audi (PPE) geht in einen Ladefehler, der nur durch Ent-/Verriegeln zurückgesetzt wird. - Jeder serielle Modbus-Fehler beim Rücklesen bricht die Umschaltung ab (
reraise=True). Die Rückleseschleife
erzeugt bis zu 40 zusätzliche Transaktionen auf dem RS485-Bus genau im Umschaltmoment. Ein einzelner Aussetzer
("No response received", bei uns sporadisch auch an anderen Stellen zu sehen) reicht, und die Exception
verlässtperform_phase_switchvor der GPIO-Sequenz. Die Hardware bleibt auf der alten Phasenzahl, die
Regelung arbeitet mit der neuen. Bis zum nächsten Umschaltversuch kommt keine Ladung zustande.
CP nach Fehler/Abbruch bei Phasenumschaltung und CP-Unterbrechung immer wieder verbinden #4037 behandelt die Folge (CP bleibt bei Exception nachGPIO.HIGHgetrennt), nicht diesen Abbruch davor.
Vorschlag
Das Rücklesen nur als Best-Effort behandeln, die feste Wartezeit aus 2.2.1 beibehalten und die GPIO-Sequenz
immer ausführen (CP im finally wieder verbinden, wie in #4037). Läuft bei uns so seit 06.11.2026:
PHASE_SWITCH_SETTLE_SECONDS = 5
def perform_phase_switch(self, phases_to_use: int) -> None:
gpio_cp, gpio_relay = self._client.get_pins_phase_switch(phases_to_use)
evse = self._client.evse_client
confirmed = False
try:
evse.set_current(0)
for _ in range(10): # bis zu 5 s auf Bestätigung 0 A warten
try:
_, _, evse_current = evse.get_plug_charge_state()
if evse_current == 0:
confirmed = True
break
except Exception as e:
log.warning(f"Phasenumschaltung LP{self.local_charge_point_num}: EVSE-Rücklesen "
f"fehlgeschlagen ({e}), weiter.")
time.sleep(0.5)
try:
evse.set_current(0)
except Exception as e:
log.warning(f"Phasenumschaltung LP{self.local_charge_point_num}: 0 A setzen "
f"fehlgeschlagen ({e}), weiter.")
except Exception as e:
log.warning(f"Phasenumschaltung LP{self.local_charge_point_num}: 0 A setzen "
f"fehlgeschlagen ({e}), Umschaltung wird trotzdem durchgeführt.")
if not confirmed:
log.warning(f"Phasenumschaltung LP{self.local_charge_point_num}: EVSE hat 0 A nicht bestätigt, "
f"Umschaltung wird nach Wartezeit trotzdem durchgeführt.")
# Immer die feste Wartezeit einhalten, damit das EV die Ladung sauber beendet hat.
time.sleep(self.PHASE_SWITCH_SETTLE_SECONDS)
try:
GPIO.output(gpio_cp, GPIO.HIGH) # CP off
GPIO.output(gpio_relay, GPIO.HIGH) # 3 on/off
time.sleep(5)
GPIO.output(gpio_relay, GPIO.LOW) # 3 on/off
time.sleep(5)
finally:
GPIO.output(gpio_cp, GPIO.LOW) # CP on - in jedem Fall wieder verbinden
time.sleep(1)
self.old_phases_in_use = phases_to_useVerifikation 13:25:28 (3 → 1 Phasen, mit obigem Code, Auto lud vorher 3-phasig):
2026-11-06 13:25:28,053 - {modules.internal_chargepoint_handler.internal_chargepoint_handler:59} - {DEBUG:Internal Chargepoint} - Switch Phases from 0 to 1
2026-11-06 13:25:28,059 - {modules.internal_chargepoint_handler.internal_chargepoint_handler:73} - {DEBUG:Internal Chargepoint} - Thread zur Phasenumschaltung an LP0 gestartet.
2026-11-06 13:25:28,341 - {modules.common.evse:57} - {DEBUG:perform phase switch 0} - Gesetzte Stromstärke EVSE: 0, Status: 2, Modbus-ID: 1
2026-11-06 13:25:31,394 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 0, Status: 2, Modbus-ID: 1 <- 5 s Wartezeit, CP noch verbunden
2026-11-06 13:25:33,489 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 0, Status: 1, Modbus-ID: 1 <- CP getrennt
2026-11-06 13:25:43,141 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 0, Status: 1, Modbus-ID: 1
2026-11-06 13:25:45,184 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 0, Status: 2, Modbus-ID: 1 <- CP wieder verbunden
2026-11-06 13:25:47,435 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 600, Status: 2, Modbus-ID: 1
2026-11-06 13:25:53,977 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 600, Status: 3, Modbus-ID: 1 <- Auto lädt
2026-11-06 13:26:09,408 - {modules.common.evse:57} - {DEBUG:Internal Chargepoint} - Gesetzte Stromstärke EVSE: 1372, Status: 3, Modbus-ID: 1
Umschaltung ohne Fehler, Auto nimmt die Ladung 1-phasig mit 13,7 A wieder auf, keine Warnung aus
perform_phase_switch.
Offene Frage an die Maintainer: Wenn das Rücklesen den Iststrom bestätigen soll, müsste es den Zählerstrom
(counter_state.currents) oder den EVSE-Status (3 → 2) abwarten, nicht den Sollwert. Die feste Wartezeit ist
der einfachere und bisher bewährte Weg.
Verwandte PRs/Issues
- fix: EVSE-Ruecklesen vor Phasenumschaltung #3326 (Ursache, in 2.3.0 enthalten)
- CP nach Fehler/Abbruch bei Phasenumschaltung und CP-Unterbrechung immer wieder verbinden #4037 (CP nach Exception wieder verbinden, behandelt nur die Folge)
- Impulsdauer fuer Phasenumschaltrelais auf 0,5s verkuerzen #4038 (Relais-Impulsdauer, unabhängig)
- [BUG] Phasenumschaltung läuft auch, wenn sich die Phasenzahl gar nicht ändert (CP ~15 s unterbrochen) #4118 (unnötige CP-Unterbrechung bei unveränderter Phasenzahl, gleicher Codebereich)
Activity
kaindl commentedon Nov 10, 2026
Sollte es nicht reichen, den charging-State von get_plug_charge_state mit abzufragen? Der prüft doch schon auf Strom > 0, oder?
Also von
zu
Stefan3934 commentedon Nov 11, 2026
Danke für den Blick drauf.
chargingzusätzlich abzufragen ändert leider nichts, dennchargingwird inget_plug_charge_state()aus demselben Sollwert abgeleitet:Unmittelbar nach
set_current(0)liest Register 1000 bereits 0, damit istchargingFalse, egal ob die EVSEnoch Status 3 (C, Fahrzeug lädt) meldet.
evse_current == 0 and not chargingist also dieselbe Bedingung wieevse_current == 0und bricht die Schleife genauso im ersten Durchlauf ab.Was tatsächlich den Zustand des Fahrzeugs abbildet, ist
state_number(Register 1002): 3/4 = Fahrzeug lädt(State C), 2 = angesteckt, lädt nicht (State B). Darauf müsste die Schleife warten, nicht auf den Sollwert.
get_plug_charge_state()gibt den Status nicht zurück, man bräuchte also entweder den Rohstatus im Rückgabewertoder einen eigenen Lesezugriff in
perform_phase_switch.In meinen Logs vom 06.11. sieht man beide Fälle:
getrennt, Audi meldet "Ladenetz Fehler". Mit der alten festen Pause (
time.sleep(5)in 2.2.1, siehe auchden Kommentar in
control/phase_switch.py: "Wenn gerade geladen wird, muss vor der Umschaltung eine Pausevon 5s gemacht werden") trat das nie auf.
get_plug_charge_state()wirft nach einem seriellen Aussetzer(
No response received), wegenreraise=Truebricht die Umschaltung vor der GPIO-Sequenz ab, Relais bleibtauf 3 Phasen, Soll-Phasenzahl 1, die Regelung gibt Strom frei und wartet vergeblich.
Der zweite Punkt bleibt auch mit einem korrekten Statuskriterium bestehen: ein einzelner Modbus-Fehler im
Rücklesen darf die Umschaltung nicht abbrechen. Mein Vorschlag wäre daher:
state_number not in (3, 4)warten (Fahrzeug hat die Ladung beendet), nicht auf denSollwert.
verlassen.
CP nach Fehler/Abbruch bei Phasenumschaltung und CP-Unterbrechung immer wieder verbinden #4037, damit CP in jedem Fall wieder verbunden wird. In allen anderen Fällen die GPIO-Sequenz ausführen und
old_phases_in_usesetzen.Bei mir läuft seit 06.11. eine Variante mit fester 5-s-Pause als Rückfallebene und Best-Effort-Rücklesen
(Code im Issue oben), seither keine Auffälligkeit bei den Umschaltungen. Wenn Statuskriterium gewünscht ist,
teste ich eine entsprechende Fassung gern an meiner series2 mit dem Audi.
kaindl commentedon Nov 11, 2026
Ah, macht auch irgendwie Sinn, dass man aus der evse nur die Vorgaben herauslesen kann, nicht die Ist-Werte ;)
Das Problem, das ich bei deinem Ansatz sehe: Der Fehler, der diese Anpassung überhaupt erst ausgelöst hat, ist wieder drin und wird laut Kommentar auch akzeptiert ("Umschaltung wird trotzdem durchgeführt.").
Eigentlich sollte die Logik aber ja genau andersherum ein Schalten der Schütze unter Last auf jeden Fall verhindern.
Die aktuelle Logik prüft und wiederholt ja nur das Setzen in der evse
Demnach fehlt dann IMHO vor dem CP off noch eine tatsächliche Überprüfung, ob auch wirklich kein Strom mehr fließt und nur dann darf der CP unterbrochen werden:
Hast du Lust, das mal zu testen, wenn das für dich sinnvoll erscheint? Bei mir wird planmäßig erst am Wochenende die aktuelle openWB ohne Phasenumschaltung gegen eine mit Phasenumschaltung getauscht, dann kann ich auch gegen einen A6 e-tron testen.
Stefan3934 commentedon Nov 12, 2026
Einverstanden, der Zählerstrom ist das einzige Kriterium, das den Iststrom abbildet – die feste Pause war
bei mir nur die Rückfallebene, weil der Sollwert nichts aussagt. Ich teste die Variante mit Zählerprüfung
gern an meiner series2 (MPM3PM, Audi A6 e-tron). Geht bei mir auch erst am Samstag.
Drei Dinge würde ich dabei anders machen:
Lesefehler in der Schleife nicht zum Abbruch machen. Der Zähler hängt am selben RS485-Bus wie die
EVSE; der Aussetzer vom 06.11. 13:15 (
No response received) trifftget_counter_state()genauso. Mitreraise=Trueum die ganze Schleife bricht ein einzelner fehlgeschlagener Lesezugriff die Umschaltung ab,obwohl die nächste Abfrage 0,5 s später 0 A gezeigt hätte. Besser: Exception in der Schleife abfangen,
weiter pollen, und erst abbrechen, wenn innerhalb des Zeitfensters keine Bestätigung 0 A kam. Damit
bleibt deine Eigenschaft "ohne bestätigte 0 A wird nicht geschaltet" erhalten, ohne dass ein Busfehler
allein reicht.
Toleranzschwelle statt
== 0. Der MPM3PM liefert zwar bei offenem Fahrzeugschütz exakt 0,0 A (sieheLogs oben), aber andere Zähler (SDM, B23) rauschen im Hundertstel-Bereich, und
0.0 == 0auf Floatsist unnötig scharf.
max(currents) < 0.5o.ä. reicht;get_values()nutzt fürphases_in_useohnehin> 3 A.Zeitfenster 10 s statt 5 s. Nach IEC 61851-1 darf das EV bis 3 s brauchen, um auf PWM-Abschaltung zu
reagieren; dazu kommen die Zählerabfragen selbst (B23 mit
sleep(0.1)je Register, SDM ähnlich), so dass5 s nur etwa 5–6 Abfragen sind. Die EVSE-Schleife davor endet ja ohnehin beim ersten Durchlauf.
Konkret (deine Fassung, nur die drei Punkte ergänzt plus das
finallyaus #4037):Zum Abbruchfall noch eine Beobachtung:
perform_phase_switchläuft im Handler direkt als Thread-Target(
__thread_phase_switch), die Exception landet im Log und im FaultState von LP0, aber nicht bei derRegelung.
check_phase_switch_completed()gibt nach Thread-Ende den Strom frei und merkt den Fehlschlagerst nach
keep_charge_active_durationüberfailed_phase_switches(Zähler-Phasenzahl ≠phases_to_use).Bis dahin rechnet die Regelung mit der neuen Phasenzahl, die Hardware steht auf der alten. Mit
Zählerprüfung wird der Abbruch seltener, verschwindet aber nicht – vielleicht ein Thema für einen
separaten Fix.
Testen kann ich frühestens am Samstag. Bis dahin gern Rückmeldung zu den drei Punkten, dann spiele ich die
abgestimmte Fassung ein und melde mich mit Logs der ersten PV-Umschaltungen (1→3 unter Last und 3→1).
kaindl commentedon Nov 12, 2026
@Stefan3934 sieht gut aus, ich werds bei mir auch gleich drauf packen und voraussichtlich am Wochenende gegen A6 e-tron und einen 2025er ID.3 testen 👍
seaspotter commentedon Nov 12, 2026
Zwei Dinge fallen mir an der aktuellen Fassung noch auf:
get_plug_charge_state()) liest weiterhin nur das Register zurück, dasset_current()selbst gerade geschrieben hat - sie bestätigt also nichts und bricht bei einem einzelnen Modbus-Fehler dort weiterhin die ganze Umschaltung ab (reraise=True), nur eben über den EVSE-Bus statt den Zähler-Bus.max(counter_state.currents)kann crashen, nicht nur falsch liegen: B23 liefert bei nicht angeschlossener PhaseNone(check_nan()),max()auf einer Liste mitNonewirft TypeError. Zusätzlich: SDM implementiertget_currents()gar nicht separat, nurget_counter_state()- falls das noch irgendwo direkt genutzt wird, kommt nur[0]*3vom Abstract-Default zurück.Vorschlag, der beides behebt (EVSE-Schleife komplett raus, nur noch der Zähler-Poll als echtes Kriterium, None-sicher):
Das try/finally ist aus #4037 vorweggenommen (dort noch offen) - sonst würden sich beide PRs an derselben Stelle überschneiden.
Stefan3934 commentedon Nov 13, 2026
@seaspotter beide Punkte stimmen, danke. Die EVSE-Schleife hatte ich drin gelassen, um nah an
kaindls Fassung zu bleiben; als Kriterium taugt sie nicht, und als zweite Abbruchquelle ist sie sogar
schädlich. Das
Nonevom B23 (check_nan()) hatte ich übersehen. Deine Fassung ist aus meiner Sichtdie richtige Basis, ich spiele sie am Samstag so ein.
Zwei Ergänzungen würde ich noch vorschlagen:
Zusätzlich auf den EVSE-Status warten (Register 1002 nicht 3/4). Der Zähler beweist 0 A, aber
nicht, dass das Fahrzeug sein Schütz geöffnet hat und in State B ist. Ein EV, das bei 0 A in State C
verharrt (Ladepause, Balancing), sieht beim CP-Trennen denselben Abriss wie unter Last. Das Statusregister
ist genau die Information, die der EVSE-Schleife gefehlt hat.
get_plug_charge_state()liest es bereits,gibt es aber nicht zurück; am wenigsten invasiv wäre, den Rohstatus wie
evse_currentals Attribut zumerken:
und in der Schleife beide Kriterien zu verlangen (Lesefehler wie beim Zähler nur loggen):
Falls ihr den EVSE-Zugriff in der Schleife lieber ganz vermeiden wollt, ist der Zähler allein immer
noch deutlich besser als der Stand in 2.3.0; dann nur Punkt 2.
default=0nicht als Bestätigung werten. Liefert der Zähler für alle drei PhasenNone(Lesefehler, der nicht als Exception ankommt), ergibt
max(..., default=0)0 A und die Umschaltungläuft ohne echte Messung. Mit
werte and max(werte) < …wie oben gilt "keine Messung = keineBestätigung", und nach dem Zeitfenster greift der Abbruch.
Zum Zeitfenster: mit den
sleep(0.1)je Register im B23-/SDM-Treiber dauert ein Schleifendurchlauf eher1 s als 0,5 s, 20 Durchläufe sind dann bis zu 20 s. Für den Abbruchfall ist das in Ordnung, nur damit es
beim Lesen der Logs nicht überrascht.
Ich melde mich nach dem Wochenende mit Logs beider Richtungen (1→3 unter Last, 3→1) von series2 + A6 e-tron.
Stefan3934 commentedon Nov 14, 2026
Testergebnis vom Samstagvormittag (14.11.2026), openWB series2, EVSE-Firmware 18, MPM3PM-Zähler, Audi A6 Avant e-tron, 2.3.0 mit der Fassung von @seaspotter plus den beiden Ergänzungen aus meinem letzten Kommentar (EVSE-Statusregister 1002 nicht 3/4, "alle None" zählt nicht als 0 A). Beide Richtungen unter voller Last, Umschaltung per "Anzahl Phasen" im Sofortladen.
3 → 1 Phasen, Auto zieht 15,6 / 9,7 / 15,9 A:
1 → 3 Phasen, Auto zieht 14,8 A auf L1:
Kein Busfehler, kein Abbruch, kein "Ladenetzfehler" am Audi, beide Male lädt das Auto nach der Umschaltung ohne Zutun weiter. Ein Durchlauf dauert hier mit MPM3PM rund 1,3 s, der Audi hat die Ladung in beiden Fällen innerhalb von 2 s beendet.
Durchlauf 2 der ersten Umschaltung ist aus meiner Sicht das interessanteste Detail: Die EVSE meldet schon Status 2 (State B), auf L2 fließen aber noch 0,86 A. Erst einen Durchlauf später ist der Zähler wirklich bei 0. Das spricht dafür, beide Kriterien zu verlangen (Zähler unter 0,5 A und Status nicht 3/4) und bei "fast 0" lieber einen Durchlauf länger zu warten; der Zähler allein mit
== 0hätte hier ebenfalls erst in Durchlauf 3 ausgelöst, der EVSE-Status allein schon in Durchlauf 2 unter Restlast.Der Vollständigkeit halber: In der Nacht davor (Zeitladen, Umschaltung ohne Last beim Planstart) lief dieselbe Fassung ebenfalls unauffällig.
Unabhängig davon bin ich beim Testen über ein anderes Problem gestolpert, das nichts mit der Umschaltung zu tun hat: Die Wiederholung der Control-Pilot-Unterbrechung ("Auto lädt trotz Freigabe nicht") feuert in 2.3.0 in jedem Regelzyklus statt nach dem Wiederholintervall, weil
control_parameter/timestamp_last_cp_retryinsetdata.pynicht validiert und damit nie übernommen wird, undtimestamp_charge_startbeim Ladestopp nicht zurückgesetzt wird. Das hat den Audi heute zweimal in den Ladenetzfehler getrieben, bevor die Umschaltung überhaupt dran war. Dafür mache ich ein eigenes Issue auf, damit es hier nicht vermischt wird.Falls hilfreich, stelle ich das vollständige Log (main.log + internal_chargepoint.log mit DEBUG, 08:33 bis 08:59) gern zur Verfügung.
seaspotter commentedon Nov 14, 2026
Klingt doch ganz vielversprechend, Danke für den Test und die Zusammenfassung.
Da der
cp_retryeh von mir ist, hab ich das gleich als PR eingereicht um das zu fixen, danke fürs Melden. Brauchst also kein Issue aufmachen. #4329Für die Phasenumschaltung machst du n PR oder bei Bedarf kann ich auch unterstützen oder es machen, will euch die Arbeit aber nicht wegnehmen, ist nur n Angebot :)
kaindl commentedon Nov 14, 2026
Danke für die Tests und die Umsetzung 😊
Habs vorher mit der Version aus dem PR mit A6 e-tron und ID.3 erfolgreich getestet 👍