SOH Cycle Controller
This controller runs a defined State-of-Health (SOH) test cycle on an ESS (battery storage system). It executes an optional reference cycle and a measurement cycle, then evaluates the result to determine the SOH of the ESS.
The purpose of this README is to store useful technical information about the controller logic and states. This information is primarily needed for developers (e.g., to answer questions from product management).
Configuration
The following configuration parameters are available:
-
id
Component-ID – Unique ID of this component (default:ctrlEssSohCycle0) -
ess_id
ID of the ESS device to monitor (e.g.,ess0) -
alias
Human-readable name of this component; defaults to Component-ID -
enabled
Whether this component is enabled (default:true) -
mode
Operating mode – SelectMANUAL_ONto activate the cycle logic;MANUAL_OFFdisables the cycle (default:MANUAL_OFF) -
logVerbosity
Sets the logging verbosity level (default:NONE)-
NONE: No logs -
DEBUG_LOG: Detailed logging to Controller.Debug.Log
-
-
referenceCycleEnabled
Enables the optional reference cycle measurement (default:false)-
If
false: cycle skips directly to the measurement cycle -
If
true: full cycle with reference measurements included
-
Monitoring
Typical channels can be followed from Grafana or online monitoring (names may differ depending on configuration).
Core state and results
-
ctrlEssSohCycle0/StateMachine
Current state of the SOH state machine:
IDLE,PREPARE,REFERENCE_CYCLE_CHARGING,REFERENCE_CYCLE_CHARGING_WAIT,
REFERENCE_CYCLE_DISCHARGING,REFERENCE_CYCLE_DISCHARGING_WAIT,
MEASUREMENT_CYCLE_CHARGING,MEASUREMENT_CYCLE_CHARGING_WAIT,CHECK_BALANCING,
MEASUREMENT_CYCLE_DISCHARGING,MEASUREMENT_CYCLE_DISCHARGING_WAIT,
EVALUATE_RESULT,DONE,ERROR_ABORT. -
ctrlEssSohCycle0/SohPercent
Calculated SOH result of the last completed cycle in percent (0–100). -
ctrlEssSohCycle0/SohRawDebug
Raw calculated SOH value without clamping to 100. May exceed 100 and is intended for debugging. -
ctrlEssSohCycle0/MeasuredCapacity
Last measured capacity of the ESS in Watt-hours (Wh).
Battery balancing status and diagnostics
-
ctrlEssSohCycle0/IsBatteryBalanced
Indicates whether the battery cells are sufficiently balanced.
Values:NOT_MEASURED,BALANCED,NOT_BALANCED,ERROR. -
ctrlEssSohCycle0/BalancingDeltaMvDebug
Cell voltage delta (max − min) in millivolts. Persisted for debugging long-running cycles.
nullif delta cannot be calculated. -
ctrlEssSohCycle0/BalancingReason
Explains why the balance check results inNOT_MEASUREDorNOT_BALANCED.
Typical values:
NONE,BASELINE_MIN_MISSING,MAX_VOLTAGE_UNDEFINED,MIN_VOLTAGE_UNDEFINED,
DELTA_NEGATIVE,DELTA_ABOVE_THRESHOLD,TIMEOUT,INTERNAL_ERROR.
Note: exact enum values depend on the controller version.
Algorithm logic
The SOH Cycle Controller is implemented as a state machine with the following phases:
1) Idle & preparation
-
IDLE– Waits for activation viaMANUAL_ONmode. -
PREPARE– Prepares the ESS by discharging to minimum SOC (0%).
2) Reference cycle (optional)
-
REFERENCE_CYCLE_CHARGING– Charges the battery to maximum SOC (100%) at 0.2C rate. -
REFERENCE_CYCLE_CHARGING_WAIT– Waits for voltage stabilization. -
REFERENCE_CYCLE_DISCHARGING– Discharges the battery to minimum SOC (0%) at 0.2C rate. -
REFERENCE_CYCLE_DISCHARGING_WAIT– Waits for voltage stabilization.
3) Measurement cycle (always executed)
-
MEASUREMENT_CYCLE_CHARGING– Charges the battery to maximum SOC (100%) at 0.2C rate.
During this phase the controller continuously collects cell voltage range data for balancing diagnostics. -
MEASUREMENT_CYCLE_CHARGING_WAIT– Waits for voltage stabilization. -
CHECK_BALANCING– Evaluates battery cell balancing status using the measured cell voltage delta.
Sets:-
IsBatteryBalanced -
BalancingDeltaMvDebug -
BalancingReasonThreshold: 100 mV.
-
-
MEASUREMENT_CYCLE_DISCHARGING– Discharges the battery to minimum SOC (0%) at 0.2C rate while measuring energy for capacity calculation. -
MEASUREMENT_CYCLE_DISCHARGING_WAIT– Waits for voltage stabilization.
Battery balancing check: how voltage delta is measured
What is measured?
The balancing check uses the cell voltage delta:
delta_mV = maxCellVoltage_mV - minCellVoltage_mV
The value is written to BalancingDeltaMvDebug and used to determine
IsBatteryBalanced.
How are min and max voltages captured?
During the measurement charging phase and again at
CHECK_BALANCING, the controller calls:
refreshMeasurementChargingVoltageRange()
This method reads:
-
ess.getMinCellVoltage() -
ess.getMaxCellVoltage()
and stores them internally.
Important: min and max may be captured at different times
Min and max voltages are updated independently:
The stored minimum voltage is actually the highest observed minimum during charging:
if (stored == null || current > stored) {
stored = current;
}
The stored maximum voltage is the highest observed maximum:
if (stored == null || current > stored) {
stored = current;
}
As a result, the voltage delta may combine values measured at different points in time. It represents a range envelope observed during charging, not necessarily an instantaneous snapshot.
Implications
-
The delta is a diagnostic indicator of imbalance.
-
It may be slightly conservative, but helps answer:
-
“Did a large spread occur during charging?”
-
“Is the spread still significant near the end of charging?”
-
If an instantaneous delta at a single timestamp is required, min and max would need to be sampled together and evaluated immediately.
CHECK_BALANCING behavior and diagnostics
In CHECK_BALANCING, the controller: 1. Refreshes voltage range
data 3. Calculates voltage delta and diagnostic reason 5. Sets: *
BalancingDeltaMvDebug * BalancingReason * IsBatteryBalanced 13.
Continues the cycle even if the battery is not balanced
Diagnostics are persisted as channels, enabling root-cause analysis without relying on logs.