FoxESS EVO 10-5-H - Successfully Enabling Force Discharge / Force Charge in Home Assistant
I've managed to force discharge / force charge my FoxESS EVO 10-5-H in Home Assistant using modbus. I have the Elfin EW11 wired in to the inverter on pins 11 and 12. I am using v 1.15.0 of Nathan Marlor's foxess_modbus HACS integration, which he very recently updated with the work Adam has done on the brilliant _EVO fork.

Problem is that with the EVO you can't set work mode to Force Charge / Force Discharge, and it's a right pain getting it to dynamically work with timed periods, especially if you are linking to Predbat. Additionally many of the addresses seem to be read-only even over a hardwired modbus connection.

This method uses the Remote Control feature. Specific addresses used are:

46001 - Remote control
46002 - Remote Timeout_Set
46003 - Remote Control Active Power Command

Turns out you need to set all of these to get it to actually run, and you need to do that each time you want to trigger an action.

46001 - Remote control - setting this as '5' forces discharge to the grid. Setting it as '7' forces charge from the grid.
46002 - Timeout for the control in seconds. I use "300".
46003 - I haven't figured out what 46003 is, but 46004 is the required power to discharge / charge with. And 46004 cannot be written to. however 46003 accepts two comma separated values, so I use "0,5000"


You can test this by going to Settings / Developer Tools / Actions and finding the Write registers for your integration, select your inverter, then in "start address" put '46001' and in Values put '5'. then repeat for the other two addresses.

As this is a faff to do every time, and I have 0 idea how to do the GitHub bits, I've made it easier on Home Assistant.

Note the below isn't fully tested, but seems to be working for me. If you're using a different integration, you need to change the automation action target from foxess_modbus.write_registers to your one.

The way it works is you create 3 helpers to allow you to set the charge / discharge rate, and the mode. Changing the mode triggers an automation, which writes the modbus commands to charge or discharge. if you change back to self-use, it changes 46001 to '0' (off).

There is then a second automation that re-starts the first one every 4 minutes to ensure it doesn't time-out.

And there's a third automation that ensures you don't go below your minimum SOC.

Predbat can then be configured to target the work mode entity ID to trigger charge or discharge modes.

This may not be the easiest way to do this, but wanted to share the knowledge in case it helps someone.



Steps:


1. Create Helpers:

Number Helpers

Name: FoxESS Charge Power
Minimum Value: 0
Maximum Value: 5000
Step size: 100
Unit of measurement: W


Name: FoxESS Discharge Power
Minimum Value: 0
Maximum Value: 5000
Step size: 100
Unit of measurement: W

These control the maximum allowed power to / from your battery. Mine maxes out at 5,000W, hence above.

Once you've created the helper, you also need to assign a value to it eg 5000


Mode Helper

In configuration.yaml add the below:

Code: Select all

input_select:
  foxess_mode:
    name: FoxESS Mode
    options:
      - Self Use
      - Force Charge
      - Force Discharge
    initial: Self Use
    icon: mdi:battery
    
This creates an input selector you can use. Set the state as per options.



Automations

1. FoxESS Apply Mode

Code: Select all

alias: FoxESS Apply Mode
description: Writes charge/discharge/stop commands to FoxESS inverter via Modbus
variables:
  mode: "{{ states('input_select.foxess_mode') }}"
  charge_w: "{{ states('input_number.foxess_charge_power') | int(3000) }}"
  discharge_w: "{{ states('input_number.foxess_discharge_power') | int(3000) }}"
triggers:
  - entity_id:
      - input_select.foxess_mode
      - input_number.foxess_charge_power
      - input_number.foxess_discharge_power
    trigger: state
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ mode == 'Self Use' }}"
        sequence:
          - action: foxess_modbus.write_registers
            data:
              inverter: [your_inverter_reference]
              start_address: 46001
              values: "0"
      - conditions:
          - condition: template
            value_template: "{{ mode == 'Force Charge' }}"
        sequence:
          - action: foxess_modbus.write_registers
            data:
              inverter: [your_inverter_reference]
              start_address: 46001
              values: "7"
          - action: foxess_modbus.write_registers
            data:
              inverter: [your_inverter_reference]
              start_address: 46002
              values: "300"
          - action: foxess_modbus.write_registers
            data:
              inverter: [your_inverter_reference]
              start_address: 46003
              values: 0,{{ charge_w }}
      - conditions:
          - condition: template
            value_template: "{{ mode == 'Force Discharge' }}"
        sequence:
          - action: foxess_modbus.write_registers
            data:
              inverter: [your_inverter_reference]
              start_address: 46001
              values: "5"
          - action: foxess_modbus.write_registers
            data:
              inverter: [your_inverter_reference]
              start_address: 46002
              values: "300"
          - action: foxess_modbus.write_registers
            data:
              inverter: [your_inverter_reference]
              start_address: 46003
              values: 0,{{ discharge_w }}
2. FoxESS Remote Control Keepalive

Code: Select all

alias: FoxESS Remote Control Keepalive
description: Re-sends command every 4 minutes to prevent 300s timeout expiry
triggers:
  - minutes: /4
    trigger: time_pattern
conditions:
  - condition: template
    value_template: >
      {{ states('input_select.foxess_mode') in ['Force Charge', 'Force
      Discharge'] }}
actions:
  - action: automation.trigger
    target:
      entity_id: automation.foxess_apply_mode


3. FoxESS Stop Discharge at Min SoC

Code: Select all

alias: FoxESS Stop Discharge at Min SoC
description: Reverts to Self Use when battery hits MinSoC on Grid threshold
triggers:
  - value_template: |
      {{ states('sensor.foxess_bat_soc') | float(100)
         <= states('sensor.foxess_bat_minsocongrid') | float(10) }}
    trigger: template
conditions:
  - condition: state
    entity_id: input_select.foxess_mode
    state: Force Discharge
actions:
  - action: input_select.select_option
    target:
      entity_id: input_select.foxess_mode
    data:
      option: Self Use
To find [your_inverter_reference] go to Settings / Developer Tools / Actions, enter UI mode and find Read Registers / Write Registers linked to the FoxESS - Modbus integration from the top drop down. Next select your inverter. Now switch to YAML mode and your inverter name will be there next to inverter: xxxxxxxxxxxx