BMS Kommunikation Infini-/MPP-Solar MPI / FSP Hybrid 10k und DIY Batterie

@domo1234 Das hat eig. alles nichts mit der BMS Kommunikation bzw. dem Protokoll davon zu tun.

Ich schlage vor, du eröffnest einen neuen Thread mit genauer Problembeschreibung, FW-Version, Settings, usw.
Die Bilder von irgendwelchen Tastmotas,etc. helfen nicht wirklich, wenn nicht beschrieben ist, was man darauf im Zusammenhang mit dem Problem sehen kann.

Für AccessPort brauchst du das RS232 Kabel, das mit dem WR daherkommt (glaube es ist ein Nullmodem). Mit SolarPower testen und wenn das funktioniert, dann kommt AccessPort auch klar damit.

Guten Morgen,
hier das Ergebnis

mit Einspeisung - Anzeige Inverter auf 50A Ladestrom
^P005BATS
^D0763000,0560,0560,0000,060,0530,0464,0530,0440,0560,0,,,1,0560,000,0600,0400¯[
^P004BMS
^D0520540,090,0,0471,00,0,0560,0560,3200,0,0,0464,0400

Einspeisung verboten - Anzeige auf 120A
^P005BATS
^D0763000,0560,0560,0000,060,0530,0464,0530,0440,0560,0,,,1,0560,000,0600,0400¯[
^P004BMS
^D0520540,090,0,0471,00,0,0560,0560,3200,0,0,0464,0400

Hi Rio,

dein Script infinipoll10k_bms.php läuft bei mir bereits und liest ab morgen sobald die Sonne scheint die Daten meines Easun ein, damit 123solar (auf das ich auch erst durch dich gekommen bin) die Daten aufschnupfen kann.
Danke dafür!

Nur eine Sache verstehe ich nicht, und zwar wie der Wechselrichter nun zu den JK-BMS-Daten kommt.
Ich hab noch nie mit shared memory gearbeitet, aber ich nehme an, irgendein anderes Script schreibt die Daten des vom ESP32 ausgelesenen BMS in irgendeiner Form in dieses Shared Memory, wo PHP dann darauf zugreifen kann?

Ich hab am ESP32 die Version von mascheihei (bzw. sein neuestes Update) installiert.
Diese Version gibt zusätzlich zum MQTT einfach via HTTP JSON aus mit den Werten des BMS. (Außerdem sind anscheinend ein paar Bugs behoben und die Alarme eingebaut.)

Wäre es nicht einfacher, diese im Script infinipoll10k_bms.php fürs Senden an den Wechselrichter zu verwenden?

Danke und lg
LichtiMC

Moin!
Infinipoll10k_bms checkt beim Start das vorhandensein von Shared Memory Object 0x4801 und aktiviert/deaktiviert die BMS Funktion im Script damit.
Die Daten vom BMS kommen via ESP32bei mir am Mosquitto an und werden dort von readmqttbms abgefragt und in eben jenes ShaMemObj geschrieben. Das Script muss also logischerweise vor infinipoll gestartet werden.

Ich weiß, ist nicht schön und ich werde das irgendwann auch in Infinipoll10k einbauen - aber erst, wenn alles fertig erforscht ist und ich Zeit dafür hab.
Hab die neueste Doku des Protokolles von Pylontech erst kürzlich erhalten und daher die Alarm-Codes usw. noch nicht in die Scripts mit eingebaut.

Ich möchte über meine vorhandene RS485 Kommunikation auch das Batterieentlade/-ladeverhalten beeinflussen.

Mein JKMBS kommuniziert bereits mit Node Red auf meinem Raspi. Das BMS wird per ESP32 ausgelesen und stellt die Infos per MQTT bereit.

Weiter habe ich eine bestehende RS485 Verbindung zwischen meinem WR und dem SDM630. Diese sind jeweils angebunden mit...
1x RS485/IP Gateway am WR (MPI 10K)
1x RS485/IP Gateway am SDM630

Beide kommunizieren auch bereits mit Node Red auf meinem Raspi.

Dh. ich habe bereits eine Verbindung (über den RS485/IP Converter) mit dem WR und möchte dies nun nutzen, um den WR die entsprechenden Infos zu geben.

Da ich die Modebus Nodes unter Node Red nicht zum fliegen bekomme, habe ich entsprechende UDP-Nodes verwendet.
Das Problem ist dabei nur, dass ich nun nicht direkt die Befehle absetzen kann und diese daher vorher konvertieren muss.
Grundsätzlich verstehe ich das Protokoll. Wie ich den Buffer erstelle, um mit dem SDM630 zu kommunizieren habe ich bereits hinbekommen. Die Register sind mir bekannt.

Nur wie konvertiere ich denn nun z.B. den Befehl für die Beinflussung des Lade/Entladeverhaltens des WRs (^D054BMS) in Dezimal oder Hex?
Die Register für den MPI 10K sind mir nicht bekannt. Nur die Befehlssätze.

Bin für jede Unterstützung dankbar.

Wenn ich dich richtig verstehe, möchtest du andere Befehle für den WR (wie z.b. ^D054BMS..) auch über die Verbindung zur Modbus-Karte absetzten? Das wird nicht funktionieren.
Du brauchst auch eine Verbindung zu einem der Seriellen/USB Ports um mit dem WR "kommandos" austauschen zu können.

Da auch die Modbus-Karte beim Infini nichts anderes als ein Modbus-zu-RS232 Converter ist, könntest du die Karte ganz außen vor lassen und deinen TCP-Serial Wandler an den RS232 anstecken.
Die paar EMINFO Kommandos die die Modbus-Karte aus den Modbus-Meldungen erstellt hast du wohl auch ratzfatz nachprogrammiert. Dann kannst du nebenbei alle anderen Abfragen (Leistungs-/Ertragsdaten, Konfiguration, etc.) auch gleich über die eine Verbindung schicken.

Einziger (kleiner) Haken an der Sache: Die RS232 fährt mit 2400 Baud!

Hallo Rio,

danke für dein Engagement!

Ich habe eine Frage bezüglich dem Aufbau des D054BMS-Kommandos: In deinem angehängten Bild

wird für den Warningcode eine Stelle ",0" reserviert.
In deinem Sourcecode des "readmqttbms.php" dagegen sind zwei Stellen vorgesehen:

//BMS warning code, tbd
shmop_write($sh_bms1, ",00", 23); // static

Welche Variante ist korrekt?

Grüße Alex

Gut erkannt. ?
Das "einstellige" hatte ich mal von der BMS-Box mitgeloggt. Ich denke aber, die Stellenanzahl ist relativ egal, solange dort der Wert in Dezimal zwischen den beiden Kommas steht (bisweilen immer "0" bzw. "00").
Um den BMS-Fehlercode Richtung WR sauber reverse-engineeren zu können, müsste die BMS-Box/Card lt. Pylontech Protkollbeschreibung (siehe Anhang) CID2 0x62 abfragen. Tut sie aber nicht und daher kann ich ihr auch keine "simulierten" Fehler vorgaukeln um zu sehen, was dann für eine Wert dort zum Infini geschickt wird.
Somit scheint mir der Parameter ungenutzt, zumindest mit der Voltronic eigenen BMS-Box.

Sunsynk_BatteryCompatibility_v12_English.pdf (737 KB)

Ahh, ok.
Mir war nur aufgefallen, dass damit auch die Länge des Strings für die WR-Kommunikation beeinflusst wird. Vermutlich geht es dem WR um die Gesamtlänge des gesendeten Strings, denn in "deinem" String wird der MaxDischargeCurrent nur mit 3 Stellen übertragen. In den anderen WR-Strings (z.B. ^P004BMS) sind es immer 4 - wie beim MaxChargeCurrent. Ich habe dann die Kommunikation auf 4 Stellen erweitert und der WR hat den String abgelehnt. Der Versuch mit nur einer Fehlerstelle und 4 MCC Stellen war dann erfolgreich.
Da ich ebenso DIY-Akkus habe, versuche ich mich an einer (für mich) komfortableren Konfigurationsmöglichkeit, ohne SolarPower ? .

Grüße Alex

@riogrande75

Ich versuche verzweifelt Befehle über den RS232/TCP Konverter an den WR zu senden. Er möchte einfach nicht antworten.

Kannst du mir bitte erklären, warum ich denn nicht alle Steuerbefehle über die Modbus Karte senden kann, wenn doch im WR so oder so alles an der RS232 Schnittstelle zusammenläuft?

Hab das nun auch hier schon oft genug erwähnt: Die USB/RS232(DB9) Schnittstelle ist eine serielle Punkt-zu-Punkt Verbindung. Asynchron, Terminal Modus.

Die RS485 Modbus-Schnittstelle ist auf der Modbus-Karte, welche quasi als Protokoll Umsetzer arbeitet (modbus/register-rs232/Kommandos). Auf der anderen Seite der Karte (golden Fingers) ist im WR nichts anderes als die 2. Serielle Schnittstelle, welche praktisch gleich arbeitet wie die 1.
Aber, es ist eben die Modbus-Karte dazwischen.

Les dir mal das Wiki zu Modbus durch und schau dir die beiden Schnittstellen auf dem OSI Layern an. Dann verstehst du das vielleicht.

@riogrande75 Ahhh.... ich dachte, ich kann via Modbus in die Register schreiben und dadurch den WR steuern. OK, geht nicht. Habe ich nun verstanden.

Dann versuche ich nun die RS232 Schnittstelle über (W)Lan anzubinden und teste dann deine Kommandos.

Danke dir!

1 „Gefällt mir“

Worin liegt denn der Unterschied zwischen dem ^D054BMS Kommando und ^S005EDmn<cr>: Set energy distribution?

Mit dem ersten Befehl wird der Status im Display angezeigt. Mit dem zweiten nicht. Dafür habe ich hier mehr Optionen.
Mir scheint, dass D054BMS die Möglichkeiten von S005EDmn bündelt, um es auf das Wesentliche zu bringen.

Gibt es auch einen "technischen" Unterschied?

Versteh nicht ganz, auf was du da raus willst...
^S005ED ist ein Config-Setting, welches sogar in den Flash geschrieben wird. Das wird einmal eingestellt und hat rein gar nix mit dem BMS zu tun.

Das ^D054BMS... ist das Kommando, dass dem WR zyklisch die Info's von einem BMS bzw. Batterie gibt. Um diese Info (die er gerade von einem angeschlossenen BMS empfangen hat) dem WR wieder zu entlocken, kann man das mit ^P004BMS<cr> abfragen. Ist zur Diagnose recht hilfreich, um zu prüfen, ob korrekte Daten von einem BMS empfangen werden.

@riogrande75

Ich hatte dein Topic so verstanden, dass du mit dem Befehl die Ladeelektronik des WR zum Akku beeinflusst.

Bei mir übernimmt dies der ^S005ED Befehl. Ich habe mich dann gefragt, wo genau hier der Unterschied ist.

OK, es sind unterschiedliche Befehle mit unterschiedlichen Funktionsumfang.

Für meine "Problemstellung" (die Steuerung der Ladeelektronik) macht es scheinbar keinen Unterschied.
Ich erreiche mit beiden eine Aktivierung bzw. Deaktivierung des Lade/Entladevorgangs.

Hallo zusammen,

@NTG4u:
zunächst kann ich @riogrande75 nur zustimmen: Der Hauptunterschied zw. ^S005ED und ^D054BMS liegt ganz einfach darin, dass mit ^S-Befehlen der interne Flash/EEPROM-Speicher des Wechselrichters beschrieben wird. Sie werden genutzt, um statische Parameter festzulegen. Dieser Speicher ist nicht für dauerhafte Schreibvorgänge ausgelegt. Wird darüber die Steuerung des WRs versucht "nachzubauen" und vielfach am Tag der Speicher neu beschrieben, wirst du ihn früher oder später "töten"!

^D-Kommandos sind sogenannte "Device Response", also Rückinfos von angeschlossenen Geräte (BMS, Smartmeter, usw.), auf die der WR eigenständig auf Grund seiner eingebauten Logik reagiert - je nachdem wie schlau die installierte/aktuelle Firmware ist.

So, nun zu meinem Problem, bei dem ich hoffe, dass ihr mir hier helfen könnt:

Ich versuche eine Regelung via "Dual ModBus Box"-Schema zu implementieren, also die ^D-Kommandos eines externen Smartmeters, der Netzbezug/Lieferung misst, über die Rs232-Schnittstelle an den Wechselrichter (FSP Hybrid 10k) zu senden.
Damit soll die interne Logik des WRs, wenn PV-Leistung anliegt, eine Null-Einspeisung (+ Überschuss zum Laden der Batterie) und anschließend (wenn Batterie voll) eine Voll-Einspeisung realisieren.
Ist die PV-Leistung zu gering soll die Regelung den anliegenden Netzbezug über Entladen der Batterie ausgleichen, bis diese leer ist.

Kennt ihr die entsprechenden ^D-Kommandos, um dem WR die aktuelle Smartmeter-Leistung mitzuteilen?

@an-wi

Ich hab das lt. deiner Anforderung gelöst.

Das Kommando um dem WR den aktuellen Verbrauch oder die aktuelle Erzeugung mitzuteilen lautet:

^S026EMINFO00000,00000,1,00150
^S026EMINFO00000,00000,0,00200

Der erste Befehl sagt dem WR, dass er um 150W mehr einspeisen soll.
Der zweite Befehl, dass er um 200W weniger einspeisen soll.

Ich schicke ihm das aktuell ca. 1-2 mal pro Sekunde, was perfekt funktioniert. Er muss eines der Kommandos aber mindestens einmal alle 3-5 Sekunden erhalten. Sonst hört er auf einzuspeisen.

Sollte dein Smartmeter also den Wert bspw. nur alle 10 Sekunden liefern, dann müsstest du folgende Logik implementieren:

  1. 14:00:00 - Smartmeter liefert Wert 1200W Bezug, bspw. weil sich irgendein Heizgerät eingeschalten hat.
  2. 14:00:00 - Du schickst das sofort mittels ^S026EMINFO-Kommando an den Wechselrichter weiter: ^S026EMINFO00000,00000,1,01200
  3. 14:00:00 - Wechselrichter reagiert und speist 1200W mehr ein.
  4. 14:00:01 - Du schickst das Kommando ^S026EMINFO00000,00000,1,00000 an den Wechselrichter, damit er seine Einspeiseleistung beibehält und nicht aufhört einzuspeisen.
  5. 14:00:[02-09] - Wiederholung von Punkt 4, weil keine neuen Leistungswerte vom Smartmeter vorhanden sind.
  6. 14:00:10 - Neuer Wert vom Smartmeter kommt und der Vorgang 1-5 beginnt von vorn.

Je länger der Intervall ist, wo der Smartmeter die aktuelle Leistung liefert, desto mehr Watt wirst du vom Netz einspeisen und beziehen, weil die Nullausregelung ungenauer wird.
Aber keine Sorge: Auch bei einem Intervall von 10 Sekunden oder mehr wirst du wsl. nicht viel beziehen und einspeisen, außer du hast große Verbraucher, die alle paar Sekunden ein- und wieder ausschalten.

Übrigens: Falls du den seriellen Port der Modbus-Schnittstelle benutzen möchtest, könntest du meinen selbstgebastelten Adapter nachbauen:

Ich hoffe das hilft dir weiter.

lg David

2 „Gefällt mir“

Hallo Riogrande,

eine weitere Frage zum ^D054BMS Kommando. In deinem Skript "readmqttbms.php" wird aus dem aktuell fließendem Strom das Richtungs-Bit extrahiert und der Strom als positiver Wert übergeben:

        if(strpos($message->topic, "Charge_Current")){
$bmscurr = $message->payload;
if($debug) echo "STROM: $bmscurr \n";
$bmscurr = substr(round($bmscurr),-4);
$bmscurr = str_replace("-","0",$bmscurr);
if($bmscurr < 0) $bmsdir = 1;
if($bmscurr >=0) $bmsdir = 0;
shmop_write($sh_bms1, ",".$bmsdir.",".paddings($bmscurr,4), 16);
}

Müsste die Zeile mit dem String-Replace nicht nach der Richtungsabfrage kommen? So dürfte das Richtungsbit immer "0" sein, oder? :hmm:

Grüße Alex

@al_ro Verstehe nicht ganz, was du mit "nach der Richtungsabfrage" meinst. Diese Codeschnippsel macht ja gerade das, weil das BMS bzw. der ESP32 dafür keinen eigenen "Parameter" vorsieht.
Hab mir das gerade nochmal angesehen, funktioniert bei mir auf jeden Fall korrekt.
Wenn Data/Charge_Current auf MQTT Seite mit einem negativen Vorzeichen daherkommt, dann scheibt das Script eine 1 (=discharge) in das SharedMemObj:

@riogrande75
Was @al_ro meint (und was ich auch unlogisch finde), warum du zuerst das "-" (Minus) mit str_replace in $bmscurr ersetzt und erst danach die "< 0"-Prüfung bzw. ">= 0"-Prüfung machst, wenn doch dann gar kein "-" mehr in der Variable drin stecken kann!?!?