DIY smart grid: EV (Tesla) charging on excess solar power production

After browsing a couple of solutions for this, I figured out how to make my EV charge on excess solar power production (when available). After automating the process of adjusting the charging power to the current grid power state, I’ve added some functionality to optimize the usage. I’ve tried covering basic usability and some added usability scenario’s. Let me take you through the steps.

Here’s what I started with:

  • a smart power meter (using the DSMR integration) that shows the total grid power consumption and production
  • a Tesla (using the HACS Tesla integration)
  • solar panels feeding power to my home grid
  • an iPhone with the Home Assistant companion app

Objective:
Feed excessive solar power to the car when it’s connected at home.

Steps taken:

Although I could have used the ‘power consumption’ directly (as it already is the sum of power production minus power consumption) to start the charging and calculate the amount of power surplus to use for charging, it would be a bit impractical as I would need to incorporate the power consumption value as well when re-calculating the power draw while charing. To avoid this, I had decided on creating a single ‘grid usage’ sensor. It looks like this:

- platform: template
  sensors: 
    power_grid_usage:
      friendly_name: "Power Grid Usage"
      unit_of_measurement: "W"
      value_template: >
        {% set power_production_w = states('sensor.power_production') | float * 1000 %}
        {% set power_consumption_w = states('sensor.power_consumption') | float * 1000 %}
        {% if power_production_w >= 0 and power_consumption_w >= 0 %}
          {{ (power_production_w - power_consumption_w) }}
        {% elif power_production_w >= 0 %}
          {{ power_production_w }}
        {% else %}
          {{ -1 * power_consumption_w }}
        {% endif %}

Next, I needed an automation that would start the charging when there is a grid surplus, adjusts the charging rate for varying power production and stops the charging when there is no surplus available. I’ve calculated it using 240 watts increments. Here’s what that automation looks like:

alias: "[Tesla] Charge on solar power"
description: ""
trigger:
  - platform: state
    entity_id: sensor.power_grid_usage
condition:
  - condition: state
    entity_id: binary_sensor.charger
    state: "on"
  - condition: state
    entity_id: device_tracker.location_tracker
    state: home
  - condition: state
    entity_id: input_boolean.smart_charge
    state: "on"
action:
  - variables:
      grid_usage: "{{ states('sensor.power_grid_usage') | float }}"
      max_charging_amps: 16
      min_charging_amps: 1
      grid_voltage: 240
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ grid_usage > 0 }}"
        sequence:
          - service: switch.turn_on
            target:
              entity_id: switch.charger
            data: {}
          - service: number.set_value
            target:
              entity_id: number.charging_amps
            data:
              value: >
                {% set charger_power_draw = (states('number.charging_amps') |
                int) * grid_voltage %} {% set charging_amps = ((grid_usage +
                charger_power_draw) / grid_voltage) | round(0, 'floor') | int %}
                {{ [max_charging_amps, charging_amps] | min }}
      - conditions:
          - condition: template
            value_template: "{{ grid_usage <= 0 }}"
        sequence:
          - service: number.set_value
            target:
              entity_id: number.charging_amps
            data:
              value: >
                {% set deficit_watts = -1 * grid_usage %} {% set
                current_charging_amps = states('number.charging_amps') | int %}
                {% set required_charging_amps = ((deficit_watts / grid_voltage)
                | round(0, 'ceil')) | int %} {% set updated_charging_amps =
                current_charging_amps - required_charging_amps %} {% if
                updated_charging_amps < min_charging_amps %}
                  1
                {% else %}
                  {{ [max_charging_amps, updated_charging_amps] | min }}
                {% endif %}
          - choose:
              - conditions:
                  - condition: template
                    value_template: "{{ states('number.charging_amps') | int <= 1 }}"
                sequence:
                  - service: switch.turn_off
                    target:
                      entity_id: switch.charger
                    data: {}
mode: single

