Chapter 8 – Dispatch Strategies and Control Logic

A battery is only as useful as the logic that controls it. This chapter covers how to decide — for each hour — whether to charge from solar, charge from the grid, discharge to the house, or hold. We progress from simple rule-based strategies to optimization-based approaches.


8.1 The Dispatch Problem

At each time step (typically each hour or 15-minute interval), the system must decide:

  1. Where does the house load come from? (Solar direct / Battery / Grid)
  2. Does the battery charge? (From solar surplus / From grid)
  3. Is any surplus exported to the grid?

Inputs available:


8.2 Strategy 1: Self-Consumption Priority (Basic Rule)

The simplest and most common strategy. Logic at each time step:

solar = measured solar production (W)
load  = measured household load (W)
soc   = battery state of charge (0–1)

net = solar - load

if net > 0:                          # Solar surplus
    if soc < soc_max:
        charge_rate = min(net, max_charge_rate)
        export = net - charge_rate
    else:
        export = net                  # Battery full, export all

else:                                 # Deficit
    deficit = -net
    if soc > soc_min:
        discharge_rate = min(deficit, max_discharge_rate)
        grid_import = deficit - discharge_rate
    else:
        grid_import = deficit         # Battery empty, import all

Performance: Very good for maximizing self-consumption. Does not optimize for tariff timing. Straightforward to implement in any home energy management system.


8.3 Strategy 2: Peak Shaving

Goal: keep grid import below a threshold power level (e.g., 1 kW), regardless of price. Useful for households with demand charges.

grid_threshold = 1000  # W

if solar >= load:
    # Charge battery from surplus
    charge(solar - load)
    grid_import = 0
else:
    deficit = load - solar
    if deficit > grid_threshold:
        # Discharge battery to keep import below threshold
        discharge_needed = deficit - grid_threshold
        if soc > soc_min:
            discharge(min(discharge_needed, available_capacity))
    grid_import = min(deficit, grid_threshold)

8.4 Strategy 3: TOU-Aware Dispatch

Uses tariff schedule to decide when to charge from grid and when to discharge:

price_now = tariff.price(hour)
price_peak_threshold = 0.25   # €/kWh — discharge when more expensive
price_charge_threshold = 0.12 # €/kWh — charge from grid when cheaper

solar_surplus = max(0, solar - load)
deficit = max(0, load - solar)

# Charge from solar surplus (always)
if solar_surplus > 0 and soc < soc_max:
    charge(solar_surplus)

# Discharge during peak price periods
elif deficit > 0 and price_now >= price_peak_threshold and soc > soc_min:
    discharge(min(deficit, max_discharge_rate))
    grid_import = deficit - actual_discharge

# Charge from grid during cheap periods (only if battery not already full)
elif price_now <= price_charge_threshold and soc < 0.5:
    grid_charge(min(max_charge_rate, available_capacity_to_50pct))

else:
    grid_import = deficit

Performance improvement vs. Strategy 1 on TOU tariffs: typically saves an additional 5–12% on the annual electricity bill.


8.5 Strategy 4: Day-Ahead Optimization

The most powerful approach: use a day-ahead forecast of load and solar to compute the optimal battery schedule for the next 24 hours.

Formulated as a linear program:

Minimize: Σ_h [ grid_import(h) × price(h) ] − Σ_h [ grid_export(h) × export_price(h) ]

Subject to:

This is a convex LP, solvable in milliseconds with scipy.optimize.linprog or PuLP.

from dispatch_optimizer import optimize_day

schedule = optimize_day(
    solar_forecast=solar_kwh_per_hour,   # list of 24 values
    load_forecast=load_kwh_per_hour,
    prices=price_per_kwh,
    battery_params={
        "capacity_kwh": 10.0,
        "dod": 0.90,
        "charge_efficiency": 0.97,
        "discharge_efficiency": 0.97,
        "max_charge_kw": 5.0,
        "max_discharge_kw": 5.0,
        "initial_soc": 0.5,
    }
)

print(f"Optimal daily cost: €{schedule['cost']:.2f}")
print(f"Grid imports: {sum(schedule['grid_import']):.1f} kWh")

Performance vs. Strategy 1: saves an additional 8–18% on the energy bill, depending on tariff variability and forecast accuracy.


8.6 Forecast-Based Pre-Charging

A common practical optimization: if tomorrow morning’s weather forecast shows a cloudy day, charge the battery tonight from cheap off-peak grid power. If a sunny day is forecast, don’t bother — the battery will fill from solar.

Simple rule:

if tomorrow_solar_forecast < 50% of typical and price_now < off_peak_threshold:
    charge to 80% SoC from grid

This captures much of the day-ahead optimization benefit without the LP complexity.


8.7 Backup Reserve Strategy

If backup during outages is a priority, always maintain a minimum SoC reserve:

backup_reserve = 0.30  # Keep 30% SoC as backup at all times
effective_soc_min = max(soc_min, backup_reserve)

For a 10 kWh battery with 30% backup reserve: 3 kWh always reserved, 7 kWh available for daily dispatch. This reduces self-consumption performance by ~5–10% but provides 6+ hours of critical-load backup.


8.8 Communication Protocols and HEMS

Real home energy management systems (HEMS) implement these strategies and communicate with inverters, batteries, and smart meters using standard protocols:

Protocol Typical use
Modbus RTU/TCP Inverter telemetry and control
SunSpec Standardized solar/storage device interface
EEBus European smart home energy protocol
OCPP EV charging station communication
Home Assistant / OpenHAB Open-source HEMS platforms
Proprietary APIs SolarEdge, Fronius, Victron, etc.

Open-source solutions like Home Assistant + Solcast integration can implement all the strategies in this chapter using automation rules, with accuracy improving as you add actual solar irradiance forecasts.


8.9 Performance Comparison Summary

Strategy Complexity Annual saving vs. no battery Notes
No battery (solar only) Baseline ~50–55% SSR
Self-consumption priority Low +€250–350/yr Most deployed
TOU-aware dispatch Medium +€310–440/yr Requires tariff data
Day-ahead LP optimization High +€380–520/yr Requires forecasts

Figures assume: 5,000 kWh/year household, 4 kWp solar, 10 kWh battery, Lyon France, €0.25/kWh peak / €0.12/kWh off-peak TOU tariff.


Navigation: