Skip to content

Detailed Technical Understanding of OpenEMS Edge

1. Project Overview

OpenEMS Edge is the software stack designed to run on a local energy management controller. It is built on Java and OSGi (Open Services Gateway initiative), providing a modular, dynamic, and robust environment for managing energy storage systems, photovoltaic plants, electric vehicle chargers, and other energy hardware.

2. Core Architecture & Concepts

The architecture is centered around a unified data model and a synchronous execution cycle.

2.1. OSGi & Modularity

OpenEMS uses OSGi to manage Components. Each driver (e.g., for a specific generic ESS) or controller is an OSGi Bundle. - Service-Oriented: Components register as OSGi Services (e.g., ManagedSymmetricEss, Controller). - Dynamic: Components can be started, stopped, or updated at runtime without restarting the entire system. - Configuration: The standard OSGi Configuration Admin is used to configure components (e.g., IP addresses, Modbus IDs).

2.2. The Data Model: Natures, Components, and Channels

  • Nature: A Java Interface defining a set of standard capabilities. For example, SymmetricEss is a Nature that guarantees the existence of a Soc (State of Charge) channel.
  • Component: A concrete instance (Java Class) that implements one or more Natures.
  • Channel: The atomic unit of data. Every point of data in OpenEMS is a Channel.
    • ReadChannel: Represents "Inputs" (e.g., Measured Power, SoC).
    • WriteChannel: Represents "Outputs" or "Setpoints" (e.g., Set Active Power).
    • StateChannel: Represents boolean states, often faults or warnings.

2.3. The Process Image

OpenEMS operates on a synchronized Process Image to avoid race conditions and ensure data consistency during a control cycle. * NextValue: Controllers and Drivers write to the "NextValue" buffer during a Cycle. * Value (Current): At the beginning of a Cycle, the "NextValue" is promoted to the current "Value". All Controllers reading data in step N see the same stable snapshot of data from step N-1.

3. The Execution Cycle (Heartbeat)

The core logic is driven by the Cycle Worker, typically running once per second.

sequenceDiagram
    participant Timer
    participant Cycle
    participant Channels
    participant Scheduler
    participant Controllers
    participant Hardware

    Timer->>Cycle: Tick (1s)

    rect rgb(240, 248, 255)
    Note over Cycle, Channels: Phase 1: Process Image Switch
    Cycle->>Channels: nextProcessImage()
    Note right of Channels: NextValue becomes CurrentValue
    end

    rect rgb(255, 250, 240)
    Note over Cycle, Controllers: Phase 2: Control Logic
    Cycle->>Scheduler: Execute Schedulers
    loop For each Controller
        Scheduler->>Controllers: run()
        Controllers->>Channels: Read Inputs (Sensors)
        Controllers->>Channels: Write Next Setpoints
    end
    end

    rect rgb(240, 255, 240)
    Note over Cycle, Hardware: Phase 3: Execute Writes
    Cycle->>Hardware: Trigger Write to External Devices
    end

4. Automation Logic: Controllers in Detail

OpenEMS follows a modular controller concept. A controller is a logic block that reads component data and calculates new setpoints.

4.1. Scheduler

The Scheduler determines the execution order. This is critical because multiple controllers might try to influence the same hardware. * Prioritization: Typical priority: High Priority (Emergency) > Balancing > Optimization > Low Priority. * Constraint Solving: Controllers can add Constraints (e.g., "Power must be <= 2000 W"). A central solver then finds the optimal value satisfying all constraints.

4.2. Functional Implementation Logic

I. ESS Controllers (Energy Storage)

1. Symmetric Balancing Controller (Self-Consumption) * Objective: Minimize Grid Exchange (Target: 0 W). * Logic: 1. Read GridActivePower (Meter) and EssActivePower (ESS). 2. Calculate RequiredPower = GridActivePower + EssActivePower - TargetSetpoint. 3. Apply PID Filter to smooth the request. 4. Write result to the ESS SetActivePowerEquals channel.

2. Peak Shaving Controller * Objective: Prevent grid consumption from exceeding a limit (e.g., 20 kW). * Logic: 1. Read GridActivePower. 2. If GridActivePower > PeakShavingLimit: * Calculate Delta = GridActivePower - PeakShavingLimit. * Discharge Battery by Delta. 3. Else, if GridActivePower < RechargePower: * Charge Battery slowly to prepare for next peak.

3. Limit Total Discharge (Deep Discharge Protection) * Objective: Protect Battery health. * Logic: Uses a State Machine. * Normal: SoC > MinSoC. No action. * MinSoC: SoC <= MinSoC. Set Constraint SetActivePowerLessOrEquals(0) (Block Discharge). * ForceCharge: SoC <= ForceChargeSoC. Enforce Charging Power (e.g., -2000 W).

