The implementation of our battery system continues and I have another question the OpenEMS device.
I have been basing the implementation for our system on the Fenecon Home and Commercial batteries within OpenEMS which has been very useful.
I understand from the code and community posts that the best way to implement a battery is to use StartStoppable, a StateMachine and to use the battery in production with the Generic ESS component.
I am unclear on how the methods for StartStoppable work and are to be implemented and how this relates to the state machine and the physical device.
In the implementation for the Fenecon batteries, I see that the battery implementation maintains startStopTarget which is an AtomicReference to a StartStop which appears to maintain the current state of the system (i.e whether it is started or stopped) and has a config element which sets the default start/stop behaviour.
I am unsure about how this is connected to the actual physical battery and how commands are sent to the battery to start/stop. I can’t find any modbus registers in the code which correspond to starting/stopping the battery via either the StartStop or else the state machine. Is there something I am not understanding about how this code works?
I have another question about the StateMachine - I can see that we have GO_RUNNING and RUNNING as states within the state machine. What is the difference between these? (Same thing for STOPPED and GO_STOPPED)
The specific battery we are using does not have a single Modbus register for starting/stopping the battery. Instead there are separate registers for “Sleep/Wake command”, “Charge command” and “Discharge command” and these are triggered by writing the value “0xAA” to the relevant register.
The manual gives specific guidance that when the battery is in sleep status, it is necessary to send the wake command before charging/discharging. If the battery is in any kind of protection state (e.g over/under voltage) which switches off the main relay, it is necessary to send the relevant charge/discharge command before doing anything else.
Would we need to implement some sort of logic to get the StateMachine to write the correct values to the correct registers as needed?
As you described, a StartStoppable device usually has two sources to know if it should start. Either via a static configuration or via an external call to setStartStop() (or start() or stop()).
Those two sources build the startStopTarget which is then evaluated in the State-Machine - e.g. in the initial UNDEFINED state - see FENECON Home battery for an example. The actual start command then differs for every device, e.g. a FENECON Home battery can be started by toggeling a digital output (see GO_RUNNING)
GO_RUNNING: the device is trying to start (but not yet ready)
RUNNING: the device is actually running and ready to work
This whole procedure really sounds like using a State-Machine is a good way to implement this. I would set the ‘Wake command’ in a GO_RUNNING state and only when the battery is ‘awake’, I would change to RUNNING state.
I am not sure what’s with the “Charge/Discharge commands”, because this is usally not something we control on the Battery (DC) level, but on the BatteryInverter level.
In general: it is never required to use a state-machine, but at least for us it proved to be a great tool to validate/test the expected behaviour and communicate the internal funcationality to our product managers and sales people.
Thank you very much for your detailed answer - extremely helpful as always!
Given that our Start/Stop command is a Modbus register which receives the values ‘0xAA’ and ‘0x55’ to sleep/wake, I am wondering what is the best way to handle this in the code. I would like the relevant channel in our Openems device to be only capable of receiving the correct values and not to allow arbitrary string/character input. Would you have any suggestion on the best way to handle this?
I think that we could have the channel take an enum value which just allows the values for sleep/wake.
Do you think this is a good approach? Are you aware of any examples like this where an enum is used for channel input.
I have checked with our battery manufacturer as I was also unsure about the meaning of the ‘charge’/‘discharge’ commands as one would indeed expect that these are handled by the inverter.
These values are actually only to be set when the battery is in under/over voltage protection mode - once the battery goes into protection mode the main relay is disconnected and it is necessary to manually put the battery into charge/discharge model to get out of the protection mode.
I suppose a way to handle this would be to have the GO_RUNNING handler check whether the battery is in any sort of protection state (which maybe should be defined as a fault in Openems?) and to send the relevant charge/discharge command in order to increase/decrease the voltage to get out of the protection mode.