As you can see, I’ve added some things in the process. Here’s what’s going on:

  • The conditions for initiating the automation are that the car charge connector needs to be connected, the car needs to be at my home location and a boolean called ‘smart charge’ needs to be on. The latter comes in handy for switching between smart charging (using this automation) and regular (max power) charging, as you will see later on.
  • I’ve set variables for the grid usage, min and max amps and the grid voltage
  • I’ve separated the actions for when grid voltage > 0 and voltage <= 0, as they have different workings
  • each time the grid usage changes, it triggers a new calculation. The <= 0 was the nifty part and took me some time, as I first completely overlooked the fact that when the grid voltage updated, I needed to store the previous values to calculate the deficit and set the amps accordingly.

Now that this worked, I decided to add some use cases.

Here’s the automation that starts regular (full power) charging when the smart charging boolean is turned off manually (or by automation):

alias: "[Tesla] Max power charge when smart charging is switched off"
description: ""
trigger:
  - platform: state
    entity_id: input_boolean.smart_charge
    to: "off"
condition:
  - condition: state
    entity_id: binary_sensor.charger
    state: "on"
  - condition: template
    value_template: "{{ states('sensor.battery')|float < states('number.charge_limit')|float }}"
action:
  - service: switch.turn_on
    target:
      entity_id: switch.charger
    data: {}
  - service: number.set_value
    target:
      entity_id: number.charging_amps
    data:
      value: |
        {{ states.number.charging_amps.attributes.max | int }}

As a sanity measure (to avoid the situation that I connect the car and it doesn’t start charging at all), I decided to create an automation that resets the smart charging boolean (so next time it connects, it starts charging regularly on full power), everytime the charge connector disconnects from the charge port:

alias: "[Tesla] Reset smart charging state upon charge connector disconnect"
description: ""
trigger:
  - platform: state
    entity_id: binary_sensor.charger
    to: "off"
action:
  - service: input_boolean.turn_off
    target:
      entity_id: input_boolean.smart_charge
    data: {}
  - service: number.set_value
    target:
      entity_id: number.charging_amps
    data:
      value: 16

Here’s the automation that asks me if I want to start smart charging, when I connect the car during daylight:

alias: "[Tesla] Ask user for smart charging when charge port connector connects"
description: ""
trigger:
  - platform: state
    entity_id: binary_sensor.charger
    to: "on"
condition:
  - condition: state
    entity_id: device_tracker.location_tracker
    state: home
  - condition: state
    entity_id: sun.sun
    state: above_horizon
action:
  - service: notify.user
    data:
      message: Enable smart charging?
      data:
        actions:
          - action: enable_smart_charging
            title: Enable
          - action: disable_smart_charging
            title: Disable

And here’s how the actions are handled:

alias: "[Tesla] smart charging iOS actions"
description: ""
trigger:
  - platform: event
    event_type: ios.notification_action_fired
    event_data:
      actionName: enable_smart_charging
  - platform: event
    event_type: ios.notification_action_fired
    event_data:
      actionName: disable_smart_charging
action:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ trigger.event.data.actionName == 'enable_smart_charging' }}"
        sequence:
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.smart_charge
            data: {}
      - conditions:
          - condition: template
            value_template: "{{ trigger.event.data.actionName == 'disable_smart_charging' }}"
        sequence:
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.smart_charge
            data: {}
          - service: switch.turn_on
            target:
              entity_id: switch.charger
            data: {}
          - service: number.set_value
            target:
              entity_id: number.charging_amps
            data:
              value: 16

Next, I wanted to receive a notification when the car is smart charging, but there is no surplus power production for a prolonged period of time (30 minutes), and I wanted to be able to switch from smart charging to regular charging:

alias: "[Tesla] iOS notify upon prolonged solar power deficit"
description: ""
trigger:
  - platform: state
    entity_id: switch.charger
    to: "off"
    for:
      minutes: 30
condition:
  - condition: state
    entity_id: input_boolean.smart_charge
    state: "on"
  - condition: template
    value_template: "{{ states('sensor.battery')|float < states('number.charge_limit')|float }}"
  - condition: state
    entity_id: binary_sensor.charger
    state: "on"
action:
  - service: notify.user
    data:
      message: No solar power available, disable smart charging?
      data:
        actions:
          - action: TURN_OFF_SMART_CHARGING
            title: Disable

Here’s how the actions are handled:

alias: "[Tesla] iOS actions prolonged solar power deficit"
description: ""
trigger:
  - platform: event
    event_type: ios.notification_action_fired
    event_data:
      actionName: TURN_OFF_SMART_CHARGING
condition: []
action:
  - service: input_boolean.turn_off
    target:
      entity_id: input_boolean.smart_charge
    data: {}

And for the opposite situation - notify me when there is a power surplus, but the car isn’t charging at all or is regular charging, so I can switch to smart charging:

alias: "[Tesla] iOS notify upon solar power production surplus"
description: ""
trigger:
  - platform: numeric_state
    entity_id: sensor.power_grid_usage
    above: 500
    for:
      minutes: 5
condition:
  - condition: state
    entity_id: input_boolean.smart_charge
    state: "off"
  - condition: template
    value_template: "{{ states('sensor.battery')|float < states('number.charge_limit')|float }}"
  - condition: state
    entity_id: binary_sensor.charger
    state: "on"
  - condition: sun
    before: sunset
    after: sunrise
action:
  - service: notify.user
    data:
      message: Excessive solar power production, enable smart charging?
      data:
        actions:
          - action: TURN_ON_SMART_CHARGING
            title: Inschakelen

And for the handling of the actions:

alias: "[Tesla] iOS actions solar power production surplus"
description: ""
trigger:
  - platform: event
    event_type: ios.notification_action_fired
    event_data:
      actionName: TURN_ON_SMART_CHARGING
condition: []
action:
  - service: input_boolean.turn_on
    target:
      entity_id: input_boolean.smart_charge
    data: {}

Well, that’s about it. I’ve been using this for about a month now, and it seems to cover almost all of my use cases. Let me know what you think!

7 Likes

Nice one, I sorta just started blindly trying to achieve a very similar result with a state machine in node-red, as my coding is terrible. Amazing how many ways there are to achieve nearly the same result.

Only real differences:

  1. Never let the charger turn off, keep the min amps at 1 even if it uses grid power
  2. Delay the optimal charge calc to 1/min and give some time for the car to react to setting change and energy meter numbers to update.

Not sure if these changes place less stress on the battery or charging equip (of relevance) but thought it a nice balance to not potentially hammering the car with minor adjustments.

I think my approach could be improved with some smarts to manage debouncing on the edge (if it matters) or incorporate a solar forecast to optimise grid usage based on remaining charge time/energy required to reach the car charge limit.

1 Like

Thanks for sharing, nice to have some alternative insights!

I’m wondering what your reasoning is behind the 1 amp minimum. To me, it feels like kind of defeating the purpose of building a fully optimized smart grid (I know, it’s splitting hairs, but I’m the precise type :wink: )

Here’s my motivation why that’s of no use:

  1. First, my home charging maximum power of 16 amps x 240 volts = 3.8kW compared to the supercharging limit of 624 amps x 400 volts = 250kW is kind of low-balling it when it comes to stressing the system… :wink:

  2. Second, the initiation, switching and halting of the charge session is not something that physically stresses the system, as all energy flow is electronically regulated via a power protocol. This is especially true for ramping up the charging amps. I won’t deny that the internal relay switches more often when no restraint are implemented along the borders of the net grid production, but the power increase as regulated by the protocol still prevents it from being heavily loaded (e.g. it’s not switching the full 16 amps resistive load all at once, as it is regulated, and solar power increases don’t happen in that large of chunks anyway) It kind of depends on the quality of the components used, wether a lot of switching is a disadvantage or not.

If you do feel the need to take the no-risk approach to this downside, then I would recommend a principle a bit like you’ve already implemented. Immediately after the charger switches to the on-state, block it from switching off for about a minute to prevent every-power-update-oscillation. Still, I would want it to switch on without a delay when the first opportunity arises (net grid power production >= 240 watts), not to miss any sunshine for driving purposes! :slight_smile:

@xdss I have been thinking about how to go about this for a couple of days, and I decided on going with this.

I’ve added a script to delay the switch.turn_off for the charger, that runs in single mode (it should finish it 2 minute delay without restarting or starting in parallel):

alias: "[Tesla] Delayed charger switch turn off"
mode: single
sequence:
  - delay:
      minutes: 2
  - service: switch.turn_off
    target:
      entity_id: switch.charger
    data: {}

I’ve updated the automation that controls the charge current in two spots, first to call the script when needed, and second to stop the script when the updated_charging_amps evaluates to 1 or bigger. In this way, every re-calculation within the time frame of 2 minutes that allows for the charger to run cancels the script for switching off the charger:

alias: "[Tesla] Charge on solar power"
description: ""
trigger:
  - platform: state
    entity_id: sensor.power_grid_usage
condition:
  - condition: state
    entity_id: binary_sensor.charger
    state: "on"
  - condition: state
    entity_id: device_tracker.location_tracker
    state: home
  - condition: state
    entity_id: input_boolean.smart_charge
    state: "on"
action:
  - variables:
      grid_usage: "{{ states('sensor.power_grid_usage') | float }}"
      max_charging_amps: 16
      min_charging_amps: 1
      grid_voltage: 240
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ grid_usage > 0 }}"
        sequence:
          - service: switch.turn_on
            target:
              entity_id: switch.charger
            data: {}
          - service: number.set_value
            target:
              entity_id: number.charging_amps
            data:
              value: >
                {% set charger_power_draw = (states('number.charging_amps') |
                int) * grid_voltage %} {% set charging_amps = ((grid_usage +
                charger_power_draw) / grid_voltage) | round(0, 'floor') | int %}
                {{ [max_charging_amps, charging_amps] | min }}
          - service: script.turn_off
            target:
              entity_id: script.delayed_charger_turn_off
      - conditions:
          - condition: template
            value_template: "{{ grid_usage <= 0 }}"
        sequence:
          - service: number.set_value
            target:
              entity_id: number.charging_amps
            data:
              value: >
                {% set deficit_watts = -1 * grid_usage %} {% set
                current_charging_amps = states('number.charging_amps') | int %}
                {% set required_charging_amps = ((deficit_watts / grid_voltage)
                | round(0, 'ceil')) | int %} {% set updated_charging_amps =
                current_charging_amps - required_charging_amps %} {% if
                updated_charging_amps < min_charging_amps %}
                  1
                {% else %}
                  {{ [max_charging_amps, updated_charging_amps] | min }}
                {% endif %}
          - choose:
              - conditions:
                  - condition: template
                    value_template: "{{ states('number.charging_amps') | int <= 1 }}"
                sequence:
                  - service: script.turn_on
                    target:
                      entity_id: script.delayed_charger_turn_off
                    data: {}
mode: single

Will test over the weekend!

1 Like

This works great! So I’m keeping this construct. I’ll play around for a bit with the delay settings based on real-life oscillation. Will report on that and adjust accordingly.

Minor update. It seems there has been a change in the API, which caused the script to encounter an error if the requested charging amps (say 16A) is bigger than the car’s set maximum number of amps (say due to a cold battery).

To fix this, I chose to dynamically update the variable ‘max_charging_amps’ from the set 16 amps to the maximum that the car enforces. This limit is shown as the attribute ‘max’ in the number.charging_amps. So here’s the changed variable:

max_charging_amps: "{{ state_attr('number.charging_amps', 'max') | int }}"

Now everything runs fine once again!

1 Like

Wow this looks great, I was looking for a solution as my energy monitor isn’t compatible with chargehq.net.
Thanks for sharing. I’ll let you know how it goes

1 Like

