Asynchronous writing modbus device

Greetings,

I am trying to implement a modbus device bundle that integrates a specific ESS into openEMS. I have succeeded in creating the bundle and it is working fine for monitoring, but it fails when I try to add tasks to write into registers.

I have added a write only channel to my component and mapped it to a FC16WriteRegistersTask, and while it succeeds in writing, it keep doing it cyclically, which is nor optimal (too many useless calls) nor right (it starts writing the initial [0] value and never stops, messing with the ESS).

Is there a way to set the channel to write only when I use setNextWriteValue() function?

The channel declaration:
image

The Modbus task configuration:

I am using float variables, so I plan to use FloatWriteChannel class inside my applyPower() function from my device, a method called by the controller I am implementing in openEMS. I don’t plan to use PID, but direct command. The applyPower() function:
image

I am new to openEMS and as a product owner who dares to make proof of concepts, I am no Java expert as well, so I would be very glad if anyone could help me with this case.

Best regards!

Hi Daniel and welcome to the Community.

This is the actual behaviour. It will not execute a modbus write (FC16) if this method has not been called.

This is ok. The applyPower() method is called on every Cycle. The way you wrote it in the screenshot, it will set the Write-Channel each Cycle and also physically write the register on each Cycle.

This is what we want usually for a storage system, because the ESS knows that there is no timeout and the EMS is still sending commands. Usually there will be some kind of Watchdog implemented on the device side, which requires cyclic writing even if the value is unchanged.

If you wanted to write only let’s say every 60 Cycles, you could add a simple cycle counter with an if. Something along the lines:

private int cycleCounter = 0;
private Integer lastSetActivePower = null;

@Override
public void applyPower(int activePower, int reactivePower) throws OpenemsNamedException {
	if(!Objects.equal(this.lastSetActivePower, activePower) || cycleCounter++ > 59) {
		this.cycleCounter = 0;
		this.lastSetActivePower = activePower;
		var channel = (FloatWriteChannel)this.channel(PocEss.ChannelId.TARGET_ACTIVE_POWER);
		channel.setNextWriteValue(activePower);
	}
}

PID is always used internally before calling the applyPower() method. If you don’t want to use it, you can disable it in the Ess Power Component configuration → https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/Config.java#L26-L27

Regards,
Stefan

Thanks @stefan.feilmeier, i could make it all work thanks to your comment.

Best regards,

Daniel Makohin

1 Like