Ankündigung

Einklappen
Keine Ankündigung bisher.

Einbindung von Modbus TCP

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • ivande
    antwortet


    beim solaredge-Wechselrichter welcher auch nach dem sunspec-Format tickt, hab ich ein eigenes Skale-Faktor-Item (AC_Leistung_sf) angelegt und dann mit dem eval im eigentlichen Leistung-Item (AC_Leistung) die Berechnung gemacht:
    eval: value*10**sh.Photovoltaik.AC_Leistung_sf()

    der Scale-Faktor ändert sich auch laufend, (z.B. 0, -1 -2, -3, -4)

    Code:
    solaredge_SE6000:
        AC_Leistung_sf:    # hier landet der Scale-Faktor z.B. -1
            type: num
            name: I_AC_Power_SF
            enforce_updates: True
            modBusAddress: 40084
            modBusDataType: int16
        AC_Leistung:  # hier wird die Leistung ausgelesen und mit dem Scale-Faktor-Item verrechnet:
                      #z.B. 35.362*10**-1 = 3.536,2 W * 0.001(modBusFactor) = 3,5362 kW
            type: num
            name: I_AC_Power
            enforce_updates: True
            eval: value*10**sh.Photovoltaik.AC_Leistung_sf()
            modBusAddress: 40083
            modBusFactor: 0.001
    wichtig dabei, dass das Item mit dem Skale-Faktor zuerst angelegt wird, damit auch beim Lesen der Modbus-Register zuerst der Scale-Faktor gelesen wird und dann erst das Item mit dem eigentlichen Wert gelesen wird, welches dann das eval auslöst.

    mit modBusFactor: 0.001 skaliere ich das ganze dann noch von Watt auf kW
    Zuletzt geändert von ivande; 08.01.2022, 22:23.

    Einen Kommentar schreiben:


  • tsb2001
    antwortet
    So, kurze Statusrückmeldung:
    Das Plugin läuft nun seit 4 Tagen ohne jegliche Einschränkung oder Fehler.

    Leider ist mir jetzt eines aufgefallen:
    Mein Wechselrichter (und nicht nur Fronius, sondern auch SMA, Kostal, Solaregde usw.) tauscht Daten auf dem Modbus nach dem Sunspec-Format aus. Dies ist ein freier Zusammenschluss ganz vieler Hersteller, um einen herstellerübergreifenden Standart zum Datenaustausch über Modbus einzuführen. Hier kann man mal gucken, wer da alles mitmacht: https://sunspec.org/members/

    Dummerweise kochen die ihr eigenes Süppchen und übertragen die Daten nach einem interessanten Muster:
    in einem Register wird der Wert übertragen, und dann gibt es ein weiteres Register, in dem der ScaleFactor übertragen wird. Es werden folglich nur ganze Zahlen übertragen und die Nachkommastellen werden durch das ausgelesene Register mit dem ScaleFactor in der Stelle „verschoben“.

    Ich habe mich gewundert, warum die Strom- und Leistungswerte nur manchmal zueinander passten. Bis ich gemerkt habe, dass die Stromwerte variabel skaliert werden.

    Jetzt könnte man einfach das Register des jeweiligen ScaleFactor mit auslesen und mit dem übertragenen Wert multiplizieren.

    Leider einfacher als gedacht: Das Datenformat lautet sunssf und besteht aus folgendem Aufbau:
    As an alternative to floating point format, values are represented by integer values with a signed scale factor applied. The scale factor explicitly shifts the decimal point to the left (negative value) or the right (positive value). Scale factors may be fixed and specified in the documentation of a value, or may have a variable scale factor associated with it. For example, a value “Value” may have an associated value “Value_SF” of type “sunssf” that is a 16 bit two’s compliment integer.
    sunssf signed range: -10 ... 10 Not Implemented: 0x8000
    If a value is implemented and has an associated scale factor, the scale factor must also be implemented.
    Die originale Umschreibung findet sich hier: https://sunspec.org/wp-content/uploa...dels-12041.pdf

    Kann mir irgendwer auf die Sprünge helfen, wie ich den „16 bit two’s compliment integer“ aus dem Plugin in eine rechenbare Zahl umgewandelt bekomme?

    Einen Kommentar schreiben:


  • ivande
    antwortet
    super dass es soweit läuft, die index.html hat es aus versehen nicht auf git geschaft. Aber dort war nur die Änderung enthalten welche Du selber herausgefunden hast.

    Einen Kommentar schreiben:


  • tsb2001
    antwortet
    Hi, doch, das war es.
    Die Adresse wurde nach folgendem Format ausgegeben: 40072.200
    Vor der Änderung:
    Vorher.png

    Irgendwie hat die sich in dem Item versteckt. Ich habe jetzt nicht explizit geguckt, wo die herkommt, habe mich aber an der Zusammensetzung des "regToRead" orientiert und die Zeile im Webinterface:
    Code:
    <td class="py-1">{{ item }}</td>
    umgeändert und die Adresse aus dem regToRead herausgelöst mit:
    Code:
    <td class="py-1">{{ p._regToRead[item].regAddr }}</td>
    Nach der Änderung:
    Nachher.png


    Dann passt auch das Ergebnis im Web-Interface.

    Alles andere funktioniert einwandfrei!

    Vielen Dank nochmal!

    Wenn du noch Änderungen implementieren möchtest und dazu Tester suchst, schreib mich gerne an.
    Angehängte Dateien

    Einen Kommentar schreiben:


  • ivande
    antwortet
    Zitat von tsb2001 Beitrag anzeigen
    Alle Register mit gleicher Registernummer vom Smartmeter und Wechselrichter werden mit dem jeweiligen Trennpunkt mit der Unit benannt
    Registernummer mit Trennpunkt und Unit sollte mit der ausgetauschter Datei webif/templates/index.html eigentlich im Webinterface nicht sichtbar sein..

    Einen Kommentar schreiben:


  • tsb2001
    antwortet
    Zitat von ivande Beitrag anzeigen
    hier wären wieder die Änderungen zum Testen:

    https://github.com/ivan73/plugins-mo...lop/modbus_tcp

    bitte auch die anderen Dateien austauschen, nicht nur die __init__.py
    zumindest die plugin.yaml und die Datei webif/templades/index.html
    Noch eben schnell ausgetauscht. Funktioniert bis hierhin ohne Probleme!
    Alle Register mit gleicher Registernummer vom Smartmeter und Wechselrichter werden mit dem jeweiligen Trennpunkt mit der Unit benannt und kommen jetzt auch richtigerweise doppelt an.

    In den Items werden die Werte auch offensichtlich alle gelesen, jedoch sind die Werte des Wechselrichters bei der momentanen Sonneneinstrahlung um 00:49 Uhr leider alle auf "0" 😄
    Ich gebe morgen dazu Rückmeldung!

    Einen Kommentar schreiben:


  • ivande
    antwortet
    hier wären wieder die Änderungen zum Testen:

    https://github.com/ivan73/plugins-mo...lop/modbus_tcp

    bitte auch die anderen Dateien austauschen, nicht nur die __init__.py
    zumindest die plugin.yaml und die Datei webif/templades/index.html


    Zitat von tsb2001 Beitrag anzeigen
    Mal als Info für mich: Mit welchen Methoden entwickelst du das? Hast du irgendwie eine IDE, mit der du online die Daten mitverfolgen kannst?
    angefangen habe ich mit eclipse und Remote Debug, damit kann man den python-Code debuggen und die verschiedensten Variablen von SH verfolgen. Da das Händling damit aber recht umständlich ist, benutze ich eigentlich nur mehr einen Editor (notepad++) und sehe mir die Variabel über Log-Ausgaben an


    Einen Kommentar schreiben:


  • tsb2001
    antwortet
    Ja, auch ne Lösung!
    Wenn ich was testen soll, nur her damit. Heute wird es nichts mehr; da ich aber noch Urlaub habe, kann ich morgen experimentieren.

    Mal als Info für mich: Mit welchen Methoden entwickelst du das? Hast du irgendwie eine IDE, mit der du online die Daten mitverfolgen kannst?

    Einen Kommentar schreiben:


  • ivande
    antwortet
    hab es inzwischen schon so gelöst, allerdings mit dem unit dahinter,.. muss nur noch ein paar Tests machen, voraussichtlich am abend kann ich es dann ins git pushen


    Adresse "40072" + Unit "200" ergibt 40072.200

    Einen Kommentar schreiben:


  • tsb2001
    antwortet
    Zitat von ivande Beitrag anzeigen

    das letzte gewinnt.. zur Problem-Behebung muss ich im plugin die Auflistung anpassen/umgestalten, da die Registeradresse als Dictionary-Key verwendet wird und nur 1x enthalten sein kann.. ich melde mich wenn es wieder ein update zum testen gibt.

    Danke für Deine Rückmeldung
    Nee, FALSCH! Vielen Dank für diese gute Arbeit und deine Mühen!

    Aber ich ich mir schon gedacht. Ich versuche grade, den Code zu verstehen. Leider sind meine Python-Kenntnisse sehr rudimentär, sonst würde ich gerne mehr helfen.
    Ich habe die Unit mal mit ins Webinterface gebracht und da sieht man das Ergebnis ganz gut:
    Unbenannt.png

    Einfach mal eine Idee: Was ist denn, wenn du im Dictionary die Unit dem Register vorne anstellst, sodass sich eine beispielsweise Zahl mit 8 Stellen ergibt
    Aus dem Register des Wechselrichters mit der Unit "1 " und dem Strom L1 der Adresse "40072" würde "00140072"
    Aus dem Register des Smartmeters mit der Unit "200" und dem Strom L1 der Adresse "40072" würde "20040072"
    Ein weiterer Zähler mit der Unit 201 würde auf die "20140072" den Strom L1 zuordnen.

    Der Vorteil wäre; egal wie viele Units vorkommen würden, der Index wäre eindeutig, da die Nummer der Unit nur einmal vorkommt.
    Beispiel Fronius: es lassen sich noch mehr Zähler via ModBus RTU anschliessen. Somit könnte auf der Modbus-TCP-Seite auch ein gleicher Zähler mit der Unit 201, 202, usw. entstehen.
    Durch das Voranstellen der Unit wäre somit eine eindeutige Indizierung möglich.
    Angehängte Dateien

    Einen Kommentar schreiben:


  • ivande
    antwortet
    Zitat von tsb2001 Beitrag anzeigen
    Da es zwei gleiche (aber mit unterschiedlichen Units) versehene Registernummern gibt, fragt er immer nur eine von beiden (mit der vielleicht höheren BusUnit?) ab.
    Oder "gewinnt" das letzte hierarchisch angeordnete Item in der Item-Konfiguration?
    das letzte gewinnt.. zur Problem-Behebung muss ich im plugin die Auflistung anpassen/umgestalten, da die Registeradresse als Dictionary-Key verwendet wird und nur 1x enthalten sein kann.. ich melde mich wenn es wieder ein update zum testen gibt.

    Danke für Deine Rückmeldung

    Einen Kommentar schreiben:


  • tsb2001
    antwortet
    ivande

    Hey, super, vielen Dank!
    Ich habe einfach nur die __init__.py getauscht und es funktioniert mit der Angabe von mehreren Units einwandfrei.

    Wo es noch hängt:
    beim parsen der Items wird ja quasi der Index der Abfrage anhand der ModBus-Adressen erzeugt.
    Da es zwei gleiche (aber mit unterschiedlichen Units) versehene Registernummern gibt, fragt er immer nur eine von beiden (mit der vielleicht höheren BusUnit?) ab.
    Oder "gewinnt" das letzte hierarchisch angeordnete Item in der Item-Konfiguration?

    Der erste Eintrag unten vom Strom L1 (das ist der Wechselrichter) wird gar nicht abgefragt und auch nicht getriggert. Da steht immer nur
    Update durch Init:Initial_Value
    beim Starten von SmarthomeNG.

    Versehe ich die Zeilen vom Smartmeter mit der "#" (I_SM_L1), gibt es nur den einen Eintrag mit (I_L1) vom Wechselrichter. Dieser wird dann auch korrekt gelesen.
    Nehme ich die "#" wieder weg und werden zwei Einträge generiert, "gewinnt" wieder das Smartmeter und liefert Daten.

    Beispiel:
    Code:
    PV_GEN_24:
       I_L1:
          type: num
          value: '0'
          modBusAddress: 40072
          modBusUnit: '1'
          modBusFactor: '0.0001'
    ...
       I_SM_L1:
          type: num
          value: '0'
          modBusAddress: 40072
          modBusUnit: '200'
          modBusFactor: '0.0001'

    Einen Kommentar schreiben:


  • ivande
    antwortet
    hab nun slaveUnit zu den Itams hinzugefügt:

    Code:
     modBusUnit: '71'                    #(optional) default: slaveUnit aus der Plugin-Konfig
    evtl. zum Austesten aus meinem Fork:

    https://github.com/ivan73/plugins-mo...lop/modbus_tcp

    Einen Kommentar schreiben:


  • Bonze
    antwortet
    .. war quatsch, die id muss also per item gespeichert werden und beim auslesen mit genutzt werden, weil tcp eigentlich diese angabe nicht nutzt,.., aber in kombination von Modbus RTU und TCP kann sie genutzt werden , und das is genau hier der fall..

    Einen Kommentar schreiben:


  • tsb2001
    antwortet
    Hier hat das jemand mit Node Red und pymodbus umgesetzt. Leider verstehe ich in python nur Bahnhof:

    Hello,
    for pymodbus, some code snippets (replace your IP of course):
    Code:
    from pymodbus.client.sync
    import ModbusTcpClient as ModbusClient
    from pymodbus.payload import BinaryPayloadDecoder
    from pymodbus.constants import Endian
    client = ModbusClient('your IP address here', port=502)
    client.connect()
    Note, it shouldn't matter if you go via WLAN or LAN, just as long as your on same subnet.
    then the following constants to address the inverter and meter:
    (note you must address them in hex. my meter id is 240 and inverter is 1
    Code:
    INVERTER = 0x1 #1 in decimal
    METER = 0xf0 #240 in decimal
    then an example function:
    Code:
    def show_import_read():
        """ shows import energy count of meter
        register 40138
        2 registers
        value is Wh returns float32 """
        myresponse = client.read_holding_registers(40138-1, 2, unit=METER)
        decoder = BinaryPayloadDecoder.fromRegisters(myresponse.registers,byteorder=Endian.Big)
    return decoder.decode_32bit_float()
    You'll see that the read holding registers function take a parameter "unit", not the main connect function.
    register list was obtained from Fronius website.
    The decoder functions made life easier.
    it's not easy to display the code neatly.

    …nur falls es hilft…

    Einen Kommentar schreiben:

Lädt...
X