Skip to content

Commit

Permalink
Low power mode fixes, new margin control for low power mode (#1677)
Browse files Browse the repository at this point in the history
* Low power mode fixes, new margin control for low power mode

* [pre-commit.ci lite] apply automatic fixes

---------

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
  • Loading branch information
springfall2008 and pre-commit-ci-lite[bot] authored Dec 1, 2024
1 parent 2e68a9d commit 9e5c0e4
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 9 deletions.
12 changes: 12 additions & 0 deletions apps/predbat/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,18 @@
"default": False,
"reset_inverter": True,
},
{
"name": "charge_low_power_margin",
"friendly_name": "Low power mode margin",
"type": "input_number",
"min": 0,
"max": 30,
"step": 5,
"unit": "minutes",
"icon": "mdi:seatbelt",
"enable": "set_charge_low_power",
"default": 10,
},
{
"name": "set_reserve_enable",
"friendly_name": "Set Reserve Enable",
Expand Down
5 changes: 3 additions & 2 deletions apps/predbat/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,10 @@ def execute_plan(self):
current_charge_rate = inverter.get_current_charge_rate()

# Adjust charge rate if we are more than 10% out or we are going back to Max charge rate
if abs(new_charge_rate - current_charge_rate) > (0.1 * inverter.battery_rate_max_charge) or (new_charge_rate == inverter.battery_rate_max_charge * MINUTE_WATT):
max_rate = inverter.battery_rate_max_charge * MINUTE_WATT
if abs(new_charge_rate - current_charge_rate) > (0.1 * max_rate) or (new_charge_rate == max_rate):
inverter.adjust_charge_rate(new_charge_rate)
resetCharge = False
resetCharge = False

if inverter.inv_charge_discharge_with_rate:
inverter.adjust_discharge_rate(0)
Expand Down
1 change: 1 addition & 0 deletions apps/predbat/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -1773,6 +1773,7 @@ def fetch_config_options(self):
self.set_export_freeze = self.get_arg("set_export_freeze")
self.set_charge_freeze = self.get_arg("set_charge_freeze")
self.set_charge_low_power = self.get_arg("set_charge_low_power")
self.charge_low_power_margin = self.get_arg("charge_low_power_margin")
self.calculate_export_first = True

self.set_status_notify = self.get_arg("set_status_notify")
Expand Down
1 change: 1 addition & 0 deletions apps/predbat/prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def __init__(self, base=None, pv_forecast_minute_step=None, pv_forecast_minute10
self.set_discharge_during_charge = base.set_discharge_during_charge
self.set_read_only = base.set_read_only
self.set_charge_low_power = base.set_charge_low_power
self.charge_low_power_margin = base.charge_low_power_margin
self.car_charging_slots = base.car_charging_slots
self.car_charging_limit = base.car_charging_limit
self.car_charging_from_battery = base.car_charging_from_battery
Expand Down
28 changes: 26 additions & 2 deletions apps/predbat/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ def run_execute_test(
set_charge_window=False,
set_export_window=False,
set_charge_low_power=False,
charge_low_power_margin=10,
assert_charge_time_enable=False,
assert_force_export=False,
assert_pause_charge=False,
Expand Down Expand Up @@ -778,6 +779,7 @@ def run_execute_test(
my_predbat.num_cars = 1
my_predbat.inverter_hybrid = inverter_hybrid
my_predbat.set_charge_low_power = set_charge_low_power
my_predbat.charge_low_power_margin = charge_low_power_margin

if assert_immediate_soc_target is None:
assert_immediate_soc_target = assert_soc_target
Expand Down Expand Up @@ -1080,7 +1082,29 @@ def run_execute_tests(my_predbat):
assert_status="Charging",
assert_charge_start_time_minutes=-1,
assert_charge_end_time_minutes=my_predbat.minutes_now + 60,
assert_charge_rate=500,
assert_charge_rate=600, # Within 10%
battery_max_rate=2000,
)
if failed:
return failed

# 60 minutes - 30 minute margin = 30 minutes to add 0.4kWh to each battery (x2 inverters)
# (60 / 20) * 400 = 1200
failed |= run_execute_test(
my_predbat,
"charge_low_power2c",
charge_window_best=charge_window_best,
charge_limit_best=charge_limit_best,
assert_charge_time_enable=True,
soc_kw=9.2,
set_charge_window=True,
set_export_window=True,
set_charge_low_power=True,
charge_low_power_margin=40,
assert_status="Charging",
assert_charge_start_time_minutes=-1,
assert_charge_end_time_minutes=my_predbat.minutes_now + 60,
assert_charge_rate=1200,
battery_max_rate=2000,
)
if failed:
Expand All @@ -1090,7 +1114,7 @@ def run_execute_tests(my_predbat):
# (60 / 50) * 450 = 540
failed |= run_execute_test(
my_predbat,
"charge_low_power2c",
"charge_low_power2d",
charge_window_best=charge_window_best,
charge_limit_best=charge_limit_best,
assert_charge_time_enable=True,
Expand Down
13 changes: 8 additions & 5 deletions apps/predbat/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ def find_charge_rate(model, minutes_now, soc, window, target_soc, max_rate, quie
"""
Find the lowest charge rate that fits the charge slow
"""
margin = 10
margin = model.charge_low_power_margin
target_soc = round(target_soc, 2)

if model.set_charge_low_power:
minutes_left = window["end"] - minutes_now - margin

Expand All @@ -208,21 +210,22 @@ def find_charge_rate(model, minutes_now, soc, window, target_soc, max_rate, quie

# What's the lowest we could go?
min_rate = charge_left / minutes_left
min_rate_w = int(min_rate * MINUTE_WATT)

# Apply the curve at each rate to pick one that works
rate_w = max_rate * MINUTE_WATT
best_rate = max_rate
while rate_w >= 400:
rate = rate_w / MINUTE_WATT
if rate >= min_rate:
if rate_w >= min_rate_w:
charge_now = soc
minute = 0
# Compute over the time period, include the completion time (margin was already counted)
for minute in range(0, minutes_left + PREDICT_STEP, PREDICT_STEP):
# Compute over the time period, include the completion time
for minute in range(0, minutes_left, PREDICT_STEP):
rate_scale = get_charge_rate_curve(model, charge_now, rate)
charge_amount = rate_scale * PREDICT_STEP * model.battery_loss
charge_now += charge_amount
if charge_now >= target_soc:
if round(charge_now, 2) >= target_soc:
best_rate = rate
break
rate_w -= 100.0
Expand Down

0 comments on commit 9e5c0e4

Please sign in to comment.