Modbus FC16WriteRegistersTask - simultanes Schreiben

Hallo,

ich bin gerade dabei einen ESS in OpenEMS zu integrieren. Der Wechselrichter möchte drei SignedInt 32 auf einmal geschrieben haben. Mit FC16WriteRegisters werden die drei Register aber hintereinander geschreiben. Das akzeptiert der Wechselrichter nicht.

new FC16WriteRegistersTask(487, //
	m(InverterX.ChannelId.EMS_POWER_SET, new SignedDoublewordElement(487)), //
	m(InverterX.ChannelId.EMS_MIN_BAT_CHARGE, new SignedDoublewordElement(489)), //
	m(InverterX.ChannelId.EMS_MAX_BAT_CHARGE, new SignedDoublewordElement(491))
)

Danke für die Hilfe!

Hallo taschaue,

um sicherzustellen, dass alle drei SignedInt 32 Register gleichzeitig geschrieben werden, können wir die FC16WriteRegistersTask so konfigurieren, dass alle Register in einem einzigen Modbus-Request geschrieben werden. Hier ist die Lösung:

Hier ist ein Beispiel, wie du die FC16WriteRegistersTask konfigurieren kannst, um die drei Register gleichzeitig zu schreiben:

import io.openems.edge.bridge.modbus.api.element.SignedDoublewordElement;
import io.openems.edge.bridge.modbus.api.task.FC16WriteRegistersTask;
import io.openems.edge.ess.core.channel.ChannelId;

public class InverterX {

    // Definiere die Kanal-IDs für den Wechselrichter
    public static class ChannelId {
        public static final String EMS_POWER_SET = "EMS_POWER_SET";
        public static final String EMS_MIN_BAT_CHARGE = "EMS_MIN_BAT_CHARGE";
        public static final String EMS_MAX_BAT_CHARGE = "EMS_MAX_BAT_CHARGE";
    }

    // Konfiguriere die Aufgabe zum Schreiben von Registern
    public void configureTask() {
        new FC16WriteRegistersTask(487,
            // Weise den Kanälen die entsprechenden Modbus-Elemente zu
            m(ChannelId.EMS_POWER_SET, new SignedDoublewordElement(487)),
            m(ChannelId.EMS_MIN_BAT_CHARGE, new SignedDoublewordElement(489)),
            m(ChannelId.EMS_MAX_BAT_CHARGE, new SignedDoublewordElement(491))
        );
    }

    // Methode zur Zuordnung der Kanäle zu den Elementen
    private Object m(String channelId, SignedDoublewordElement element) {
        // Implementiere diese Methode, um die Kanäle den Elementen zuzuordnen
        // Dies ist ein Platzhalter für die tatsächliche Implementierung
        return new Object(); // Ersetze dies durch die tatsächliche Zuordnungslogik
    }
}

Erklärung:

  • FC16WriteRegistersTask startet bei Adresse 487.
  • m(ChannelId.EMS_POWER_SET, new SignedDoublewordElement(487)) erstellt ein Element für Adresse 487.
  • m(ChannelId.EMS_MIN_BAT_CHARGE, new SignedDoublewordElement(489)) erstellt ein Element für Adresse 489.
  • m(ChannelId.EMS_MAX_BAT_CHARGE, new SignedDoublewordElement(491)) erstellt ein Element für Adresse 491.

Diese Konfiguration sollte sicherstellen, dass alle drei Register in einem einzigen Modbus-Request geschrieben werden, was den Anforderungen des Wechselrichters entspricht.

Ich bitte dich ebenfalls, deine Implementierung öffentlich zu machen, sollte sie fertig sein, so profitieren wir alle davon !

Grüße !

1 Like

@taschaue: Die Register eines FC16WriteRegistersTask werden alle auf einmal geschrieben, wenn auch wirklich alle Werte gesetzt sind. (Nachzulesen im Code ist das hier → openems/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/FC16WriteRegistersTask.java at develop · OpenEMS/openems · GitHub)

Du musst also sicherstellen, dass z. B. in der applyPower()-Methode alle drei Write-Channels gesetzt werden:

this.channel(InverterX.ChannelId.EMS_POWER_SET).setNextWriteValue(1);
this.channel(InverterX.ChannelId.EMS_MIN_BAT_CHARGE).setNextWriteValue(0);
this.channel(InverterX.ChannelId.EMS_MAX_BAT_CHARGE).setNextWriteValue(1234);

Viel Erfolg bei der Implementierung.

Ich würde mich natürlich ebenfalls über den Quellcode freien - darum geht’s ja bei OpenEMS :wink:

1 Like

Hallo @stefan.feilmeier & @Sn0w3y,

vielen Dank für die raschen Infos. Hat jetzt funktioniert. Wenn die Implementierung fertig ist, dann werde ich einen Pull Request erstellen.

Hätte noch ein zweites Thema - kann dazu aber auch gerne ein neues Topic eröffnen. Über das obige Modbus Register kann ich nur die aktuelle Einspeise- oder Bezugsleistung am NAP setzen. Der Wechselrichter hat einen Smartmeter über RS485 und regelt dann am NAP auf die gesetzte Leistung aus. Das funktioniert soweit - ist aber meiner Meinung nach nicht wirklich kompatibel mit den openEMS Controllern. Ich habe versucht, dass ich einfach von “setActivePower” die “consumptionActivePower” abziehe. Das erzeugt aber unschöne Schwingungen, da vermutlich die Smartmeter Register zu langsam im Wechselrichter neu gesetzt werden bzw. zu langsam gelesen werden. Habt ihr schon Erfahrungen mit ESS, wo nur die aktuelle Leistung am Netzanschlusspunkt gesetzt werden kann?

Beste Grüße!

Hey :slight_smile:

Ich bin raus, dazu müsste ich leider den Code sehen, da ich mir das praktisch so immer besser vorstellen kann.

Eventuell hat @stefan.feilmeier da noch eine Idee.

Grüße !

Hallo @taschaue,

die Berechung wäre auch mein Ansatz gewesen. Wenn die Daten aber nicht zusammenstimmen, hast du keine Chance. Ich sehe zwei Möglichkeiten:

  1. Versuche mit dem PID-Regler in Ess.Power die Regelung so weit zu verlangsamen, dass die Schwingungen weniger werden.

  2. Wenn der Wechselrichter ohnehin selbst am NAP ausregelt, könntest du einen “SMART-Mode” wie bei FENECON Home mit GoodWe umsetzen. Dieser übernimmt nur immer dann die Regelung, wenn sie von Eigenverbrauchsoptimierung abweicht: Laden/Entladen am Fronius Symo Gen24 Hybridwechselrichter mit Modbus - #3 by stefan.feilmeier

Gruß,
Stefan

Danke für die schnelle Rückmeldung bei Nacht :wink:

Kann ich die Parameter des PID Reglers auch in der Implementierung des neuen Wechselrichters anpassen oder ist das nur zentral möglich/sinnvoll? Hintergrund wäre: wenn ich zwei verschiedene ESS habe, das die Parameter unterschiedlich sind.

Den Smart Modus habe ich vor umzusetzen. Ich möchte aber z.B. BuyFromGrid mit openEMS nutzen und da benötige ich vermutlich die Übersteuerung des Wechselrichters. Bei Eigenverbrauchsoptimierung möchte ich auf jeden Fall den Algorithmus des WR nutzen, da dieser bestimmt schneller ist und besser appliziert wurde.