Skip to content

Commit 8ab4d7e

Browse files
authored
[Edge] Refactor AC-in setpoint calculation (OpenEMS#3584)
This PR refactors the AC-in setpoint calculation logic in VictronEssImpl.java to improve code maintainability and readability. It introduces a new method, calculateAcInSetpoint, which encapsulates the logic for clamping the battery power to hardware limits and adjusting for AC-out load. This change simplifies the main logic flow by abstracting the detailed calculation steps into a separate, well-documented method. Additionally, it fixes potential issues with the previous implementation by ensuring that the hardware limits are applied before adjusting for AC-out load, which prevents the hardware constraints from being bypassed. The accompanying tests in VictronEssImplTest.java have been updated to cover various scenarios, ensuring the new method behaves as expected. fixes OpenEMS#3573
1 parent 8378b74 commit 8ab4d7e

2 files changed

Lines changed: 81 additions & 16 deletions

File tree

io.openems.edge.victron/src/io/openems/edge/victron/ess/VictronEssImpl.java

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -513,23 +513,10 @@ public void applyPower(int activePowerTarget, int reactivePower) throws OpenemsN
513513
}
514514
}
515515

516-
if (activePowerTarget < 0) {
517-
// CHARGE: AC-Out draws power from battery, subtract from target
518-
activePowerTarget -= acOutputActivePowerSum;
519-
this.logDebug(this.log, "Symm. PowerWanted ChargeMode after subtraction of AC Out: "
520-
+ acOutputActivePowerSum + " -> " + activePowerTarget);
521-
} else if (activePowerTarget > 0) {
522-
this.logDebug(this.log, "Symm. PowerWanted DischargeMode Target -> " + activePowerTarget);
523-
}
516+
activePowerTarget = calculateAcInSetpoint(activePowerTarget, acOutputActivePowerSum, this.maxChargePower,
517+
this.maxDischargePower);
524518

525-
// Clamp power to hardware limits
526-
527-
if (activePowerTarget < 0 && Math.abs(activePowerTarget) > this.maxChargePower) {
528-
activePowerTarget = this.maxChargePower * -1;
529-
}
530-
if (activePowerTarget > 0 && activePowerTarget > this.maxDischargePower) {
531-
activePowerTarget = this.maxDischargePower;
532-
}
519+
this.logDebug(this.log, "Symm. PowerWanted after clamp and AC-Out adjustment: " + activePowerTarget);
533520

534521
this._setAllowedChargePower(this.maxChargePower * -1); // Negative for charging
535522
this._setAllowedDischargePower(this.maxDischargePower); // Positive for discharging
@@ -574,6 +561,40 @@ public Power getPower() {
574561
return this.power;
575562
}
576563

564+
/**
565+
* Calculates the AC-in setpoint by first clamping the battery power to hardware
566+
* limits, then adjusting for AC-out load.
567+
*
568+
* <p>
569+
* Clamping is applied before the AC-out adjustment so that the hardware limits
570+
* constrain the battery charge/discharge power, not the total AC-in power which
571+
* must also cover AC-out loads.
572+
*
573+
* @param activePowerTarget the requested battery power (negative=charge,
574+
* positive=discharge)
575+
* @param acOutputActivePowerSum the total AC-out load (always positive)
576+
* @param maxChargePower the maximum charge power (positive value)
577+
* @param maxDischargePower the maximum discharge power (positive value)
578+
* @return the adjusted AC-in setpoint
579+
*/
580+
protected static int calculateAcInSetpoint(int activePowerTarget, int acOutputActivePowerSum, int maxChargePower,
581+
int maxDischargePower) {
582+
// Clamp power to hardware limits before AC-Out adjustment
583+
if (activePowerTarget < 0 && Math.abs(activePowerTarget) > maxChargePower) {
584+
activePowerTarget = maxChargePower * -1;
585+
}
586+
if (activePowerTarget > 0 && activePowerTarget > maxDischargePower) {
587+
activePowerTarget = maxDischargePower;
588+
}
589+
590+
// CHARGE: AC-Out draws power from battery, subtract from target
591+
if (activePowerTarget < 0) {
592+
activePowerTarget -= acOutputActivePowerSum;
593+
}
594+
595+
return activePowerTarget;
596+
}
597+
577598
/**
578599
* Calculates apparent power sum from millivolt and milliampere values.
579600
*

io.openems.edge.victron/test/io/openems/edge/victron/ess/VictronEssImplTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,48 @@ public void testGetPowerPrecision() {
111111
assertEquals(100, victronEss.getPowerPrecision());
112112
}
113113

114+
@Test
115+
public void testCalculateAcInSetpoint_chargeWithAcOutLoad() {
116+
// Issue #3573: Charge request of 3kW with 5kW AC-out load
117+
// Battery should charge at 3kW, so AC-in must be 8kW
118+
var result = VictronEssImpl.calculateAcInSetpoint(-3000, 5000, 3000, 3000);
119+
assertEquals(-8000, result);
120+
}
121+
122+
@Test
123+
public void testCalculateAcInSetpoint_chargeExceedsMaxWithAcOut() {
124+
// Charge request of 5kW exceeds maxChargePower of 3kW, with 2kW AC-out
125+
// Should clamp to -3kW charge, then subtract 2kW AC-out => -5kW
126+
var result = VictronEssImpl.calculateAcInSetpoint(-5000, 2000, 3000, 3000);
127+
assertEquals(-5000, result);
128+
}
129+
130+
@Test
131+
public void testCalculateAcInSetpoint_chargeWithinLimitsNoAcOut() {
132+
// Charge request of 2kW, no AC-out, maxCharge 3kW
133+
var result = VictronEssImpl.calculateAcInSetpoint(-2000, 0, 3000, 3000);
134+
assertEquals(-2000, result);
135+
}
136+
137+
@Test
138+
public void testCalculateAcInSetpoint_dischargeWithinLimits() {
139+
// Discharge request of 2kW, maxDischarge 3kW
140+
var result = VictronEssImpl.calculateAcInSetpoint(2000, 1000, 3000, 3000);
141+
assertEquals(2000, result);
142+
}
143+
144+
@Test
145+
public void testCalculateAcInSetpoint_dischargeExceedsMax() {
146+
// Discharge request of 5kW, maxDischarge 3kW => clamped to 3kW
147+
var result = VictronEssImpl.calculateAcInSetpoint(5000, 0, 3000, 3000);
148+
assertEquals(3000, result);
149+
}
150+
151+
@Test
152+
public void testCalculateAcInSetpoint_zeroPower() {
153+
// Zero power target, should remain zero
154+
var result = VictronEssImpl.calculateAcInSetpoint(0, 5000, 3000, 3000);
155+
assertEquals(0, result);
156+
}
157+
114158
}

0 commit comments

Comments
 (0)