-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First Support for VE-Direct Hex messages #479
Conversation
Vielen Dank für das Programmieren. Hast du dir schon Gedanken gemacht wie das Auslesen von Werten funktionieren soll? Eventuell Variablen für alle Werte anlegen und dann alle Werte zyklisch auslesen? |
Generell wird das Auslesen von vielen Werten ja schon über das Textprotokoll unterstützt und hierfür gibt es z.B. für den MPPTController auch die entsprechende Variable Interessant sind denke ich die Werte, für die eine Anfrage (GET-Kommando) gestellt werden muss über das Hex-Protokoll. Da die Antworten hier mit einer Zeitverzögerung kommen wäre vielleicht eine Umsetzung über einen Callback-Mechanismus sinnvoll um den Kontrollfluss nicht zu blockieren. D.h. beim Anfragen eines Wertes wird eine Referenz zu einer Funktion mit Übergeben die aufgerufen wird, wenn z.B. vom MPPT-Controller eine Antwort gekommen ist. |
Das klingt sehr vernünftig, allerdings wäre das mehr als genug für diesen Anwendungsfall. In der Der JK BMS Controller macht es ähnlich. |
Für mich ist nur das auslesen des battery maximum current (0xEDF0). interessant. Für jemande der den Akku maximal ausnutzen möchte, wäre der "BMS Controlled" Modus + Remote sensor data (voltage and/or temperature) interessant. Da könnte man die Werte von der Pylontech oder einem anderen BMS and den Victron senden. Man könnte ein Array anlegen, in dem die zyklischen GET + SET Befehle und die dazu passenden empfangenen Werte eingetragen werden. Die Befehle aus dem Array würden dann zyklisch abgefragt werden. Dann könnte später je nach eingestellten Optionen dem Array Befehle hinzugefügt oder entfernt werden. |
Ok, ich bin bei ein paar Tests auf 2 Probleme gestossen:
Zum Thema zyklisches Abfragen von Werten wie z.B.Maximum Battery Current: Das ist eigentlich nur möglich, wenn man eine Anfrage nur alle paar Sekunden sendet, ansonsten gibt es keine Daten mehr über das Textprotokoll. Vor allen Dingen wenn mehrere Werte abgefragt werden kann es dann länger dauern. Ausserdem muss man irgendwie die kurzen Pausen zwischen den einzelnen Kommandos sicherstellen. Könnte man das z.B. in einen separaten Thread auslagern? Da habe ich keine Erfahrung mit dem ESP32. Alternativ könnte man auch komplett auf das Textprotokoll verzichten und nur die asynchronen Hex-Nachrichten auswerten. Soweit ich das sehe werde hier mindestens die gleichen Werte gesendet. Das könnte das gesamte Handling sogar einfacher machen, wäre aber eine große Umstellung. Man könnte auch komplett auf das zyklische Anfragen der Werte verzichten und es so umsetzen, der "Consumer" aktiv den gewünschten Wert anfragen muss und dieser dann wie beim JK BMS Controller abgespeichert wird, wenn die Antwort kommt. Viele Möglichkeiten, was meint ihr? Klar, wenn es nur um den einen Wert für maximum Battery geht kein Problem, aber es soll ja auch erweiterbar sein. |
Also ich habe es noch nicht getestet. Kannst du bitte kurz schreiben auf welchem Gerät mit welcher Firmware du getestet hast? In dem Dokument steht ja, dass wenn das HEX-Protokoll benutzt wird, das Text-Protokoll unterbunden wird. Eigentlich kann das HEX-Protokoll gar nicht so langsam sein, Victron nutzt es ja selber um MPPTs zu synchronisieren bzw. BMS / Battery Sense usw. Da es eine Serielle Schnittstelle ist, ist der Ablauf eigentlich klar. Befehl senden, auf Antwort warten, Befehl senden, auf Antwort warten.... Dauerfeuer raussenden und hoffen, dass alles in der richtigen Reihenfolge abgearbeitet wird, wird nicht funktionieren. Die Geräte brauchen in der Regel immer ein paar ms um zu Antworten. Ich denke auch der Teil welcher momentan das Textprotokoll verwendet müsste auf HEX-Protokoll umgeändert werden und durch eine loop zyklisch abgefragt werden. |
Ich teste das gerade mit meinem AC Lader Blue Smart IP22 24/16 FW 3.42, passt also nicht ganz zu de Dokumentation für die MPPTs, es gibt aber anscheinend viele Überschneidungen.
Langsam ist es auch nicht, bzw. auf jeden Fall ausreichend. Zum Synchronisieren von mehreren MPPTs untereinander reicht es auf jeden Fall, da muss ja nicht kontinuierlich gesendet werden.
Je nachdem, wie es auf der Gegenstelle implementiert ist. Da könnte auch eine Art FiFO-Buffer sein, der erst einmal alle Befehle entgegennimmt und der Reihe nach abarbeitet, je nach dem wann Zeit ist. Das Abarbeiten in der richtigen Reihenfolge wäre nebenbei ja auch gar nicht nötig. Schwierig ist eben nur die Strategie immer erst auf eine Antwort zu warten bevor der nächste Befehl gesendet wird. Was passiert, wenn es zu Übertragungsfehlern kommt? Wie lange warten man? Ich habe mich gerade mal testweise angetastet: Wenn ich immer 50ms Pause zwischen den Befehlen lasse, wird auch kein Befehl verschluckt, d.h. es kommt relativ zuverlässig zu jedem Befehl eine Antwort. Wäre vielleicht eine Strategie, oder einfach pro loop-Durchlauf jeweils nur einen Befehl absenden. Dann hat man implizit ein delay was gross genug sein sollte und muss kein Generell: Ich glaube trotzdem immer noch dass da Victron-Protokoll schon implizit so designed ist dass die Werte, die sich oft ändern ohnehin schon automatisch per Text-Protokoll und asynchrone Nachricht geschickt wird. Der Wert für Max Battery Current ist ja so ein typischer Wert, der eigentlich gerade nicht kontinuierlich abgefragt werden müsste. |
Da stimme ich zu. So sollte es sein.
Du stellst definitiv die richtigen Fragen, sehr gut. Bei Übertragungsfehlern bekommst du vermutlich keine Antwort. Dir bleibt nur, ein Timeout abzuwarten und deine Nachricht zu wiederholen. Oder die nächste zu schicken, weil sich die Schicht drüber kümmern wird/muss, dass es nochmal versucht wird. Im JK BMS Controller ist so eine "state machine" mit einem Timeout implementiert. Warum schickst du mehrere Nachrichten kurz hintereinander? Willst du mehrere Werte "gleichzeitig" abfragen? Hast du geprüft, ob man nicht mehrere Werte pro Nachricht anfragen kann? |
Das war eigentlich eher als Test ob man die Implementierung z.B. ohne eine State-Machine hinbekommt. Meine Überlegung: Ich schicke einfach Regelmässig Anfragen (GET Befehle) für alle Werte raus, für die ich gerne eine Antwort hätte und die nicht ohnehin schon regelmässig automatisch unaufgefordert kommen. Die Antworten sammeln ich dann einfach wie sie kommen ein und kann da das gleiche Handling machen wie auch jetzt schon. Nur das zusätzlich auch Hex-Nachrichten geparsed werden. So muss ich mich auch nicht Übertragungsfehler beim Empfangen oder Senden der Nachrichten zu kümmern und mir merken, ob eine Anfrage erfolgreich gesendet wurde. Anders sieht es beim Setzen von Werten aus, wie z.B. dem Battery Current Limit. Hier braucht man denke ich eine State-Machine die Überprüft, ob ein entsprechendes ACK zum gesendeten Befehl empfangen wurde. Im JK BMS Controller ist es in dem Sinne etwas anders, weil hier die Werte immer erst angefragt werden müssen.
Nein, ich wollte wie gesagt nur das regelmässige Abfragen von mehreren Werten einfacher machen (siehe oben). Mehrere Werte gleichzeitig anfragen geht nicht laut VE.Direct Protokoll. Danke erst einmal für den Input. Ich probiere mal, was bei mir funktioniert und teste auch mal mit meinem MPPT Lader. |
Es ist vermutlich Sinnvoller die GET-Befehle genauso zu behandeln wie die SET-Befehle. Damit du Fehlermeldungen zu ordnen kannst. Wie bereits oben geschrieben macht der Ablauf Befehl senden, Antwort abwarten und auswerten, Befehl senden, Antwort abwarten und auswerten am meisten Sinn bei so einer Schnittstelle. Das ist ein sequentieller Ablauf der für alle Befehle gilt. Befehle raus senden und Antworten einsammeln wird nicht funktionieren. |
Sehe ich grundsätzlich nicht so und das Bestätigen meine Tests auch nicht. Hier mal ein Ausschnitt aus den Logs:
Man sieht am Anfang schön, dass zeitlich erst einmal 2 Kommandos gesendet werden und die Antworten auf beide Kommandos danach reinkommen |
Daraus darf man aber nicht herleiten, dass x-beliebige Befehle, Anzahl auch >2 senden direkt hintereinander funktioniert. Du weißt nicht wie viele Befehle der Victron zwischenspeichern kann, bzw. Bytes und du weißt auch nicht ob es sich von Modell zu Modell oder von Firmware zu Firmware oder von Typ zu Typ unterscheidet. Und selbst wenn man es wüsste, dann müsste man selber mit rechnen wie viel Bytes die gesendeten Befehle haben um den Buffer gegenüber nicht zum Überlauf zu bringen. |
Ich glaube, wir reden gerade auch ein bisschen aneinander vorbei. Mir geht es gar nicht darum, den Input-Buffer mit Befehlen zu fluten und evtl. zum Überlaufen zu bringen. Das würde ich einfach dadurch lösen, dass ich genug Zeit zwischen den einzelnen Kommandos lasse (obwohl der Victron da auch sehr robust zu sein scheint). Ich glaube eben nur einfach, dass man für das reine regelmässige Abfragen von Werten, die nicht als automatisch als Noch mal ein anderer Punkt der mir eher Sorgen macht. In der Doku steht:
Das wäre ja bei Nutzung im DPL schon der Fall. Hast Du dir dazu Gedanken gemacht? Es hört sich eher nicht danach an, als ob man den Wert für Battery Maximum Current oft verändern sollte. |
Unabhängig davon wie viele Befehle, man weiß nicht wann man den Input Buffer gegenüber überflutet und wie groß der ist. Ich habe da auch schon so meine Erfahrungen gemacht und würde es direkt mit Errorhandling und Timeouts machen da Probleme früher oder später auftreten werden und man sich dann ein kompliziertes debuggen sparen kann.
Das wird in einen nicht flüchtigen Speicher geschrieben. Solche Schreibvorgänge dauern immer etwas länger, deshalb soll man es nicht in einer loop machen. Wenn es ein EEPROM ist, dann verträgt der > 100.000 Schreibzyklen. Ich schreibe das Limit nur wenn der Full Solar Passtrough erreicht ist und wenn er wieder ausgeschaltet wird. Das sind maximal 2 Schreibzyklen an einem Tag an dem die Sonne scheint. Man könnte auch das Remote Register benutzen, dann müsste man aber spätestens alle 60 Sekunden den Wert erneut geschrieben haben. Der Charger Maximum Current ist übrigens Load + Batterycurrent. |
Ganz ehrlich, ich würde wahrscheinlich nach aktuellem Stand ohnehin erst einmal gar keine Werte so kontinuierlich abfragen. Alle relevanten sich oft ändernden Werte kommen ohnehin schon jetzt automatisch und werden abgespeichert. Du sagst ja selber, dass Du das Battery Limit Current maximal 2 Mal am Tag anpassen würdest. Dafür muss der aktuelle Wert nicht alle paar Sekunden gezogen werden. Ein anderer Anwendungsfall wären statistische Werte der letzen Tage (jeweils größere Brocken). Die können auch bei Bedarf angefragt werden in dem Moment wo sie gebraucht werden (z.B. zur Anzeige im Webinterface). Vorschlag: Für die relevanten Werte gibt es jeweils Variablen in z.B.
oder werden upgedatet, wenn ein entsprechendes positives ACK auf eine SET-Anfrage an das Victron-Gerät empfangen wurde. 'requestMeasurementUpdate' stösst dann den Tanz mit einer State-Machine, Error-Handling, Timeout etc. an und returned dann auch mit entprechendem Zustand als Fehler-Rückgabewert, wenn gerade schon eine Abfrage am Laufen ist, bzw. auf eine Antwort gewartet wird.
Das stimmt. Ich merke auch gerade, dass ich da eher an meinen Anwendungsfall gedacht habe, also das kontinuierliche Anpassen für Überschusseinspeisung mit einem AC Lader.
Das wäre dann vielleicht eher etwas für meinen Anwendungsfall. Danke für den Hinweis.
Jupp, hab ich auch schon gefunden und getestet. Der Wert ist leider Read-only. |
Ich würde das Limit gerne auf der Webseite anzeigen und da man es auch per APP ändern kann würde ich es wiederholt abfragen.
Da reicht eine Abfrage am Tag, weil die Daten sich innerhalb eines Tages ja nicht ändern können.
Ich würde das erweitern um:
Das Array verwendet einen eigenen Datentyp bestehend aus z.B. command, response, fault, responseTimestamp, Intervall eine State-Machine welche eine innere Loop hat:
und eine äußere Loop:
Dann kann man eine Funktion schreiben welche die daten entsprechend hinzufügt und auswertet:
Eine Funktion welche Werte im Array setzt oder abfragt Beispiel zyklische abfrage BatteyMaximumCurrent Beispiel zyklisches setzen ChargeCurrentLimit Beispiel explizite abfrage BatteyMaximumCurrent Der Vorteil:
Ich denke so viel mehr Arbeit ist das auch nicht. Ich kann da gerne auch mithelfen... |
@philippsandhaus Ich kann auch was vorbereiten und bei mir testen. |
@JaMo523 Ja, mach das gerne. Ich komme leider im Moment nicht zu viel. Nimm also gerne meinen aktuellen Stand und erweitern entsprechend. |
b771e5e
to
0f062a9
Compare
0f062a9
to
f0e686e
Compare
Servus, ich habe das hex Protokoll bei mir schon seit einigen Monaten laufen. Ich kann Werte aktiv Abfragen, die Antworten verarbeiten und Werte setzen. Umgesetzt habe ich damit zum Beispiel ein soclimit. Wenn der Forecast am nächsten Tag einen gewissen Wert überschreitet, dann limitiere ich den soc auf 80%, das reicht dann für die Nacht. Für die Limitierung habe ich zwei Mechanismen implementiert: Ich kann euch dazu gerne Erfahrungswerte liefern falls irgendwelche Fragen aufkommen :) Programmiertechnisch ist es sicher alles andere als gut umgesetzt aber es funktioniert für mich stabil :) Ich würde den Ladestrom nicht über die Batterysettings dynamisch anpassen. Falls der esp mal aussteigt, dann verbleibt evtl ein ungünstiger Wert. Lieber über external control zyklisch senden, dann gibts bei Ausfall einen Fallback. |
Hallo @bonzai-wurst , danke für die Infos. Aus meiner Sicht macht es sehr viel den external control Modus zu nutzen, des Aspekt definierter Fallback, falls OpenDTU mal ausfällt, hatte ich noch gar nicht im Sinn. Ausserdem wird dadurch auch das Problem umgangen, dass der Flash des MPPT zu oft geschrieben würde. Dadurch könnte man es super ganz normal mit in die Controlloop vom vom DPL mit einbinden. Ich hoffe, ich finde nächstens etwas mehr Zeit, dann würde ich das mal so umsetzen. Vielleicht schon einmal zwei Frage:
|
Hi Philipp,
Ich weiß nicht was der shunt alles übergibt aber für external control sind Batteriespannung und Temp nicht relevant. Also wenn die Werte über den shunt reinkommen, dann werden sie das auch während external control weiter tun.
Laut Victrons hex Protocol documentation Seite 23 muss das mindestens einmal pro Minute gesendet werden. Ich habe den Empfang von hex Werten übrigens mit einem array von struct mit hex id, timestamp und value gelöst. Das Array enthält von jeder id immer den neuesten Wert, wenn das Array voll ist, wird der älteste Wert überschrieben. Das ist sicher nicht elegant aber es funktioniert für mich :-) Ich lese eigentlich nur den voltage setpoint falls sich der mppt im state absorption oder float befindet. Alles andere hat mich bisher nicht interessiert. Den voltage setpoint brauche ich, weil ich ein "overfeed" implementiert habe. Wenn der Speicher voll ist und ich die überschüssige Energie nicht selbst brauchen kann, wird eingespeist und an die Allgemeinheit verschenkt. |
Dieser Thread ist für mich sehr interessant, da ich nach einer Möglichkeit suche, den Ladestrom eines MPPT von extern dynamisch zu steuern, da ich bisher einen zum AC- Überschußladen missbrauche. Eigentlich genau das, |
Das kann ich bestätigen. Manchmal kommen einfach gar keine Antworten, dann eine Weile wieder alle. Pausen machen hat nicht geholfen. Was aber sehr gut zu funktionieren scheint: HEX-Kommandos direkt nach einer ungefragten TEXT-Nachricht verschicken. Mein MPPT antwortet dann sehr zuverlässig, auch wenn die Kommandos direkt aneinandergereiht sind. Meine beste Vermutung dazu: Der MPPT mag keinen Input verarbeiten, während er TEXT-Nachrichten verschickt. |
@philippsandhaus Basierend auf #833, was sollte als nächstes passieren? Können wir diesen PR schließen und du formulierst deine Anforderungen in einem neuen Issue, oder machst basierend auf #833 weiter am Code in einem neuem PR? |
Hallo @schlimmchen, ja, ich denke es ist am besten diesen PR zu schliessen. Die angedachten Arbeiten sind ja erledigt. Ich würde auf Basis des jetzigen und #436 dann einen neuen PR aufbauen. |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns. |
This is some initial base work for both #470 and #436 to make further development of the two issues independent.
It does two things: