Modbus Kommunikation in unterschiedlichen Geschwindigkeiten

Hallo Zusammen,

Ich möchte gerne verschiedene Modbusgeräte unterschiedlich oft auslesen/beschreiben.
Ein Batteriewechselrichter soll beispielsweise alle 200ms geschrieben und gelsen werden. (Das ist dann einfach die cycle Time)
Aber eine andere Komponente, eine Klimaanlage, ist nicht in der Lage mit so vielen Anfragen umzugehen, deswegen würde ich sie gerne selterner, z.B. nur alle 10s lesen/schreiben.

Gibt es in OpenEMS dafür eine Möglichkeit? Ich habe bisher keine finden können.
Zumindest nicht, ohne tief in der Modbus Bridge oder dem Modbus Worker Änderungen vornehmen zu müssen, was ich nach Möglichkeit gerne vermeiden würde.

Hat jemand Ideen wie man das möglichst einfach unsetzten kann?

Viele Grüße

Tobi

So, ich habe eine Lösung gefunden und schreibe das hier einfach mal rein, vielleicht hilft es irgendwann nochmal jemandem.

Eine in OpenEMS eingebaute Funktion die das einfach so tut habe ich nicht gefunden, aber man kann über die jeweilige ModbusBridge mit der Funktion removeProtocol(componentId) das Modbus Protokoll entfernen, sodass es nicht mehr ausgeführt wird:

getBridgeModbus().removeProtocol(this.config.id());

Und dann nach der entsprechenden gewünschten Zeit vieder hinzufügen:

getBridgeModbus().addProtocol(this.config.id(), getModbusProtocol());

Dabei ändert sich das Modbus Protokoll nicht, auch wenn man in der defineModbusProtocol() das return von bestimten Dingen abhängig macht. Das liegt daran dass das Protokoll in der ModbusBridge in einer private Variable gespeichert wird. So wird beim ausführer der getModbusProtocol() einfach der gespeicherte Wert zurückgegeben:

/**
	 * Gets the {@link ModbusProtocol}. Creates it via
	 * {@link #defineModbusProtocol()} if it does not yet exist.
	 * 
	 * @return the {@link ModbusProtocol}
	 * @throws OpenemsException on error
	 */
	protected ModbusProtocol getModbusProtocol() throws OpenemsException {
		ModbusProtocol protocol = this.protocol;
		if (protocol != null) {
			return protocol;
		}
		this.protocol = this.defineModbusProtocol();
		return this.protocol;
	}

In meinem Fall wollte ich aber das Protokoll dahingehend ändern, dass ich immer Werte Lesen, aber nur unter bestimmten bedingungen Werte schreiben wollte. Das habe ich gelöst, indem ich bewusst über die setNextWriteValue den Wert auf null gesetzt habe:

	try {
		this.get_temp_heat_target_write_channel().setNextWriteValue(null);
	} catch (OpenemsNamedException e) {
		e.printStackTrace();
	}

In diesem Fall werden die Write Tasks nicht ausgeführt, obwohl sie im Modbus Protokoll drin sind. Ich habe nicht nachgeforscht woran das liegt, aber es funktioniert zuverlässig.

Das ist vermutlich keine Awendung, wie sie von den Entwicklern vorgesehen war, aber wie gesagt, es funktioniert in meinen Tests zuverlässig.

Viele Grüße

Tobi

Hallo Tobi,

danke für die Rückmeldung. Ich hätte das vermutlich für diesen Fall genau so gelöst. Man könnte darüber nachdenken so etwas als Standardfunktion mit einzubauen - so ähnlich wie das bereits über die Priority im ModbusTask funktioniert.

Den Teil mit den Write Tasks habe ich nicht verstanden. Es ist by design so, dass Write-Register nur beschrieben werden, wenn deren Wert != null ist:

Die Logik, dass ein Wert nicht ständig gesetzt wird, haben wir dann meistens im Controller. Ein “Fix Digital Output Controller” wird z. B. nur den Write-Channel beschreiben, wenn der Digitalausgang noch nicht dem Zielwert entspricht:

Gruß,
Stefan

Hi Stefan,

danke für den Hinweis. Ich glaube ich hatte gar nicht getestet was passiert wenn man ein einfach keinen NextWriteValue setzt. (Ich bin aus mir gerade unbekannten Gründen einfach davon ausgegangen, dass es die Werte stehen bleiben bis neue kommen).
Dann kann ich mir da ein paar Zeilen Code sparen.

Grüße

Tobi

1 Like