4. Emergency Capacity Reserve * Objective: Reserve specific capacity (e.g., 20%) for backup power. * Logic: * If Soc <= ReserveSoc, set Constraint SetActivePowerLessOrEquals(0). * This stops "economic" discharging (like Balancing), saving the energy for physical backup hardware (Emergency Power Switch).

5. Time of Use Tariff * Objective: Arbitrage (Buy Low, Sell High). * Logic: Calculates a schedule based on electricity prices. * ChargeGrid: Force charge during price valleys. * DelayDischarge: Prevent discharge during medium prices to save capacity for high price peaks.

II. EVCS Controllers (Electric Vehicle Charging)

1. EVCS Smart Charging * Objective: Charge EV with excess PV power. * Logic: The controller has two priority modes: * Priority: Car: Charge as fast as possible (or using all excess, ignoring battery). * Priority: Storage: Fill the home battery first, then charge the car. * Calculation: * ExcessPower = PV_Production - House_Load. * The controller continuously adjusts the ChargePowerLimit of the EVCS to match ExcessPower. * Hysteresis: Applied to prevent toggling charging on/off too rapidly during passing clouds.

III. PV Inverter Controllers

1. Fix Power Limit (Curtailment) * Objective: Limit PV production (e.g., due to grid operator request). * Logic: * Write a fixed percentage or Watt value to the Inverter's ActivePowerLimit channel.

2. Sell-To-Grid Limit * Objective: Limit the power fed into the public grid (e.g., "70% Rule" or "Zero Export"). * Logic: 1. Read GridActivePower (Meter) and PvActivePower. 2. Calculate Allowed PV Power: MaxPv = PvActivePower + GridActivePower + ConfiguredLimit (Note: GridActivePower is negative when selling). 3. Write MaxPv to the Inverter's ActivePowerLimit.

IV. IO Controllers (Inputs/Outputs)

1. Channel Single Threshold * Objective: Switch a Relay (Digital Output) based on a data value (e.g., Turn on Heater if Excess Power > 2000 W). * Logic: * Read Input Channel (e.g., GridActivePower). * Hysteresis: Wait for MinimumSwitchingTime. * If Value > Threshold: Set Output = ON. * If Value <= Threshold: Set Output = OFF.

V. Meter Controllers?

  • Clarification: In OpenEMS, "Meters" are typically Components that provide data, not Controllers that execute logic.
  • However, logic related to meters (like "Sell-To-Grid Limit") is handled by the controllers described above, which take the Meter data as a primary input variable.

5. Key Interface: ManagedSymmetricEss

Any Energy Storage System in OpenEMS implements this interface. Key Channels include:

Measurements & State (Read-Only)

Inherited from SymmetricEss.

Channel Name Unit Description
Soc % State of Charge (0-100)
ActivePower W Current Output (+ Discharge, - Charge)
ReactivePower var Current Reactive Power
Capacity Wh Total utilization capacity
MaxApparentPower VA Maximum apparent power limit
GridMode - 1=On-Grid, 2=Off-Grid
ActiveChargeEnergy Wh Total Energy Charged (Counter)
ActiveDischargeEnergy Wh Total Energy Discharged (Counter)
MinCellVoltage mV Minimum Cell Voltage in the pack
MaxCellVoltage mV Maximum Cell Voltage in the pack
MinCellTemperature °C Minimum Cell Temperature
MaxCellTemperature °C Maximum Cell Temperature

Control & Setpoints (Write)

Defined in ManagedSymmetricEss. These are the targets written by Controllers.

Channel Name Access Unit Description
AllowedChargePower Read W Max power the battery can currently accept (negative value, e.g. -5000)
AllowedDischargePower Read W Max power the battery can currently deliver (positive value, e.g. 5000)
SetActivePowerEquals Write W Target Setpoint: The main target power requested by a controller.
SetActivePowerEqualsWithPid Write W Target setpoint that passes through a PID filter before being applied.
SetActivePowerLessOrEquals Write W Constraint: "Do not be more positive than X" (limits Discharge).
SetActivePowerGreaterOrEquals Write W Constraint: "Do not be more negative than X" (limits Charge).
SetReactivePowerEquals Write var Target Reactive Power.
SetReactivePowerLessOrEquals Write var Reactive Power Constraint.
SetReactivePowerGreaterOrEquals Write var Reactive Power Constraint.
ApplyPowerFailed Read Bool True if the system failed to apply the requested power.