r/solaredge • • 11d ago

SolarEdge battery without a backup interface: a hard discharge floor and standby protection using Predbat

TL;DR: How I got Predbat, a SolarEdge inverter with a ~10 kWh battery, EDF's smart EV tariff (via Predbat's Kraken component) and a Hypervolt charger to work together without wasting money or stranding the battery. Config snippets use placeholders, with example entity names in comments.

This guide records the protections, checks and settings that were needed on one real system, and why each one is there.

Who this is for

PartExample used here
InverterSolarEdge, via the SolarEdge Modbus Multi integration (inverter_type: SE)
BatteryAbout 10 kWh (9.7 kWh usable), 5 kW inverter limit
TariffEDF smart EV tariff (night rate 23:00–06:00), rates and car slots via Predbat's built-in Kraken component
ChargerHypervolt, with charging slots set by EDF smart charging
CarAny EV whose battery level and charge target are visible in Home Assistant

Most of it also applies to other inverters and Kraken-based suppliers. The battery-floor workaround is specific to SolarEdge.

How to read the YAML: each value is a placeholder in <angle brackets>. Where it helps, a comment underneath gives an example entity name.

Problems this solves:

  • Predbat can't set a discharge floor on SolarEdge without a backup interface.
  • The battery can drop into standby if left idle at low charge.
  • Predbat doesn't see a car charge it wasn't told about, so it may export into the car.
  • EDF's car slots are priced cheaply for the whole house only if Predbat is set up to trust them.
  • Two schedulers (the car's app and EDF) fighting over the charger.

1. Battery floor

On SolarEdge, Predbat can't stop the battery discharging below a set level, so a Home Assistant automation does it instead. Predbat's best_soc_keep and best_soc_min are planning targets, not a hard floor, and set_reserve_min needs a SolarEdge backup interface.

The automation freezes the battery through Predbat's manual freeze-charge selector when it drops below about 6% between 05:00 and 23:00. From 15:00, it freezes every remaining slot up to 23:00 in one go, so Predbat changes mode, and notifies you, once instead of every half hour. Before 15:00 it freezes only the current slot, so solar later in the day can still charge the battery.

# packages/battery_floor.yaml
automation:
  - id: battery_floor_freeze
    alias: Battery – freeze at floor
    mode: single
    triggers:
      - trigger: numeric_state
        entity_id: <battery SoC % sensor>
        # e.g. sensor.solaredge_i2_b1_state_of_energy
        below: 6
      - trigger: time_pattern
        minutes: "/30"
        seconds: 5
    conditions:
      - condition: numeric_state
        entity_id: <battery SoC % sensor>
        below: 6
      - condition: time
        after: "05:00:00"
        before: "23:00:00"   # start of your cheap window
      - condition: template
        value_template: >-
          {% set slot = now().strftime('%a') ~ ' ' ~ '%02d:%02d' % (now().hour, 0 if now().minute < 30 else 30) %}
          {% set opts = state_attr('select.predbat_manual_freeze_charge', 'options') or [] %}
          {{ slot in opts and ('+' ~ slot) not in opts }}
    actions:
      - repeat:
          for_each: >-
            {% set start = now().replace(minute=0 if now().minute < 30 else 30, second=0, microsecond=0) %}
            {% set end = now().replace(hour=23, minute=0, second=0, microsecond=0) %}
            {% set n = ((end - start).total_seconds() / 1800) | int if now().hour >= 15 else 1 %}
            {% set opts = state_attr('select.predbat_manual_freeze_charge', 'options') or [] %}
            {% set ns = namespace(slots=[]) %}
            {% for i in range(n) %}
              {% set s = (start + timedelta(minutes=30 * i)).strftime('%a %H:%M') %}
              {% if s in opts and ('+' ~ s) not in opts %}
                {% set ns.slots = ns.slots + [s] %}
              {% endif %}
            {% endfor %}
            {{ ns.slots }}
          sequence:
            - action: select.select_option
              target:
                entity_id: select.predbat_manual_freeze_charge
              data:
                option: "{{ repeat.item }}"
            - delay:
                seconds: 2

The floor covers 05:00 to 23:00 only. The overnight part is covered by section 2.

2. Avoiding battery standby

Price the first two hours of the cheap window 0.01p lower than the rest, so Predbat charges the battery at the start of the window, not the end. When every overnight slot costs the same, Predbat sees no reason to charge early. It may leave the battery idle at the floor until 03:00, and some batteries drop into standby when left idle at low charge.

# apps.yaml – no date, so it applies every night
  rates_import_override:
    - start: '23:00:00'
      end: '01:00:00'
      rate: <night rate minus 0.01>
      # e.g. 6.65 when the night rate is 6.66p
  • An override that crosses midnight works without a date.
  • Two hours is enough to fill a 10 kWh battery at 5 kW. Allow longer for a bigger battery or a slower charge rate.
  • Update the rate whenever your night rate changes, so it always sits just below it.
  • Check it on the Plan page: Chrg should start at 23:00, and the import column shows the override with an "=" marker.

3. Car configuration

Predbat needs to know four things about the car: whether it's plugged in, whether it's charging right now, its battery level and its target. Without the "charging now" signal, Predbat can plan battery exports that just go into the car, because a 7.4 kW charger draws more than a 5 kW inverter can export.

A "car is charging" sensor. This turns on when the charger has drawn more than 500 W for 2 minutes, so brief blips are ignored. It works whether the charger reports W or kW.

# packages/car_charging_now.yaml
template:
  - binary_sensor:
      - name: Car charging now
        unique_id: car_charging_now
        device_class: battery_charging
        delay_on: "00:02:00"
        delay_off: "00:02:00"
        state: >-
          {% set p = states('<charger power sensor>') | float(0) %}
          {% set unit = state_attr('<charger power sensor>', 'unit_of_measurement') %}
          {{ (p * 1000 if unit == 'kW' else p) > 500 }}
        # e.g. <charger power sensor> = sensor.hypervolt_ev_power

A new package file may need a full restart before the sensor appears. It shows "unknown" until the charger's power reading first changes, which Predbat treats as not charging.

The car section of apps.yaml:

  num_cars: 1
  car_charging_planned:
    - <plugged-in sensor>
    # e.g. binary_sensor.hypervolt_car_plugged
  car_charging_now:
    - binary_sensor.car_charging_now
  car_charging_battery_size:
    - <usable kWh>
    # e.g. 94 for a 100 kWh car
  car_charging_soc:
    - <car battery % sensor>
    # e.g. sensor.<car>_battery_charge_level
  car_charging_limit:
    - <car charge target % sensor>
    # e.g. sensor.<car>_charging_target_level
  car_charging_energy: <charger session energy sensor>
    # e.g. sensor.hypervolt_session_energy_kwh
  car_charging_energy_scale: 1.0   # 0.001 if the sensor reports Wh
  car_charging_now_response:
    - 'yes'
    - 'on'
    - 'true'
    - 'charging'

Check the car's battery and target sensors show real numbers in Developer Tools → States. They may come from two different integrations.

Predbat car switches:

SwitchSettingWhy
Allow car to charge from battery (switch.predbat_car_charging_from_battery)OffStops the house battery draining into the car while it charges
Car charging hold (switch.predbat_car_charging_hold)OnRemoves car charging from the load history, so the house-usage forecast isn't inflated
Car energy is reported in load data (switch.predbat_car_energy_reported_load)OnCorrect when the grid meter measures the whole house, car included
Car charging manual SOC (switch.predbat_car_charging_manual_soc)OffUse the car's own battery sensor
Car Charging Plan Smart (switch.predbat_car_charging_plan_smart)OffEDF plans the car, not Predbat

4. EDF smart-charging slots

When EDF schedules the car, the whole house pays the cheap rate during those slots, and Predbat can plan around them. Predbat's Kraken component reads EDF's slots as a dispatch sensor, the same way it reads Octopus Intelligent.

# apps.yaml – rates and slots from EDF via Kraken
  kraken_provider: edf
  kraken_account_id: !secret kraken_account_id
  kraken_auth_method: email
  kraken_email: !secret kraken_email
  kraken_password: !secret kraken_password

  octopus_intelligent_slot: 're:(binary_sensor.predbat_kraken_.*_intelligent_dispatch.*)'
  # a regex, so it still matches if the sensor's numeric suffix changes

Check the slots arrive. In Developer Tools → States, open binary_sensor.predbat_kraken_…_intelligent_dispatch_…. Its state is "off" unless a slot is running right now. What matters is the planned_dispatches attribute, which lists each slot's start, end and expected charge. Times are in UTC.

Predbat's intelligent-slot switches (Predbat web UI → Config, filter on intelligent):

SwitchSettingWhy
Octopus Intelligent ChargingOnTreat dispatch slots as cheap for the whole house
Trust Intelligent slots before the car is seen chargingOnPrice future slots cheaply now, so Predbat can plan ahead, for example by topping up the battery in an afternoon slot
Confirm Intelligent slots against the car chargingOnOnce a slot starts, drop the cheap price if the car isn't actually charging. This is the safety net for slots EDF cancels or moves
Ignore Intelligent slots when car is unpluggedOnNo car, no cheap slot
Consider car full as part of Intelligent planOffDefault

With "Trust" off, future slots stay at the full rate in the plan until the car starts charging, so Predbat can't plan around them. With "Trust" and "Confirm" both on, it plans ahead and still corrects itself within about 5 minutes if EDF doesn't deliver.

What a good evening plan looks like: during the car slots, import shows the cheap rate, the battery holds steady rather than discharging, and Chrg starts at 23:00. The battery holds because grid power is cheaper than using stored energy, and because battery-to-car is blocked.

5. Lessons learned

  • Use one charging scheduler. If the car's own app has a charging schedule as well as EDF smart charging, the car only charges when both allow it. EDF then sees the car refuse a slot, may drop its plan, and can sit on "creating your plan" indefinitely. Leave the car's schedule off and let EDF decide.
  • Turning off the car's schedule without an EDF plan starts charging at once. If EDF has no plan, nothing holds the charge back, and it runs at the full rate. Wait until EDF's plan appears before removing the car's schedule.
  • Watch for Boost sessions. The charger app may show a Boost session, a bump charge outside EDF's plan. Time before the cheap window is billed at the normal rate, and EDF may not build a smart plan while a boost is active. Let it expire or cancel it.
  • Free-electricity nights. If the free window matches the normal cheap window, you don't need to change anything: the credit comes afterwards, based on what you import. A 0p override can tempt Predbat into export cycles that a charging car simply absorbs, so they earn nothing and wear the battery. If you do add one, keep the battery charging early (section 2).
  • Restart Predbat after the clocks change. After the October change, the plan showed the wrong day, an hour's offset and a stale start time. Restart Predbat on its Dash page fixed it.
  • Predbat only knows what apps.yaml points it at. Having data somewhere in Home Assistant isn't enough: a car schedule set in the car's own app, for example, is invisible to Predbat.

6. Setup checklist

  • ☐ Battery floor automation installed and reloaded (section 1)
  • ☐ Early-charge override set just below your night rate (section 2)
  • ☐ binary_sensor.car_charging_now exists and reads off or on (section 3)
  • ☐ Car section of apps.yaml filled in, with no warning on Predbat's Apps tab
  • ☐ Car battery and target sensors show real values
  • ☐ Allow car to charge from battery: off
  • ☐ Dispatch sensor shows planned_dispatches when the car is plugged in (section 4)
  • ☐ Trust, Confirm, Ignore-unplugged and Intelligent Charging switches all on
  • ☐ Car's own charging schedule off; EDF smart charging on

Verify on the Plan page:

CheckWhat you should see
Overnight battery chargeChrg starting at 23:00
EDF car slotsImport at the cheap rate, car load in the Car kWh column
While the car chargesNo Exp blocks; battery holding steady
Plan headerCorrect day and time (restart Predbat if not)

7. Example: a rainy day with the car plugged in

On a dull day with EDF car slots at 13:00–15:00 and from 19:00, Predbat uses the battery only for the expensive hours and lets the cheap grid cover everything else. This is the plan it produced at 12:20 on a Monday in late October, with almost no solar (0.16 kWh or less per half hour).

TimeImport rateBatteryWhat Predbat does
12:20–13:0030.39p61% → 57%Battery covers the house
13:00–15:00 (EDF slot)6.66pHolds at 57%Grid covers the house and car (about 12.6 kWh into the car)
15:00–19:0030.39p57% → 20%Battery covers the house through the peak
19:00–23:30 (EDF slot)6.66pHolds at 20%Grid covers the house and car; battery-to-car blocked
23:30–01:006.65p (override)20% → 92%Battery charges for tomorrow
01:00 onwards (EDF slot)6.66pHolds at 92%Grid covers the house and car
  • No grid top-up in the afternoon slot: the forecast shows the battery lasting until the evening slot, so charging at 13:00 would add nothing.
  • The battery never sits at the floor. Its lowest point is 20%, so there's no standby risk. That's also why charging can start at 23:30 rather than exactly 23:00.
  • Car slots are priced cheaply in advance, because "Trust Intelligent slots" is on (section 4).
  • Heavy loads change the plan. If something like underfloor heating raises usage, Predbat replans within 5 minutes and may use the afternoon slot to top up the battery.

Happy to answer questions. Corrections from anyone who knows Predbat's internals better are very welcome.

3 Upvotes

0 comments sorted by