I found out that the number.charging_amps accepts a setting of 0, which removes the need for the charger to switch off during smart charging. I’ve updated the script accordingly. The variable min_charging_amps now is set to a value of 0. This also removes the need for any anti-fluttering scripts, thus I’ve removed that as well.

I’ve also set the voltage variable to the actual phase voltage as reported by the DSMR sensor.

Here’s the full code for the revised script (tested and working correctly):

alias: "[Tesla] Charge on solar power"
description: ""
trigger:
  - platform: state
    entity_id: sensor.power_grid_usage
condition:
  - condition: state
    entity_id: binary_sensor.charger
    state: "on"
  - condition: state
    entity_id: device_tracker.location_tracker
    state: home
  - condition: state
    entity_id: input_boolean.smart_charge
    state: "on"
action:
  - variables:
      grid_usage: "{{ states('sensor.power_grid_usage') | float }}"
      max_charging_amps: "{{ state_attr('number.charging_amps', 'max') | int }}"
      min_charging_amps: 0
      grid_voltage: "{{ states('sensor.voltage_phase_l3') | float }}"
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ grid_usage > 0 }}"
        sequence:
          - service: switch.turn_on
            target:
              entity_id: switch.charger
            data: {}
          - service: number.set_value
            target:
              entity_id: number.charging_amps
            data:
              value: >
                {% set charger_power_draw = (states('number.charging_amps') |
                int) * grid_voltage %} {% set charging_amps = ((grid_usage +
                charger_power_draw) / grid_voltage) | round(0, 'floor') | int %}
                {{ [max_charging_amps, charging_amps] | min }}
      - conditions:
          - condition: template
            value_template: "{{ grid_usage <= 0 }}"
        sequence:
          - service: number.set_value
            target:
              entity_id: number.charging_amps
            data:
              value: >
                {% set deficit_watts = -1 * grid_usage %} {% set
                current_charging_amps = states('number.charging_amps') | int %}
                {% set required_charging_amps = ((deficit_watts / grid_voltage)
                | round(0, 'ceil')) | int %} {% set updated_charging_amps =
                current_charging_amps - required_charging_amps %} {% if
                updated_charging_amps < min_charging_amps %}
                  0
                {% else %}
                  {{ [max_charging_amps, updated_charging_amps] | min }}
                {% endif %}
mode: single

1 Like

@dikkertjedap I have tried adding your code to my system and I have some functions working but the main charge on excess isn’t. Hoping you can help out as my templating skill is very average!
I’m not using the DSMR integration but I have the Iotawatt energy monitoring system and integration.
In your power grid usage template why do you have the "float * 1000? My solar and consumption numebrs are in watts are you using this to convert a number? What number should this template produce watts or KW? this is what I get:

Hey there, how nice to see you are using my code! :slight_smile:

The x1000 is because the state of the DSMR production and consumption sensors is shown in kilowatts. So to use this in watts, I multiply by 1000. I use the float because the kilowatts are returned as a float (say 1024 watts is 1,024 kW) so to avoid any rounding during conversion. In my script, power_production_w and power_consumption_w are used in watts. So you can leave the *1000 out in lines 1 and 2. That should work!

2 Likes

Nice…

…but there is a spec for EV charging that sets the minimum charge current to be 6A - IEC 61851

Pretty sure the domestic ev charge points that offer solar excess charging always maintain the 6A minimum.

I have no idea what effects (if any) going under the minimum will have but maybe worth an investigate?

Good Luck

Good point. First of all: my wall box is from 2015 - before the IEC 61851 was conceived (I believe in 2017). That might be the reason it supports charge currents down to 0. Second: not all wallboxes are IEC 61851 compliant. As compliance is usually only implemented upon new product introduction and/or lifecycle changes, this might be a reason that a lot of chargers older than 2020 might still work with this script. Third: some chargers (like Alfen) only start charging with a 6A current but do allow for a current setting lower than that after initialization. I have no experience with this personally.

