davidusb-geek / emhass

emhass: Energy Management for Home Assistant, is a Python module designed to optimize your home energy interfacing with Home Assistant.
MIT License
260 stars 51 forks source link

howto control battery charging soc #151

Closed mschneider82 closed 4 months ago

mschneider82 commented 5 months ago

I managed to setup prices from nordpool (hourly dynamic) and pv forecast from solcast. My only workload should be currently charging the battery when its cheap and not much PV is in forecast (10 kwh battery). But i feel this is wrong, It should be charged based on the SOC calculation not as a deferred load.

When the price is cheap i have a task that charges the battery for example from 3:00 am to 4:59am from 0% to 99% (currently deferred load). The problem is, after that, i set my battery to self consumtion and it starts to discharge until midday. In the afternoon hours its mostly expensive but the SOC is nearly 0%.

How do you better charge and discharge the battery? the battery level should be preserved for the expensive hours. Do you set your min SOC every hour to another value ?

purcell-lab commented 5 months ago

Can you show us the graphs from the EMHASS Web UI.

Generally you don't treat your battery as a deferred load and it should charge during the cheapest prices of the day. Screenshot_20240123-180248

mschneider82 commented 5 months ago

I have to wait some hours when the prices for tomorrow are out, since i restarted the instance an hour ago and currently the nordpool forecast fails because it has only 12 values instead of 24. When the prices are out i can trigger the dayahead

But I have to somehow trigger the charging, it only charges itself via PV currently. There is no Trigger for charge it from Grid. I can setup a manuel crontab job or homeassist schedule to turn grid-charge on and off and set the charge W (e.g. 5000W)

But i need some way to do this based on the forecast

mschneider82 commented 5 months ago

image

image

image

image

mschneider82 commented 5 months ago

For pv export we only get 0.08€ / kwh in germany. I have set the following values:

retrieve_hass_conf:
  - freq: 60 # The time step to resample retrieved data from hass in minutes
  - days_to_retrieve: 3 # We will retrieve data from now and up to days_to_retrieve days
  - var_PV: 'sensor.total_dc_power' # Photovoltaic produced power sensor in Watts
  - var_load: 'sensor.load_power' # Household power consumption sensor in Watts (deferrable loads should be substracted)
  - load_negative: False # Set to True if the retrived load variable is negative by convention
  - set_zero_min: True # A special treatment for a minimum value saturation to zero. Values below zero are replaced by nans
  - var_replace_zero: # A list of retrived variables that we would want  to replace nans with zeros
    - 'sensor.total_dc_power'
  - var_interp: # A list of retrived variables that we would want to interpolate nan values using linear interpolation
    - 'sensor.total_dc_power'
    - 'sensor.load_power'
  - method_ts_round: 'nearest' # Set the method for timestamp rounding, options are: first, last and nearest

optim_conf:
  - set_use_battery: True # consider a battery storage
  - delta_forecast: 1 # days
  - num_def_loads: 1
  - P_deferrable_nom: # Watts
    - 500.0
  - def_total_hours: # hours
    - 2
  - treat_def_as_semi_cont: # treat this variable as semi continuous 
    - True
    - True
  - set_def_constant: # set as a constant fixed value variable with just one startup for each 24h
    - False
    - False
  - weather_forecast_method: 'scrapper' # options are 'scrapper' and 'csv'
  - load_forecast_method: 'naive' # options are 'csv' to load a custom load forecast from a CSV file or 'naive' for a persistance model
  - load_cost_forecast_method: 'hp_hc_periods' # options are 'hp_hc_periods' for peak and non-peak hours contracts and 'csv' to load custom cost from CSV file 
  - list_hp_periods: # list of different tariff periods (only needed if load_cost_forecast_method='hp_hc_periods')
    - period_hp_1:
      - start: '00:00'
      - end: '23:59'
  - load_cost_hp: 0.3507 # peak hours load cost in €/kWh (only needed if load_cost_forecast_method='hp_hc_periods')
  - load_cost_hc: 0.1419 # non-peak hours load cost in €/kWh (only needed if load_cost_forecast_method='hp_hc_periods')
  - prod_price_forecast_method: 'constant' # options are 'constant' for constant fixed value or 'csv' to load custom price forecast from a CSV file
  - prod_sell_price: 0.085 # power production selling price in €/kWh (only needed if prod_price_forecast_method='constant')
  - set_total_pv_sell: False # consider that all PV power is injected to the grid (self-consumption with total sell)
  - lp_solver: 'default' # set the name of the linear programming solver that will be used
  - lp_solver_path: 'empty' # set the path to the LP solver
  - set_nocharge_from_grid: False # avoid battery charging from the grid
  - set_nodischarge_to_grid: True # avoid battery discharging to the grid
  - set_battery_dynamic: False # add a constraint to limit the dynamic of the battery power in power per time unit
  - battery_dynamic_max: 0.9 # maximum dynamic positive power variation in percentage of battery maximum power
  - battery_dynamic_min: -0.9 # minimum dynamic negative power variation in percentage of battery maximum power
  - weight_battery_discharge: 1.0 # weight applied in cost function to battery usage for discharge
  - weight_battery_charge: 1.0 # weight applied in cost function to battery usage for charge

