HI,
For the past year or two, I’ve been using my home-brew EV charger as a dynamic solar charging solution.
I’ve created some sensors and a few automations, and I thought I’d share them with you. Are they perfect? Not at all. Do they work? Yes, though with some minor caveats.
So, how does it work?
Firstly, I created a sensor that measures my net energy usage. My solar system (Enphase Envoy-S Metered) provides all the necessary information.
Sensor:
sensor:
- name: Netto electriciteitsverbruik
unique_id: netto_electriciteitsverbruik
state: "{{ ((states('sensor.envoy_122239064314_current_power_consumption') | float(0) * 0.001) - (states('sensor.envoy_122239064314_current_power_production') | float(0) * 0.001))|round(2) }}"
unit_of_measurement: "Kw"
My 1-phase car charger is able to set the max amps charging, So I use that to dynamically control the charging current.
In my case I am on a 240V European system, so the minimum EV charging amperage of 6 amps x 240v = 1.44kW and in my case the maximum charging current is 20A x 240v = 4.8kW. Therefor I can dynamically control the charging from 1.44kW up to 4.8kW.
If you have a 3-phase charger, your minimum charge will start at 4.3kW ((3x6A) 18A x 240V = 4320W) which is way less efficient.
My new charger will be able to switch between 1-phase and 3-phase charging to make it even more efficient and to enable faster charging when needed.
####### smart solar charging ########
# evse = 1 phase car charger (API) #
# Vehicle state: #
# 2 = connected #
# 3 = charging #
# duracell = name of the Tesla EV #
# envoy = solar invertor monitoring #
#####################################
## turn smart solar charging on
- id: smart_solar_charging_on
alias: smart_solar_charging_on
initial_state: on
trigger:
- platform: state
entity_id: sensor.netto_electriciteitsverbruik # net energy usage
condition:
condition: and
conditions:
- condition: numeric_state
entity_id: sensor.netto_electriciteitsverbruik
below: "-1" # only when "uploading" more then 1Kw to the net
- condition: state
entity_id: input_boolean.solar_smart_charging # a boolean to be able to enable smart charging when needed
state: "on"
- condition: state
entity_id: sensor.evse_vehiclestate
state: "2" # Only when vehicle connected
- condition: numeric_state
entity_id: sensor.duracell_battery # Duracell is my tesla's name ;), just charge when the LFP battery is below 100%
below: "100"
action:
- service: input_number.set_value
data:
value: "6" # start at 6 amps
target:
entity_id: input_number.evse_max_amps # set the charging speed
- service: switch.turn_on
entity_id: switch.evse # turn charger on
- delay: 00:00:01
- service: switch.turn_on
entity_id: switch.duracell_charger # wake up the tesla, not really needed, is just slightly faster
- delay: 00:00:03
- service: homeassistant.update_entity
entity_id: sensor.evse # faster update the rest sensor of the charger
mode: restart
## turn smart solar charging off
- id: smart_solar_charging_off
alias: smart_solar_charging_off
initial_state: on
trigger:
- platform: numeric_state
entity_id: sensor.netto_electriciteitsverbruik
above: "0"
for:
minutes: "1"
condition:
condition: and
conditions:
- condition: state
entity_id: input_boolean.solar_smart_charging
state: "on"
- condition: state
entity_id: sensor.evse_vehiclestate
state: "3"
action:
- service: switch.turn_off
entity_id: switch.evse
- delay: 00:00:03
- service: homeassistant.update_entity
entity_id: sensor.evse
mode: restart
#### set charging amperage ####
## up
- id: smart_solar_charging_amperage_up
alias: smart solar charging amperage up
initial_state: on
trigger:
- platform: state
entity_id: sensor.netto_electriciteitsverbruik
condition:
condition: and
conditions:
- condition: numeric_state
entity_id: sensor.netto_electriciteitsverbruik
below: "-0.25" # we need at least 1A before we can go up
- condition: state
entity_id: input_boolean.solar_smart_charging
state: "on"
- condition: state
entity_id: sensor.evse_vehiclestate
state: "3" # only when actually charging
- condition: template
value_template: >-
{{ states('input_number.evse_max_amps') | float(0) <
(state_attr('input_number.evse_max_amps', 'max') | float(0)) |round(0) }}
action:
- service: input_number.set_value
data:
value: "{{ (states.input_number.evse_max_amps.state | float(0) + 1) | round(0) }}"
target:
entity_id: input_number.evse_max_amps
- service: homeassistant.update_entity
data: {}
target:
entity_id: sensor.evse
mode: restart
## down
- id: smart_solar_charging_amperage_down
alias: smart solar charging amperage down
initial_state: on
trigger:
- platform: state
entity_id: sensor.netto_electriciteitsverbruik
condition:
condition: and
conditions:
- condition: numeric_state
entity_id: sensor.netto_electriciteitsverbruik
above: "0"
- condition: state
entity_id: input_boolean.solar_smart_charging
state: "on"
- condition: state
entity_id: sensor.evse_vehiclestate
state: "3"
- condition: template
value_template: >-
{{ states('input_number.evse_max_amps') | float(0) >
(state_attr('input_number.evse_max_amps', 'min') | float(0)) |round(0) }}
action:
- service: input_number.set_value
data:
value: "{{ (states.input_number.evse_max_amps.state | float(0) - 1) | round(0) }}"
target:
entity_id: input_number.evse_max_amps
- service: homeassistant.update_entity
data: {}
target:
entity_id: sensor.evse
mode: restart
This results in:
As you can see, I am by no means an expert. I’m sure there is room for improvement, especially by combining automations.
On a cloudy day, the net energy usage checking every 10 seconds and adjusting by only 1 amp, is too slow to completely prevent any grid usage. For example, when our washing machines heater kicks in, it takes about 40-50 seconds for the charger to adjust the amperage accordingly.
This could be optimized by directly calculating the required amperage adjustment based on the actual net usage, rather than stepping up or down incrementally.
For example; if the net usage is 1.8kW, the charger would have to ideally step down 8A (1800/240=7.2) at once (with a minimum of 6A).
I haven’t yet figured out the best way to achieve this. If anyone is interested in helping out, please feel free to share!