I’ve done some investigation as you suggested, and found out that through the API (so from Home Assistant) I can stop and start a charging setting with the current set to 0 amps, and the setting persists (so I can enforce a non-IEC compliant setting). I can set the amps to any number from 0 to 16 no matter the charging state.

If I start the session through the Tesla app, it quickly jumps to 6 amps and than drops to 5 amps, not allowing me to go any lower than that through the app. Nor does the app allow me to go any lower than 5 amps even if I can set it lower through the API by setting it through Home Assistant. The app only allows me to ramp up the amps (step = 1 amp) until it gets to 5, then from 6 I cannot go below 5. The number 5 seems odd from a compliance perspective, as the specifications demand a 6 amps minimum…

Although it seems to be a matter of compliance, I don’t expect any impact on the technical side. The testing that led to the spec states that the minimum should be enforced as lower charge currents might lead to relatively too high losses, although I find that quite patronizing - charging technology has vastly evolved, as the EVs used in the IEC test are Nissan Leaf (2015 model), Peugeot Ion (2011 model) and Renault Kangoo (2012 model). Which, too be honest, is not AT ALL what I would call representative for todays EV’s and charging technology (model Y losses at 240/16A are rated at 3,5% = 0,56A). So there you have it: my plea for updating the IEC charging spec.

Alternatively, you can refer back to the version of the automation that calls the script that switches off the charger below the minimum treshold and set the minimum to 6 amps (or if it does allow you to go any lower: calculate the value at what point you find the 0,5 amp loss relatively too high). :wink:

@dikkertjedap Thanks for confirming that… I did expect you were doing that but I now understand why you are using the multiplier.

So, update… I have had more success and I’m now using your latest automation but I’m experiencing strange behaviour which could be attributed to my power which is 3 phase but I’m not sure because the Tesla app still shows 0-16Amps for charging (eventhough thats across 3 phases e.g. if set to 16A it’s actually drawing 48Amps)
To test your automation I created a number helper to trigger the “charge on solar” automation and these are the values I got:

power_grid_usage  (w) Tesla Charging Amps (A)
0                              0
300                          1
600                          3
900                          6
1200                        10
0                           10 (no change)
-300                         8
-600                         5A

It seems to ramp up ok but not down? However I would need to divide the result by 3 in order to match the charger speed because of the 3 phase power
I’m not sure how to fix this so hoping you can help or maybe your seeing a similar thing?

I don’t understand exactly what I’m looking at here. Have you set the script variables according to your grid situation (correct voltage, min and max amperes?

I have set these variables:

  - variables:
      grid_usage: "{{ states('input_number.power_grid_usage') | float }}"
      max_charging_amps: "{{ state_attr('number.tess_charging_amps', 'max') | int }}"
      min_charging_amps: 0
      grid_voltage: "{{ states('sensor.tesla_wall_connector_grid_voltage') | float }}"

Because I was testing the automation in the evening I was using a “dummy” power_grid_usage so I could test the automation, and the table in my previous response were the results.

I assume your feed in is single phase 240V? I have 3 Phase 240V.

This is my Automation:

alias: "[Tesla] Charge on solar power"
description: ""
trigger:
  - platform: state
    entity_id: input_number.power_grid_usage
condition:
  - condition: state
    entity_id: binary_sensor.tess_charger
    state: "on"
  - condition: state
    entity_id: device_tracker.tess_location_tracker
    state: home
  - condition: state
    entity_id: input_boolean.smart_charge
    state: "on"
action:
  - variables:
      grid_usage: "{{ states('input_number.power_grid_usage') | float }}"
      max_charging_amps: "{{ state_attr('number.tess_charging_amps', 'max') | int }}"
      min_charging_amps: 0
      grid_voltage: "{{ states('sensor.tesla_wall_connector_grid_voltage') | float }}"
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ grid_usage > 0 }}"
        sequence:
          - service: switch.turn_on
            target:
              entity_id: switch.tess_charger
            data: {}
          - service: number.set_value
            target:
              entity_id: number.tess_charging_amps
            data:
              value: >
                {% set charger_power_draw = (states('number.tess_charging_amps')
                | int) * grid_voltage %} {% set charging_amps = ((grid_usage +
                charger_power_draw) / grid_voltage) | round(0, 'floor') | int %}
                {{ [max_charging_amps, charging_amps] | min }}
      - conditions:
          - condition: template
            value_template: "{{ grid_usage <= 0 }}"
        sequence:
          - service: number.set_value
            target:
              entity_id: number.tess_charging_amps
            data:
              value: >
                {% set deficit_watts = -1 * grid_usage %} {% set
                current_charging_amps = states('number.tess_charging_amps') |
                int %} {% set required_charging_amps = ((deficit_watts /
                grid_voltage) | round(0, 'ceil')) | int %} {% set
                updated_charging_amps = current_charging_amps -
                required_charging_amps %} {% if updated_charging_amps <
                min_charging_amps %}
                  0
                {% else %}
                  {{ [max_charging_amps, updated_charging_amps] | min }}
                {% endif %}
