Skip to content

Commit

Permalink
Max charge rate temperature curve adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
springfall2008 authored Jan 11, 2025
1 parent f9db1d8 commit 94f36f7
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 146 deletions.
16 changes: 11 additions & 5 deletions apps/predbat/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import sys
from datetime import datetime, timedelta
from config import MINUTE_WATT, PREDICT_STEP
from utils import dp2, dp3, calc_percent_limit, find_charge_rate
from utils import dp0, dp2, dp3, calc_percent_limit, find_charge_rate
from inverter import Inverter

"""
Expand Down Expand Up @@ -101,8 +101,7 @@ def execute_plan(self):
self.log("Inverter {} Charge window will be: {} - {} - current soc {} target {}".format(inverter.id, charge_start_time, charge_end_time, inverter.soc_percent, self.charge_limit_percent_best[0]))
# Are we actually charging?
if self.minutes_now >= minutes_start and self.minutes_now < minutes_end:
new_charge_rate = int(
find_charge_rate(
new_charge_rate, new_charge_rate_real = find_charge_rate(
self.minutes_now,
inverter.soc_kw,
window,
Expand All @@ -116,9 +115,10 @@ def execute_plan(self):
self.battery_rate_max_scaling,
self.battery_loss,
self.log,
self.battery_temperature,
self.battery_temperature_discharge_curve
)
* MINUTE_WATT
)
new_charge_rate = int(new_charge_rate * MINUTE_WATT)
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
Expand Down Expand Up @@ -602,6 +602,7 @@ def fetch_inverter_data(self, create=True):
self.discharge_rate_now = 0.0
self.pv_power = 0
self.load_power = 0
self.battery_temperature = 0
found_first = False

if create:
Expand Down Expand Up @@ -666,6 +667,11 @@ def fetch_inverter_data(self, create=True):
self.pv_power += inverter.pv_power
self.load_power += inverter.load_power
self.current_charge_limit = calc_percent_limit(self.current_charge_limit_kwh, self.soc_max)
self.battery_temperature += inverter.battery_temperature


# Work out battery temperature
self.battery_temperature = int(dp0(self.battery_temperature / self.num_inverters))

# Remove extra decimals
self.soc_max = dp3(self.soc_max)
Expand Down
7 changes: 7 additions & 0 deletions apps/predbat/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -1768,6 +1768,13 @@ def fetch_config_options(self):
self.log("Warn: battery_discharge_power_curve is incorrectly configured - ignoring")
self.record_status("battery_discharge_power_curve is incorrectly configured - ignoring", had_errors=True)

# Temperature curve
self.battery_temperature_discharge_curve = self.args.get("battery_temperature_discharge_curve", {})
if not isinstance(self.battery_temperature_discharge_curve, dict):
self.battery_temperature_discharge_curve = {}
self.log("Warn: battery_temperature_discharge_curve is incorrectly configured - ignoring")
self.record_status("battery_temperature_discharge_curve is incorrectly configured - ignoring", had_errors=True)

self.import_export_scaling = self.get_arg("import_export_scaling", 1.0)
self.best_soc_margin = 0.0
self.best_soc_min = self.get_arg("best_soc_min")
Expand Down
5 changes: 5 additions & 0 deletions apps/predbat/inverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def __init__(self, base, id=0, quiet=False, rest_postCommand=None, rest_getData=
self.battery_rate_max_discharge = 0
self.battery_rate_max_charge_scaled = 0
self.battery_rate_max_discharge_scaled = 0
self.battery_temperature = 20
self.battery_power = 0
self.battery_voltage = 52.0
self.pv_power = 0
Expand Down Expand Up @@ -258,6 +259,7 @@ def __init__(self, base, id=0, quiet=False, rest_postCommand=None, rest_getData=
self.nominal_capacity = self.soc_max
self.soc_max *= self.battery_scaling
self.soc_max = dp3(self.soc_max)
self.battery_temperature = idetails.get("Battery_Temperature", 20)

if self.rest_data and ("raw" in self.rest_data):
raw_data = self.rest_data["raw"]
Expand All @@ -270,6 +272,7 @@ def __init__(self, base, id=0, quiet=False, rest_postCommand=None, rest_getData=
self.nominal_capacity = self.soc_max
self.soc_max *= self.battery_scaling
self.soc_max = dp3(self.soc_max)
self.battery_temperature = idetails.get("Battery_Temperature", 20)

# Battery capacity nominal
battery_capacity_nominal = raw_data.get("invertor", {}).get("battery_nominal_capacity", None)
Expand Down Expand Up @@ -311,6 +314,7 @@ def __init__(self, base, id=0, quiet=False, rest_postCommand=None, rest_getData=
if "Invertor_Time" in idetails:
ivtime = idetails["Invertor_Time"]
else:
self.battery_temperature = self.base.get_arg("battery_temperature", default=20, index=self.id)
self.soc_max = self.base.get_arg("soc_max", default=10.0, index=self.id) * self.battery_scaling
self.nominal_capacity = self.soc_max

Expand All @@ -323,6 +327,7 @@ def __init__(self, base, id=0, quiet=False, rest_postCommand=None, rest_getData=

ivtime = self.base.get_arg("inverter_time", index=self.id, default=None)


# Battery cannot be zero size
if self.soc_max <= 0:
self.base.log("Error: Reported battery size from REST is {}, but it must be >0".format(self.soc_max))
Expand Down
4 changes: 3 additions & 1 deletion apps/predbat/predbat.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import asyncio
import json

THIS_VERSION = "v8.10.2"
THIS_VERSION = "v8.11.0"

# fmt: off
PREDBAT_FILES = ["predbat.py", "config.py", "prediction.py", "gecloud.py","utils.py", "inverter.py", "ha.py", "download.py", "unit_test.py", "web.py", "predheat.py", "futurerate.py", "octopus.py", "solcast.py","execute.py", "plan.py", "fetch.py", "output.py", "userinterface.py"]
Expand Down Expand Up @@ -310,6 +310,7 @@ def reset(self):
self.soc_kw = 0
self.soc_percent = 0
self.soc_max = 10.0
self.battery_temperature = 20
self.end_record = 24 * 60 * 2
self.predict_soc = {}
self.predict_soc_best = {}
Expand Down Expand Up @@ -506,6 +507,7 @@ def reset(self):
self.pv_today = {}
self.load_minutes = {}
self.load_minutes_age = 0
self.battery_temperature_discharge_curve = {}

self.config_root = "./"
for root in CONFIG_ROOTS:
Expand Down
43 changes: 21 additions & 22 deletions apps/predbat/prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ def __init__(self, base=None, pv_forecast_minute_step=None, pv_forecast_minute10
self.battery_rate_max_discharge_scaled = base.battery_rate_max_discharge_scaled
self.battery_charge_power_curve = base.battery_charge_power_curve
self.battery_discharge_power_curve = base.battery_discharge_power_curve
self.battery_temperature = base.battery_temperature
self.battery_temperature_discharge_curve = base.battery_temperature_discharge_curve
self.battery_rate_max_scaling = base.battery_rate_max_scaling
self.battery_rate_max_scaling_discharge = base.battery_rate_max_scaling_discharge
self.battery_loss = base.battery_loss
Expand Down Expand Up @@ -644,28 +646,25 @@ def run_prediction(self, charge_limit, charge_window, export_window, export_limi
four_hour_rule = False
elif (charge_window_n >= 0) and soc < charge_limit_n:
# Charge enable
if self.set_charge_window and (save in ["best", "best10", "test"]):
# Only tune charge rate on final plan not every simulation
charge_rate_now = find_charge_rate(
minute_absolute,
soc,
charge_window[charge_window_n],
charge_limit_n,
self.battery_rate_max_charge,
self.soc_max,
self.battery_charge_power_curve,
self.set_charge_low_power,
self.charge_low_power_margin,
self.battery_rate_min,
self.battery_rate_max_scaling,
self.battery_loss,
None,
)
else:
charge_rate_now = self.battery_rate_max_charge # Assume charge becomes enabled here

# Apply the charging curve
charge_rate_now_curve = get_charge_rate_curve(soc, charge_rate_now, self.soc_max, self.battery_rate_max_charge, self.battery_charge_power_curve, self.battery_rate_min) * self.battery_rate_max_scaling
set_charge_low_power = self.set_charge_window and self.set_charge_low_power and (save in ["best", "best10", "test"])
# Only tune charge rate on final plan not every simulation
charge_rate_now, charge_rate_now_curve = find_charge_rate(
minute_absolute,
soc,
charge_window[charge_window_n],
charge_limit_n,
self.battery_rate_max_charge,
self.soc_max,
self.battery_charge_power_curve,
set_charge_low_power,
self.charge_low_power_margin,
self.battery_rate_min,
self.battery_rate_max_scaling,
self.battery_loss,
None,
self.battery_temperature,
self.battery_temperature_discharge_curve,
)

battery_draw = -max(min(charge_rate_now_curve * step, charge_limit_n - soc), 0, -battery_to_max)
battery_state = "f+"
Expand Down
Loading

0 comments on commit 94f36f7

Please sign in to comment.