Skip to content

Commit

Permalink
Multi-inverter fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
springfall2008 authored Dec 29, 2024
1 parent 98caca0 commit 139156a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 13 deletions.
18 changes: 10 additions & 8 deletions apps/predbat/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ def execute_plan(self):
inverter.adjust_discharge_rate(0)
resetDischarge = False

target_soc = max(self.charge_limit_percent_best[0] if self.charge_limit_percent_best[0] != self.reserve else self.soc_percent, self.reserve, self.best_soc_min)
can_freeze_charge = True

# Can only freeze charge if all inverters have an SOC above the reserve
for check in self.inverters:
if check.soc_kw < inverter.reserve:
Expand Down Expand Up @@ -164,19 +166,19 @@ def execute_plan(self):
else:
# We can only hold charge if a) we have a way to hold the charge level on the reserve or with a pause feature
# and the current charge level is above the target for all inverters
can_hold_charge = True
can_hold_charge = self.charge_limit_percent_best[0] != self.reserve
for check in self.inverters:
if check.soc_percent < self.charge_limit_percent_best[0]:
if check.soc_percent < target_soc:
can_hold_charge = False
break
if not check.inv_has_timed_pause and (check.reserve_max < check.soc_percent):
can_hold_charge = False
break
if self.set_soc_enable and can_hold_charge and self.soc_percent >= self.charge_limit_percent_best[0]:
if self.set_soc_enable and can_hold_charge and self.soc_percent >= target_soc:
status = "Hold charging"
self.log("Hold charging as soc {}% is above target {}% set_discharge_during_charge {}".format(inverter.soc_percent, self.charge_limit_percent_best[0], self.set_discharge_during_charge))
self.log("Inverter {} Hold charging as soc {}% is above target {}% ({}%) set_discharge_during_charge {}".format(inverter.id, inverter.soc_percent, self.charge_limit_percent_best[0], target_soc, self.set_discharge_during_charge))

if (self.charge_limit_percent_best[0] < 100.0) and (abs(inverter.soc_percent - self.charge_limit_percent_best[0]) <= 1.0):
if (self.charge_limit_percent_best[0] < 100.0) and (abs(self.soc_percent - self.charge_limit_percent_best[0]) <= 1.0):
# If we are within 1% of the target but not at 100% then we can hold charge
# otherwise keep charging enabled
if self.set_soc_enable and ((self.set_reserve_enable and self.set_reserve_hold and inverter.reserve_max >= inverter.soc_percent) or inverter.inv_has_timed_pause):
Expand All @@ -197,13 +199,13 @@ def execute_plan(self):
else:
inverter.adjust_charge_window(charge_start_time, charge_end_time, self.minutes_now)

inverter.adjust_charge_immediate(self.charge_limit_percent_best[0], freeze=True)
inverter.adjust_charge_immediate(target_soc, freeze=True)
else:
status = "Charging"
inverter.adjust_charge_window(charge_start_time, charge_end_time, self.minutes_now)
inverter.adjust_charge_immediate(self.charge_limit_percent_best[0])
inverter.adjust_charge_immediate(target_soc)

status_extra = " target {}%-{}%".format(inverter.soc_percent, self.charge_limit_percent_best[0])
status_extra = " target {}%-{}%".format(inverter.soc_percent, target_soc)

if not self.set_discharge_during_charge and resetPause:
# Do we discharge discharge during charge
Expand Down
65 changes: 60 additions & 5 deletions apps/predbat/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1688,10 +1688,6 @@ def run_execute_test(
):
print("Run scenario {}".format(name))
failed = False
my_predbat.soc_kw = soc_kw
my_predbat.soc_max = soc_max
my_predbat.reserve = reserve
my_predbat.soc_percent = calc_percent_limit(soc_kw, my_predbat.soc_max)
my_predbat.set_read_only = read_only
my_predbat.car_charging_slots = [car_slot]
my_predbat.num_cars = 1
Expand Down Expand Up @@ -2174,6 +2170,64 @@ def run_execute_tests(my_predbat):
if failed:
return failed

failed |= run_execute_test(
my_predbat,
"charge_imbalance3",
charge_window_best=charge_window_best,
charge_limit_best=charge_limit_best2,
assert_charge_time_enable=True,
set_charge_window=True,
set_export_window=True,
assert_status="Charging",
assert_charge_start_time_minutes=-1,
assert_charge_end_time_minutes=my_predbat.minutes_now + 60,
soc_kw=5,
soc_kw_array=[2.0, 3.0],
assert_soc_target_array=[40, 60],
assert_immediate_soc_target=50,
)
if failed:
return failed

failed |= run_execute_test(
my_predbat,
"charge_imbalance4",
charge_window_best=charge_window_best,
charge_limit_best=charge_limit_best2,
assert_charge_time_enable=True,
set_charge_window=True,
set_export_window=True,
assert_status="Hold charging",
assert_charge_start_time_minutes=-1,
assert_charge_end_time_minutes=my_predbat.minutes_now + 60,
soc_kw=6,
soc_kw_array=[3.0, 3.0],
assert_soc_target_array=[50, 50],
assert_immediate_soc_target=50,
)
if failed:
return failed

failed |= run_execute_test(
my_predbat,
"charge_imbalance5",
charge_window_best=charge_window_best,
charge_limit_best=charge_limit_best2,
assert_charge_time_enable=True,
set_charge_window=True,
set_export_window=True,
assert_status="Hold charging",
assert_charge_start_time_minutes=-1,
assert_charge_end_time_minutes=my_predbat.minutes_now + 60,
soc_kw=7,
soc_kw_array=[3.0, 4.0],
assert_soc_target_array=[40, 60],
assert_immediate_soc_target=50,
)
if failed:
return failed


failed |= run_execute_test(
my_predbat,
"charge_low_power1",
Expand Down Expand Up @@ -2583,9 +2637,10 @@ def run_execute_tests(my_predbat):
assert_immediate_soc_target=50,
reserve_max=90,
has_timed_pause=False,
soc_kw_array=[5, 4],
soc_kw_array=[5, 4]
)


# Charge/discharge with rate
for inverter in my_predbat.inverters:
inverter.inv_charge_discharge_with_rate = True
Expand Down

0 comments on commit 139156a

Please sign in to comment.