plant_conf:
  - P_grid_max: 16000 # The maximum power that can be supplied by the utility grid in Watts
  - module_model: # The PV module model
    - 'CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M'
  - inverter_model: # The PV inverter model
    - 'Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_'
  - surface_tilt: # The tilt angle of your solar panels
    - 30
  - surface_azimuth: # The azimuth angle of your PV installation
    - 205
  - modules_per_string: # The number of modules per string
    - 16 
  - strings_per_inverter: # The number of used strings per inverter
    - 1
  - Pd_max: 5000 # If your system has a battery (set_use_battery=True), the maximum discharge power in Watts
  - Pc_max: 5000 # If your system has a battery (set_use_battery=True), the maximum charge power in Watts
  - eta_disch: 0.70 # If your system has a battery (set_use_battery=True), the discharge efficiency
  - eta_ch: 0.70 # If your system has a battery (set_use_battery=True), the charge efficiency
  - Enom: 9700 # If your system has a battery (set_use_battery=True), the total capacity of the battery stack in Wh
  - SOCmin: 0.05 # If your system has a battery (set_use_battery=True), the minimun allowable battery state of charge
  - SOCmax: 0.95 # If your system has a battery (set_use_battery=True), the minimun allowable battery state of charge
  - SOCtarget: 0.05 # If your system has a battery (set_use_battery=True), the desired battery state of charge at the end of each optimization cycle
mschneider82 commented 5 months ago

charging on 2024-01-24 4:00 am for 0.17€ should be fine, but it should save battery SOC for decharging for the expensive hours. When i trigger this with a cronjob it immediately starts decharging after the charge was done. so my battery is almost empty in the afternoon when there is cloudy weather.

markusr commented 5 months ago

Try to set weight_battery_discharge and weight_battery_charge to 0.0 and try again. I found that other values don't find the "best" charging / discharging solution.

  - weight_battery_discharge: 0.0 # weight applied in cost function to battery usage for discharge
  - weight_battery_charge: 0.0 # weight applied in cost function to battery usage for charge
davidusb-geek commented 5 months ago

Try to set weight_battery_discharge and weight_battery_charge to 0.0 and try again. I found that other values don't find the "best" charging / discharging solution.

  - weight_battery_discharge: 0.0 # weight applied in cost function to battery usage for discharge
  - weight_battery_charge: 0.0 # weight applied in cost function to battery usage for charge

This is the default behavior now BTW

mschneider82 commented 5 months ago

ok thanks i will try it, but is using a deferrable the best and only solution here?

since deferrable load a fixed to a def_total_hours hours, it will always run for example 2 hours. In case of high PV i would like to skip the charge from grid. So def_total_hours should be something optional instead of fixed 2 hours .

mschneider82 commented 5 months ago

I want to share my results, it looks much better, I think i dont need a deferrable load at all. Since it must be at least 1 defereable load, i will configure it to 1 watt and 1 hour.

Based on the prediction the battery should be charged when P_batt has a negative number until the SOC_opt is reached. Then, on every hour when P_batt is 0 the self consumtion of the battery should be disabled ( i could achieve it by " Set reserved SoC for backup" to the SOC_opt value in my sungrow hybrid). How do you solve these issues?

image image image