mode: single

Try changing your trigger from an input number to a sensor (as is mine). See if that helps.

Grat work, i was thinking doing something simmilar for myself.

Few questions :

As far as i understand you measure whether there is excess solar and if that changes you either stop charging or lower the amperage so you essentially keep the load as close to 0w as possible, correct ?

I have a smart meter in HA so i have the data. The problem i have seen previously is that controlling the amperage / start / stop charging from the Tesla API which essentialy what the addon does is very slow and not consistent like you have set the charge rate twice before it gets used. Do you experience that ?

Also how do you handle the mixture of the car beeing set to charge at a specific time or that the car should not charge when you plug it in and just wait till there is excess solar since Tesla does not have an option to manually control the charge, it’s either scheduled or by the SOC. How does that work for you ?

Also could you maybe share the full code now that you made some changes to it ?

What kind of EV charger do you have ? I have a Tesla Wall Charger.

Thanks for your enthousiasm!

This is exactly what the script does. For every 240 watts surplus available on the grid, I add another ampere to the charging power (which corresponds to 240 volts x 1 ampere = 240 watts) and as soon as the grid power drops below 0, I subtract an ampere for every 240 watts needed to get to or above 0 watts available on the grid.

I’m using the HACS Tesla custom integration, and I don’t experience any lag whatsoever.

I haven’t set any (non-)charging hours, so I’m not familiar with how thats handled. As you can see in the automation, as soon as the charger is connected during the day, at home, it immediately asks me if I want to use smart charging (using excess solar power production). If connected in any other setting (so after dawn or away from home), it just starts charging at regular (full) power setting. That works perfectly.

All full code is available! Final version of the automation is found in post 8 of this thread. The script for switching off the charger as suggested in post 4 can be discarded.

I have an older evbox.com charger (something like a single-charger wall-mounted version of the BusinessLine charger).

Thank you,

Ok so few more questions :

  1. binary_sensor.charger is an entity from Tesla HACS add-on to check if the charger is connected ?
  2. sensor.power_grid_usage Is this sensor a positive value in Watts when there is surplus e.g you are feeding to grid and negative when you pull energy from the grid ?

Generally spoken: yes, it shows the connection state of the charger (car side, so not the wall box!). It’s a little more comprehensive, because when you look at the sensor in the development tools section of Home Assistant, it shows some more detailed attributes like for instance the charging state (‘charging’, ‘complete’ etc.), the type of cable that’s connected to the plug, wether a fast charging point is connected and some more.

That’s absolutely correct. It shows the value of two separate sensors as one by subtracting the actual power consumption from the actual power production, which in my case are measured by separate sensors. It’s not a critical sensor and you can do this math inside the charger automation, but this just simplifies things a bit (and I have a nice needle sensor to show on my dashboard :wink: )

When I have some more time during the summer holidays I will try to convert my automation into a blueprint to use for others.