Controller
A OpenEMS Edge Controller holds the actual business logic or the actual algorithm that controls hardware. The logic of each active Controller is executed regularly on every Cycle, i.e. once per second.
On each execution cycle, e.g. once every second, the EMS can send a control command, which allows two different ways of controlling the hardware:
-
Control by setpoint
In “control by setpoint” mode, the EMS calculates setpoint commands and sends them to the hardware for immediate execution.
Example: A power smoothing algorithm uses the current and previous output power values of a photovoltaics system. By applying its configured maximum defined ramp rate it deduces that the energy storage systems needs to be discharged with 150 kW to compensate a suddenly reduced output power. It therefore sends a setpoint for "discharge with 150 kW" to the ESS for immediate execution.
-
Control by parameterization
In “control by parameterization” mode, the EMS sends the configuration parameters for control algorithms embedded into the hardware for internal execution.
Example: In a Virtual Inertia Ancillary Services application, the EMS sends the configuration parameters for the control characteristics to the ESS. The ESS uses this parameter set for its internal, high-performance algorithm.
The following Controllers are implemented in the OpenEMS standard codebase. The links point directly to the source code.
1. Api Backend
Connects to OpenEMS Backend and sends all Channel data regularly. It is implemented as a Controller, as Channels can be written from OpenEMS Backend.
2. Api Modbus
The OpenEMS Edge Modbus-Slave-API is provided by the "Modbus-API Controller". As the Modbus protocol is widely used in industrial monitoring and automation, this allows for easy access to OpenEMS channels from external systems.
The configuration of the Modbus-API controller defines which OpenEMS Components should be exported and made available via the API. It then generates a dynamic Modbus protocol that is structured in address blocks that map to OpenEMS Components and Modbus register addresses that map to OpenEMS channels.
The modbus table is designed in a way that allows dynamic parsing of all available registers.
The following example describes a Controller that is configured to export the Sum-Component (_sum
). By reading the headers of the individual blocks, the entire Modbus protocol can be parsed dynamically:
-
Register
0
identifies the system as an OpenEMS by the hash value0x17ed6201
. -
Register
1
shows the length of the first block. Adding the length (199
) the current address (1
) gives the starting address of the next block (200
). -
Register
200
gives a string with fixed length of 16 characters with the Component-ID. -
Register
216
shows the length of the complete block. Adding the length (300
) to the starting address of the block (200
) gives the starting address of the next block (500
) and so forth. -
Register
220
identifies the first sub-block as NatureOpenemsComponent
. The length of the sub-block follows in Register221
and gives the starting address of the next sub-block (300
) and so on.
Instead of parsing the Modbus protocol, it is also possible to download the EMS specific Excel file via OpenEMS UI "System Profile" menu. An example export is available in the 'doc' folder of this bundle.
To communicate with specific channels, it is then sufficient to read or write to the matching registers, e.g.
- Read register 302 _sum/EssSoc
to get the total average state of charge of the ESS.
- Write to register 806 ess0/SetActivePowerEquals
to trigger charging or discharging of the ESS with ID ess0
.
3. Api MQTT
Publishes OpenEMS Edge data to a MQTT broker.
-
edge/{OpenEMS-Edge-ID}/channel/{Component-ID}/{Channel-ID}
-
Data of Channels is published on change and at least every 5 minutes to these topics.
-
Example:
edge/edge0/channel/_sum/GridActivePower
-
-
edge/{OpenEMS-Edge-ID}/channel/lastUpdate
-
Timestamp of the latest data update on any of the Channel topics above.
-
Example:
edge/edge0/channel/lastUpdate
-
-
edge/{OpenEMS-Edge-ID}/edgeConfig
-
Configuration of the OpenEMS Edge instance is published to this topic as a JsonObject.
-
Example:
edge/edge0/edgeConfig
-
4. REST-Api Controller
A REST-Api for external access to OpenEMS Edge. This Controller provides access to Channels and JSON-RPC Requests from an external device via JSON/REST.
The default port for the server is 8084; so the default base address for REST calls is http://x:<PASSWORD>@<IP>:8084/rest
, where
-
http
is the protocol -
x
is the user. Authentication in OpenEMS is via password only, so the username can be omitted. -
<PASSWORD>
is the user password. If no specific settings have been made, try 'user' or 'admin' here. -
8084
is the configured port
A good way to test REST-Api calls is via the Chrome extension Restlet
For more information find the implementation Source Code .
Those are the available REST-Api endpoints:
4.1. Endpoint /rest/channel/<Component-ID>/<Channel-ID>
-
Component-ID
is the ID of the Component, e.g. "_sum", "ess0", "meter0",… -
Channel-ID
is the ID of the Channel, e.g. "ActivePowerL1", "Soc",…
4.1.1. GET
Use a HTTP request with method GET
to read the current value of a Channel.
Example: To read the current state of charge of the battery, send a GET request to http://x:user@localhost:8084/rest/channel/_sum/EssSoC. It returns a response like:
{
"type":"INTEGER",
"accessMode":"RO",
"text":"",
"unit":"%",
"value":50
}
The GET
api also understands regular expressions. Send a GET request to http://x:user@localhost:8084/rest/channel/.*/Active.*Power to read all ActivePower
and ReactivePower
channels of all components. It returns a response like:
[
{
"address":"pvInverter0/ActivePower",
"type":"INTEGER",
"accessMode":"RO",
"text":"",
"unit":"W",
"value":90
},
{
"address":"meter0/ActiveProductionPower",
"type":"INTEGER",
"accessMode":"RO",
"text":"",
"unit":"W",
"value":465
},
{
"address":"meter0/ActivePower",
"type":"INTEGER",
"accessMode":"RO",
"text":"",
"unit":"W",
"value":465
},
{
"address":"meter0/ActiveConsumptionPower",
"type":"INTEGER",
"accessMode":"RO",
"text":"",
"unit":"W",
"value":0
}
]
4.1.2. POST
Use a HTTP request with method POST
to write a Channel.
Example: To switch a Digital-Output or Relay on, send a POST request to http://x:user@localhost:8084/rest/channel/io0/Relay1 with the following body:
{
"value": true
}
4.2. Endpoint '/jsonrpc'
This allows remote procedure calls (RPC) using JSON-RPC. The JSON-RPC commands need to be sent as POST
requests with the specified body.
JSON-RPC usually requires the properties 'id' and 'jsonrpc'. Those can be omitted here, as they are not required for HTTP POST calls. |
Following JSON-RPC commands are available:
4.2.1. getEdgeConfig
Gets the current configuration of the OpenEMS Edge.
{
"method": "getEdgeConfig",
"params": {}
}
5. Api Websocket
Provides a JSON/REST implementation via HTTP Websocket for OpenEMS Edge. It provides access to Channels and JSON-RPC Requests from an external device via Websocket. This Controller is used for local connection of OpenEMS UI.
6. Asymmetric Balancing Cos-Phi
Controls an asymmetric energy storage system in self-consumption optimization mode while keeping the grid meter on a defined cos-phi.
7. Asymmetric Fix Reactive Power
Sets a fixed reactive power for an asymmetric energy storage system.
8. Asymmetric Peak-Shaving
Applies asymmetric peak-shaving at the grid meter using a energy storage system. The controller evaluates the grid meter phase with the highest load and discharges the energy storage system accordingly to cut this power peak in order to avoid the fuse to be triggered. On low consumption periods the energy storage system recharges.
9. Asymmetric Phase Rectification
Balances the three phases at the grid using an asymmetric energy storage system.
10. Channel-Threshold
Generic Controller that sets a digital output according to the value of given Channel - e.g. turn a Relay on, when battery state of charge is above a given threshold.
11. CHP control via State-of-Charge (SoC)
Controls a CHP device. Signals the CHP to turn 'ON' when battery SoC is low; signal it to turn 'OFF' when SoC is high. This controller needs four parameters,
-
State of Charge(Soc) of the ESS.
-
Low Threshold(LT) Soc
-
High Threshold(HT) Soc
-
Output channel to signal.
The Soc of the Ess is compared with the LT and HT, and The following operations or state change is performed.
-
If the Soc is less-than("<") LT, signal is sent to the Output channel which eventually turns the CHP device 'ON'.
-
If the Soc is greater-than(">") HT, signal is sent to the Output channel which turns the CHP device 'OFF'.
-
Any other conditions the there is no change in the State of the CHP device.
11.1. Configuration
-
Component-ID
Unique ID of this Component (id), e.g. "ctrlIoAlarm0", "ctrlIoAlarm1" -
Alias
Human-readable name of this Component; defaults to Component-ID (alias) -
Input Channels
Addresses of the input State-Channels (inputChannelAddress), This is a array of input state channels. -
Output Channel
Channel address of the Digital Output that should be switched (outputChannelAddress) -
Low Threshold
Low boundary of the threshold -
High Threshold
High boundary of the threshold
12. Detailed Debug Log
Constantly shows the values of all Channels of a Component on the console. Primarily used for developing and debugging.
13. Debug Log
Constantly shows the most important values of all Components on the console. This is often activated by default to be able to track the running system easily.
The 'most important values' are predefined by the individual OpenEMS Components. The configuration allows to
additionalChannels
-
add additional Channels to the log
ignoreComponents
-
ignore the output of certain Components
The priority of additionalChannels
is higher than ignoreComponents
, so an explicitly added Channel will be logged even if the Component has explicitly been ignored.
15. Ess Active Power Voltage Characteristic
-
This controller charges/discharges an energy storage system with active power in order to keep the grid voltage within an acceptable range.
-
The active power set-point depends on the ratio of the grid voltage divided by the configured
nominalVoltage
parameter. -
The active power per voltage ratio is defined by a poly-line graph in the
lineConfig
parameter. It takes a Json-Array of the following form:
[ { "voltageRatio":0.95, "power":4000 }, { "voltageRatio":0.97999, "power":1000 }, { "voltageRatio":0.98, "power":0 }, { "voltageRatio":1.0299, "power":0 }, { "voltageRatio":1.03, "power":-1000 }, { "voltageRatio":1.05, "power":-4000 } ]
-
waitForHysteresis
parameter: active power set-point is not updated more often than the hysteresis time in seconds. Default value is 20 seconds. The purpose of this parameter is to avoid oscillation in grid voltage via frequently setting power.
16. ESS Balancing
This controls a energy storage system in self-consumption optimization mode by trying to balance the power at the grid connection point, i.e.: - charge the battery, when production is larger than consumption (i.e. when feeding power to the grid) - discharge the battery, when consumption is larger than production (i.e. when buying power from the grid)
16.1. Requirements
-
ManagedSymmetricEss, a controllable energy storage system
-
ElectricityMeter, a meter at the grid connection point
17. Cycle Controller
This controller was developed to support battery cycling or battery capacity test scenarios.
17.1. Configuration
Parameters which should be taken care of:
mode
-
Select MANUAL_ON to activate the logic
ess_id
-
Id of the device. ex, ess0
cycleOrder
-
Initial step decide whether to start with charge or discharge in type of 'CycleOrder'. ex, START_WITH_DISCHARGE
standbyTime
-
The time to wait between charge and discharge in minutes. ex, standbyTime=5, means wait 5 minute before switching from charge to discharge
startTime
-
Start time in format [YYYY-MM-DD HH:MM], activates the controller logic at required date and time
maxSoc
-
The maximum state-of-charge value that will be reached for charging when the controller is activated. For maxSoc=100 charging will be stopped only when 'AllowedChargePower' is 0; otherwise charging stops at maxSoc
minSoc
-
The minimum state-of-charge value that will be reached for discharging when the controller is activated. For minSoc=0 discharging will be stopped only when 'AllowedDischargePower' is 0; otherwise discharging stops at minSoc
power
-
The power in Watt to charge or discharge
hybridEssMode
-
Whether to apply the power on AC or DC side of a hybrid ESS
totalCycleNumber
-
Number of charge/discharge cycles
finalSoc
-
After the last cycle, the battery will be charged/discharge to this state-of-charge
17.2. Monitoring
Channels can be followed from Grafana or online monitoring:
ctrlEssCycle0/AwaitingHysteresis
-
Active when waiting between two states (see standby-time)
ctrlEssCycle0/CompletedCycleNumber
-
Number of already completed cycles
ctrlEssCycle0/StateMachine
-
The current State of the State-Machine: UNDEFINED, FINISHED, CHARGE, DISCHARGE, STORE_SOC, etc. states.
17.3. Algorithm logic
Controller starts with UNDEFINED
state. First checks for cycleOrder
configuration. If it is defined, according to the selection goes to CHARGE or `DISCHARGE
state.
If cycleOrder
is not defined, selection is made according to the Soc value.
If Soc is higher than 50 % starts with CHARGE
state, otherwise starts with DISCHARGE
state.
If the second state is CHARGE
state, controller start to charge the system until maxSoc
. Again, if it is configured as 100 %, when allowed charge power is 0 W, charge will be stopped. Then, based on the standbyTime
configuration will wait until hysteresis completed.
Afterwards, will switch to DISCHARGE
state.
If the second state is DISCHARGE
state, controller start to discharge the system until minSoc
. Again, if it is configured as 0 %, when allowed discharge power is 0 W, discharge will be stopped. Then, based on the standbyTime
configuration will wait until hysteresis completed.
Afterwards, will switch to CHARGE
state.
After first CHARGE
and DISCHARGE
next state will be FINISHED
. If the totalCycleNumber
is "1", next state will be FINAL_SOC
. And in this state, according to the finalSoc
system will be charged or discharged last time.
If the totalCycleNumber
is higher than "1", next cycle will be called. This process will repeat itself until totalCycleNumber
reaches. At the end, last state will be FINAL_SOC
and required last Soc value will be kept in the battery.
18. ESS Delay Charge
This Controller delays full charing of an energy storage system (ESS) to a certain hour of the day. If for example configured to delay till 4 pm, the allowed charge power is limited in a way, that 100 % State-of-Charge is reached only at 4 pm. The Controller therefor constantly watches the remaining time and remaining capacity of the ESS.
19. ESS Delayed Sell-To-Grid
Controls an energy storage system so, that it delays the sell-to-grid power e.g. of a photovoltaics system.
It charges the battery, when sell-to-grid power exceeds the configured "Sell-To-Grid power limit" and discharges when sell-to-grid power is falling below "Continuous Sell-To-Grid power".
20. ESS Emergency Capacity Reserve
This Controller allows setting a ReserveSoc
as the minimum State-Of-Charge that should be reached during normal on-grid operation, i.e. a energy storage system in self-consumption optimization mode will stop discharging at this SoC.
It is used to keep a certain part of the capacity as reserve for power outage situations.
21. ESS Fast Frequency Reserve
21.1. 1.1 Introduction
In electricity networks, the Fast Frequency Reserve (FFR) controller is providing power available to the system operator within a short interval to meet demand in case of a frequency drop, i.e. in case a generator goes down or there is another disruption to the supply. More details on Wikipedia.
This controller helps the Energy Storage System (ESS) to provide power, essentially battery discharge, when the measured "Grid frequency" is lower than that of a defined "Frequency limit".
21.2. 1.2 Controller Parameters
-
mode: mode of the controller, On or Off?
-
id: the id for the controller
-
alias: Alias for the controller
-
enabled: enabled or not?
-
meterId: the id of the meter
-
essId: the id of the Ess
-
batteryInverterId: the id of the battery inverter
-
preActivationTime: A time before the activation time for charging the system(min).
-
schedule: scheduling of the controller, via JSON see below for the example
21.2.1. 1.2.1 The Example Schedule-JSON
[
{
"startTimestamp": 1684792800,
"duration": 86400,
"dischargePowerSetPoint": 92000,
"frequencyLimit": 50000,
"activationRunTime": "LONG_ACTIVATION_RUN",
"supportDuration": "LONG_SUPPORT_DURATION"
},
{
"startTimestamp": 1684879200,
"duration": 86400,
"dischargePowerSetPoint": 6000,
"frequencyLimit": 50000,
"activationRunTime": "LONG_ACTIVATION_RUN",
"supportDuration": "LONG_SUPPORT_DURATION"
}
]
21.2.2. 1.2.2 JSON Element details
-
StartTimeStamp
: When the controller should be activated. -
Duration
: How long is the controller to be activated? -
frequency limit
: The controller continuously monitors and checks whether a Frequency limit or threshold is less than the measured grid frequency. -
DischargePower
: The Ess discharges from the batteries when generating capacity. -
activationRunTime
: The time in milliseconds required for the reserve to fully activate. Short(700 ms) or Medium(1000 ms) or Long(1300 ms) activation Time. -
supportDuration
: The time in milliseconds for which the reserve should continue providing support after the frequency has stabilized. Short(5 seconds) or Long(30 seconds) support duration.
21.2.3. 1.2.3 Explanation of the Schedule
The Schedule JSON activates FFR for a full day (86400 seconds or 24 hours) with the following parameters:
-
Schedule for 23rd May 2023 00:00:00 to 24th May:
-
Threshold frequency: 49700 mHz
-
Discharge power: 92000 W
-
Long activation time: 1.3 seconds
-
Support duration: 30 seconds
-
-
Following Schedule for 24th May 2023 00:00:00 to 25th May:
-
Threshold frequency: 49700 mHz
-
Discharge power: 52000 W
-
Long activation time: 1.3 seconds
-
Support duration: 30 seconds
-
21.3. 2.1 REST API for updating Fast Frequency Reserve controllers schedule locally
note : The controller/ App should be activated to update the schedule, which can be done using online monitoring or apache felix.
21.4. 2.1.1 Overview
This REST API allows you to update FFR schedule for the specified edge device. The API endpoint takes a JSON payload that specifies the schedule, including the start time, duration, discharge power set point, frequency limit, activation runtime, and support duration.
21.5. 2.1.2 Endpoint
-
Method: POST
-
Content-Type: application/json
-
Authorization: Basic Authentication, username: x, password: owner
21.6. 2.1.3 Body
The request body must be a JSON object with the following structure:
{
"method": "componentJsonApi",
"params": {
"componentId": "ctrlFastFreqReserve0",
"payload": {
"method": "setActivateFastFreqReserve",
"params": {
"id": "edge0",
"schedule": [
{
"startTimestamp": 1701871562,
"duration": 999,
"dischargePowerSetPoint": 6000,
"frequencyLimit": 502000,
"activationRunTime": "LONG_ACTIVATION_RUN",
"supportDuration": "LONG_SUPPORT_DURATION"
}
]
}
}
}
}
21.7. 2.1.4 Request Parameters
The request body for this REST API call is a JSON object with the following parameters:
-
method: The specific method to call within the component. In this case, it is
componentJsonApi
. -
params: The parameters associated with the method call.
-
componentId: The unique identifier of the component that is receiving the request.
-
payload: The specific data being sent to the component. See below
21.7.1. 2.1.5 Payload Parameters
Within the payload parameter, there is another JSON object that specifies the details of the activation request:
-
method: The method to call within the component to handle the activation request. In this case, it is
setActivateFastFreqReserve
. -
params: The parameters associated with the
setActivateFastFreqReserve
method. -
id: The unique identifier of the edge device for which the activation is being requested, locally is always
edge0
. -
schedule: An array of schedule items that define the activation pattern for the reserve.
21.7.2. 2.1.6 Schedule Item Parameters
Each schedule item within the schedule array specifies a specific activation period:
-
startTimestamp: The unix time stamp when the FFR should start activating.
-
duration: The duration in milliseconds for which the reserve should remain active.
-
dischargePowerSetPoint: The maximum power in kilowatts that the reserve should discharge during activation.
-
frequencyLimit: The frequency threshold below which the reserve should be activated.
-
activationRunTime: The time in milliseconds required for the reserve to fully activate.
-
supportDuration: The time in milliseconds for which the reserve should continue providing support after the frequency has stabilized.
21.7.3. 2.1.7 Example Python code
import requests
import json
from requests.auth import HTTPBasicAuth
# API URL
url = 'http://10.0.10.178:8084/jsonrpc'
# Authentication
auth = HTTPBasicAuth('x', 'owner')
# Request headers
headers = {
'Content-Type': 'application/json',
}
# Request payload
payload = {
'jsonrpc': '2.0',
'id': '00000000-0000-0000-0000-000000000000',
'method': 'componentJsonApi',
'params': {
'componentId': 'ctrlFastFreqReserve0',
'payload': {
'method': 'setActivateFastFreqReserve',
'params': {
'id': 'edge0',
'schedule': [
{
'startTimestamp': 1701871562,
'duration': 999,
'dischargePowerSetPoint': 6000,
'frequencyLimit': 502000,
'activationRunTime': 'LONG_ACTIVATION_RUN',
'supportDuration': 'LONG_SUPPORT_DURATION'
}
]
}
}
}
}
# Make the request
response = requests.post(url, auth=auth, headers=headers, json=payload)
# Print the response
print(response.json())
21.8. 3.1 REST API for Activating Fast Frequency Reserve controllers schedule using Backend
note : The controller/ App should be activated to update the schedule, which can be done using online monitoring or apache felix.
21.9. 3.1.1 Overview
This REST API allows you to update FFR for a specific edge device. The API endpoint takes a JSON payload that updates activation schedule, including the start time, duration, discharge power set point, frequency limit, activation runtime, and support duration.
21.10. 3.1.2 Endpoint
-
Method: POST
-
Content-Type: application/json
-
Authorization: Basic Authentication, username:foo.com, password:**
21.11. 3.1.3 Body
The request body must be a JSON object with the following structure:
{
"method": "edgeRpc",
"params": {
"edgeId": "fems3734",
"payload": {
"method": "componentJsonApi",
"params": {
"componentId": "ctrlFastFreqReserve0",
"payload": {
"method": "setActivateFastFreqReserve",
"params": {
"id": "edge3734",
"schedule": [
{
"startTimestamp": "1701767477",
"duration": "11000",
"dischargePowerSetPoint": "6000",
"frequencyLimit": "52000",
"activationRunTime": "LONG_ACTIVATION_RUN",
"supportDuration": "LONG_SUPPORT_DURATION"
}
]
}
}
}
}
}
}
21.12. 3.1.4 Request Parameters
-
method: The JSONRPC method to call. In this case, it is
edgeRpc
. -
params: The JSONRPC parameters.
-
edgeId: The ID of the edge device for which to activate the FFR.
-
payload: The JSONRPC payload.
21.13. 3.1.5 Payload Parameters
Within the payload parameter, there is another JSON object that specifies the details of the activation request:
-
method: The JSONRPC method to call within the component. In this case, it is
componentJsonApi
. -
params: The JSONRPC parameters for the
componentJsonApi
method. -
componentId: The ID of the component within which to call the method. In this case, it is
ctrlFastFreqReserve0
. -
payload: The JSONRPC payload for the method.
21.14. 3.1.6 Schedule Item Parameters
Each schedule item within the schedule array specifies a specific activation period:
-
startTimestamp: The unix time stamp in milliseconds when the FFR should start activating.
-
duration: The duration in milliseconds for which the reserve should remain active.
-
dischargePowerSetPoint: The maximum power in kilowatts that the reserve should discharge during activation.
-
frequencyLimit: The frequency threshold below which the reserve should be activated.
-
activationRunTime: The time in milliseconds required for the reserve to fully activate.
-
supportDuration: The time in milliseconds for which the reserve should continue providing support after the frequency has stabilized.
21.15. 3.1.7 Example Python code:
import requests
import json
from requests.auth import HTTPBasicAuth
import base64
import os
url = "https://fenecon.de/fems/rest/jsonrpc"
username = os.getenv("FENECON_USERNAME")
password = os.getenv("FENECON_PASSWORD")
headers = {
"Content-Type": "application/json",
"Authorization": "Basic " + base64.b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8")
}
body = {
"method": "edgeRpc",
"params": {
"edgeId": "fems3734",
"payload": {
"method": "componentJsonApi",
"params": {
"componentId": "ctrlFastFreqReserve0",
"payload": {
"method": "setActivateFastFreqReserve",
"params": {
"id": "edge3734",
"schedule": [
{
"startTimestamp": "1701767477",
"duration": "11000",
"dischargePowerSetPoint": "6000",
"frequencyLimit": "52000",
"activationRunTime": "LONG_ACTIVATION_RUN",
"supportDuration": "LONG_SUPPORT_DURATION"
}
]
}
}
}
}
}
}
response = requests.post(url, headers=headers, data=json.dumps(body))
if response.status_code == 200:
print("Fast Frequency Reserve activated successfully")
else:
print("Error activating Fast Frequency Reserve:", response.text)
22. Symmetric Fix Active Power
Sets a fixed active power for charging/discharging of a symmetric energy storage system.
23. ESS Fix State Of Charge
Sets active power constraints for charging/discharging of a symmetric energy storage system, to reach a final SoC under the constraints below.
-
State of Charge should be reached at a certain time or as fast as possible
-
State of Charge is held for a configured time or optionally until a specific end condition is fulfilled
24. ESS Grid Optimized Charge
Combination of the PredictiveDelayCharge and the SellToGridPowerLimit controllers:
Delays the charging of the AC or DC storage system based on predicted production and consumption given by the PredictorManager.
Even during the delayed charging, the battery is able to force charge when the sell-to-grid power exceeds the configured "Sell-To-Grid maximum power limit". This is mainly used when only 70 percent of the maximum production is allowed to feed in to the grid.
25. Hybrid-Ess Surplus-Feed-To-Grid Controller
Controls a Hybrid Battery Inverter (i.e. integrated Energy Storage System) so, that the surplus DC production of its chargers gets fed to grid.
26. ESS §14a EnWG Controller
Established by law (for Germany), this controller lowers active power to -4200 W
in response to grid operator limitations, aiming to alleviate load on transformers.
Link to legislative text: https://www.gesetze-im-internet.de/enwg_2005/__14a.html
27. ESS Limit Total Discharge
Limits the discharge power of an energy storage system according to its State-of-Charge, e.g. to keep energy for emergency power or to avoid deep discharge.
28. ESS Linear Power Band
Executes a test cycle for an energy storage system by increasing and decreasing the charging/discharging power in given limits.
29. ESS Minimum Discharge Period
Provides a minimum discharge power of the storage system for a configured time period, if a certain power peak has been reached.
This can be used in some systems where the allowed charge power has been set to zero and the storage needs a minimum discharge power for a certain time, to recognize that the storage is not full and the allowed charge power should be higher.
30. Ess Reactive Power Voltage Characteristic
-
This controller sets reactive power of an energy storage system in order to keep the grid voltage within an acceptable range.
-
The reactive power set-point depends on the ratio of the grid voltage divided by the configured
nominalVoltage
parameter. -
The reactive power set-point is defined as percent of the maximum apparent power of the inverter.
-
The reactive power per voltage ratio is defined by a poly-line graph in the
lineConfig
parameter. It takes a Json-Array of the following form:
[ { "voltageRatio":0.9, "percent":60 }, { "voltageRatio":0.93, "percent":0 }, { "voltageRatio":1.07 "percent":0 }, { "voltageRatio":1.1, "percent":-60 } ]
-
waitForHysteresis
parameter: reactive power set-point is not updated more often than the hysteresis time in seconds. Default value is 20 seconds. The purpose of this parameter is to avoid oscillation in grid voltage via frequently setting power.
31. ESS Sell-To-Grid Limit
Limits the maximum sell-to-grid power by actively charging the Ess. Can be used to apply a 70 % limit to the sell-to-grid power according to German law.
32. ESS Standby
Regularly checks the functionality of an ESS once per week while being in Standby mode.
- Use-Case
-
In projects with Hochlastzeitfenster (HLZF) the storage system might not be used for some weeks or months. In these periods it is required to make a regular check of the system and to calibrate the battery. This controller automates this function.
- Scheduling
-
The controller is supposed to be configured to run with less priority than "LimitTotalDischarge", "BatteryHandling",… and higher priority than "HLZF", "Balancing", "Peak-Shaving",…
33. ESS Time-of-Use Tariff
This Controller optimizes the performance of an energy storage system (ESS) in conjunction with a Time-Of-Use (ToU) Tariff provider.
The primary aim of the controller is to optimize the economic utilization of energy stored within the battery, primarily for self-consumption. To achieve this goal, the controller employs a rolling approach, where it continuously fetches predictions from the prediction service. It takes into account the current state of the battery’s capacity, recalculates its operations, and generates a detailed schedule for the Energy Storage System (ESS) for the upcoming 24-hour period, in 15-minute intervals.
This iterative and dynamic approach ensures that the ESS operates efficiently by staying synchronized with real-time forecasts and the evolving state of the battery, thereby maximizing cost-effectiveness and self-consumption of stored energy.
33.1. Schedule Calculation Modes
The schedule calculation process varies depending on the local market conditions. To accommodate this variability, two distinct modes have been introduced to facilitate flexible operation:
- CHARGE_CONSUMPTION
-
This mode is well-suited for markets that permit charging the battery from the grid. In this mode, the controller utilizes production and consumption forecasts along with day-ahead electricity prices to calculate the optimal time periods for charging the battery from the grid. This approach ensures efficient utilization of resources while taking advantage of cost-effective grid charging opportunities.
- DELAY_DISCHARGE
-
This mode is tailored for markets where grid charging is restricted or discouraged. In such scenarios, optimal time periods are determined based on forecasts and day-ahead pricing information. The controller then schedules the Energy Storage System (ESS) to limit or delay discharging during these specific periods. This strategic approach aims to optimize economic performance by avoiding costly grid interactions when grid charging is not feasible or economical.
These two operation modes provide the necessary flexibility to adapt to varying market conditions, allowing for efficient energy management and cost savings based on the specific requirements of your local energy market.
34. EVCS
Controls an Electric Vehicle Charging Station (EVCS) in different modes, like "Force-Charge" and "Surplus Energy Charging".
35. EVCS Fix Active Power
Sets a fixed maximum charge power to an Electric Vehicle Charging Station (EVCS).
36. Generic JsonLogic
The JsonLogic-Controller is a very generic Controller that allows the definition of a complex logic as a configuration at runtime, e.g. via Apache Felix Web Console.
It is based on the JsonLogic specification (jsonlogic.com). Logics can be defined by a rule:
{
"if":[
{
"<":[
{
"var":"_sum/EssSoc"
},
50
]
},
[
[
"ess0/SetActivePowerEquals",
5000
]
],
[
[
"ess0/SetActivePowerEquals",
-2000
]
]
]
}
The input data that is referenced via var
is automatically provided from OpenEMS Channels - e.g. as
{
"_sum/EssSoc": 40
}
This example would result in:
[
"ess0/SetActivePowerEquals",
5000
]
i.e. the Controller will require a set-point of 5000 W discharge on ess0.
It is also possible to write to multiple channels, by adding more arrays to the result.
Try yourself: http://jsonlogic.com/play.html
37. High-Load Timeslot
Controls an energy storage system for a High-Load timeslot application (German "Hochlastzeitfenster").
38. IO Alarm
Switches a digital output, when one or more State-Channels are set. This controller can be used to signal alarms. This controller is used to check for the State-Channels which are boolean type, which typically represents the error channels. A specific configured digital output channel can be signaled based on the configured input State-Channels(one more channels).
38.1. Configuration
-
Component-ID
Unique ID of this Component (id), e.g. "ctrlIoAlarm0", "ctrlIoAlarm1" -
Alias
Human-readable name of this Component; defaults to Component-ID (alias) -
Input Channels
Addresses of the input State-Channels (inputChannelAddress), This is a array of input state channels. -
Output Channel
Channel address of the Digital Output that should be switched (outputChannelAddress)
Multiple instances can be created in "Apache felix" during the configuration for each Output channel signal.
38.2. Example Configuration
-
Component-ID
: ctrlIoAlarm0 -
Alias
: myIoAlarm -
Input Channels
: [ess0/State15, ess0/State33, ess0/State43] -
Output Channel
: io0/Relay1
ess0/State15 - represents the State15 channels of the ESS0, io0/relay1 = represents the relay 1 of the KM tronic relay board. |
The above example configuration describes, if any of the configured three input channels is set to "True" then a signal "True" is sent to output channel, else the "False" signal is sent to output channel.
39. IO Analog Controller
Controller that sets a analog output according to the configured inputs to OFF|AUTOMATIC|ON.
In AUTOMATIC mode the output is set dynamically depending on the current surplus power.
40. IO Channel-Single-Threshold
Generic Controller that sets a digital output according to the value of given Channel - e.g. turn a Relay on or off, when configured input channel/SoC is above or below a given threshold respectively.
42. IO Heating Element
Controls a three-phase heating element via Relays, according to grid active power.
42.1. Phase and Level
The Controller distinguishes the definition of Phase and Level. Phase represents the electrical phase L1, L2 or L3. Level represents how many Phases are active at one point in time:
-
Level 1: only Phase L1 is active
-
Level 2: Phase L1 and L2 are active
-
Level 3: all three Phases are active
42.2. Channels
Example: * the power of the heating element per phase is 1000 W * each "x" below represents one hour
Assume the Controller was activating Phases L1, L2 and L3 during the day like this:
L3| xxx L2| xxxxxxxxx L1| xxxxxxxxxxxxxxxx t|------------------------
- Channel Phase1Time
-
= 16 h = 57600 sec
|--------------|
- Channel Phase2Time
-
= 9 hours = 32400 sec
|-------|
- Channel Phase3Time
-
= 3 hours = 10800 sec
|-|
- Channel Level1Time
-
= Phase1Time - Phase2Time = 7 hours = 25200 sec
|-| |--|
- Channel Level2Time
-
= Phase2Time - Phase3Time = 6 hours = 21600 sec
|-| |-|
- Channel Level3Time
-
= Phase3Time = 3 hours = 10800 sec
|-|
- Channel TotalTime
-
28000 Wh = 28 kWh
- Channel TotalPhaseTime
-
= Phase1Time + Phase2Time + Phase3Time = 16 + 9 + 3 = 28 h = 100800 sec
43. IO SG-Ready Heat Pump
Controls a heat pump that implements the SG-Ready standard via two Relay contacts, depending on surplus power and battery state-of-charge.
43.1. States
The Controller distinguishes the different States, according to the SG-Ready standard.
Name | Description |
---|---|
Lock State |
The lock state blocks everything till an internal maximum time of (default) two hours |
Regular State |
The heat pump runs in energy-efficient standard operation |
Recommendation State |
State: The heat pump runs in a more sufficient mode for space heating and hot water production, to use available surplus power |
Force-On State |
The heat pump runs in a definitive start/heat-up mode. Depending on the heat pump, heating is forced and additional heaters may be switched on |
43.2. Channels
The Controller has an ongoing time counter for every state, that is started and stopped if the corresponding state is active or not.
Minimum switching time: As an additional preventative, the controller has a minimum switching time. If a state changed, it will wait for this time (default 60 seconds) till the next state can be set.
45. PV-Inverter Sell-To-Grid limit
Dynamically limits the Sell-To-Grid power of a PV-Inverter to a defined maximum power.
If the configured mode is asymmetric, the controller evaluates the grid meter phase with the highest Sell-To-Grid power and curbs the PV-power of the configured PV-Inverter. The main purpose of the asymmetric mode is, to prevent the grid fuse from overcurrent.
46. Symmetric Balancing Schedule
Controls a symmetric energy storage system in balancing mode. The control algorithm charges or discharges the battery in order to reach a given power target set-point at the grid connection point. If the target set-point is defined as zero, the behaviour is like with self-consumption optimization.
This controller allows two ways of controlling the power target set-point:
46.1. 1. Definition of a power target set-point Schedule
The static configuration parameter "schedule" takes a Schedule of set-points as a Json-Array. An example schedule looks like this:
[
{
"startTimestamp": 1577836800,
"duration": 900,
"activePowerSetPoint": 0
}, {
"startTimestamp": 1577837700,
"duration": 900,
"activePowerSetPoint": -2000
}
]
This schedule will activate a power target set-point of zero starting at the epoch time 1577836800 (i.e. seconds since 1st January 2020 00:00:00 in timezone UTC), that lasts for 900 seconds (i.e. 15 minutes). Afterwards - from 1577837700 - for another 900 seconds a set-point of -2000 W (i.e. feeding 2000 W to the grid) is targeted. After the second period passes, no more charging or discharging commands are set on the battery.
The schedule configuration parameter may be updated
-
via a browser using the OpenEMS user interface
-
using the
SetGridConnSchedule
JSON-RPC Request via OpenEMS Backend -
using a direct SetGridConnScheduleRequest via JsonApi
-
or using the
UpdateComponentConfigRequest
JSON-RPC Request
Be aware that an UpdateComponentConfigRequest
will always result in a actual configuration file being updated by Apache Felix Configuration Admin, so this command should not be used too frequently, e.g. only once per day. The SetGridConnScheduleRequest
variant runs only in memory and is not persisted. Downside is, that if OpenEMS Edge gets restarted, the schedule is lost.
46.2. 2. Immediate control of the power target set-point
The power target set-point may also be controlled directly via the GridActivePowerSetPoint
channel. E.g. if the controller component has the Id ctrlBalancingSchedule0
one can use e.g. the REST-Api Controller and write
{
"value": 5000
}
to the channel ctrlBalancingSchedule0/GridActivePowerSetPoint
(e.g. ` http://x:user@localhost:8084/rest/channel/ctrlBalancingSchedule0/GridActivePowerSetPoint`), to set a temporary power target set-point of 5000.
48. Symmetric Limit Active Power
Limits the allowed active power for charging and discharging of a symmetric energy storage system.
49. Symmetric Peak-Shaving
Applies peak-shaving at the grid using a symmetric energy storage system.
50. Symmetric Random-Power
Applies random charging/discharging of a symmetric energy storage system for performance tests.