Optimizing use of unused Solar Power to charge a Tesla

Quick Update:
The last script I posted above is working flawlessly. Quickly changing power, like a windy day with a lot of clouds might lead to a few tiny over or under compensations, but that is simply down to the fact that the Tesla can’t adjust the charging amps within seconds.
It requires only one Sensor reading you entire house input/output and the Tesla Custom integration.

1 Like

Just wondering, isn’t it more logical/readable to replace *0.0033 *-1 with your (negative) mains voltage reading for example /-240? In my case it’s around 235 but sadly the P1 meter doesn’t provide this value to HA.

You can calculate it any way you like…as long as the result is the same…:wink:

At the risk of being burned for heresy, I thought I’d pose a question: Is exactly matching our excess solar to our charging rate even something we want to do?

Keep in mind that I’m doing the same thing, developing my own script that balances my charging with my solar production the way I want, but I’ve lately asked myself what the point of this is for someone like me with monthly NEM aggregation.

My understanding is that my electrical utility, PG&E, under NEM2, tracks the balance of my electrical consumption and production and sums them by time-of-use (“peak”, “off-peak”, and “partial-peak”) and by month. What that tells me is that, instead of trying to get my minute-to-minute consumption/production to zero out, I should be doing that for the month. I should be tracking the total amount of energy I’ve given to PG&E this month for the current TOU I’m in and, if I’ve got a 200kWh surplus for that TOU, I should just let my charger go at max-rate. Not only that, but I should maybe be adjusting that for TOU (so, if I’ve got a 200kWh surplus for the month for off-peak but only a 10kWh surplus for the late-afternoon partial-peak, then maybe I want to dial the charging back when the time ticks over into the partial-peak time).

Am I missing something here? I mean, with NEM3 around the corner (and the potential for “buy all/sell all”, where the production/consumption will be tracked down to the minute or second), there might be a need for scripts like these to exactly balance things, but, for right now, why aren’t we just tracking the monthly total?

Well, your usecase is very different to mine, since we don’t have “Nem” (I assume net metering?) here in Germany.

For me the equation is:

I get 8.2ct for every kWh I export to the Grid
I pay (currently) 36ct for every kWh I buy from the Grid

So for me the benefit of putting excess solar power into the car is easily calculated in €€€ :wink:

1 Like

Edit : Note : I have done some edits in the post below as I pasted old versions of the scripts.

Before I say anything, I need to acknowledge that I am pretty new to this and not really a programmer. But also thanks for CommanderROR and others for there posts and outline of there solutions as that has helped me a lot.

However, I am a bit anal about these things, and we have pretty punishing Peak usage rates, so I was keen to get something going that absolutely minimises charging for mains (importing). And I noticed that CommandersROR approach was wobbling into the importing power a little more than I really liked, and it was happening at times when I would have expected it to be correcting itself slower than I would have throught. Mind you, probably notice this when others might not, because I have grid meter that updates every second, and I recalcuate and set the rate every 2 seconds. If your meter is less granular, there are limits on what can be achived and you might not notice.

On investigations I suspect there are 2 explanations for this (but again, I am not an expert and hopefully someone more knowledgeable here can clarify and correct) :-

  1. I think there might be an issue with using “number.tai_daishar_charging_amps” in the calculations. While we can set this, and it appears to update quickly at the Tesla and the actual charge that is drawn, it appears to me in my testing that when you read this back, it is slow to update for reasons I don’t understand (I assume something to do with it is a “number…” which is part of the Tesla integration primarily used for setting something and it is only read back to HA when the integration polls the Tesla and reads it back which defaults to 660 second in my integration). I assume that this is affecting the calculation as it is often based on the old reading unless I am missing something??? So I suspect not ideal to use in the calculation because of the slow “re-read” update. I think you can improve this with a Configuration option in the integration to have it poll every say 66 sec rather than 660 sec. But there are limits.

  2. I suspect you are better to read all values as integers and makes sure each is rounded down, so when you add them together, you don’t get any rounded up to a value that has you importing (not sure if this is an issue or not).

The third area :-

  1. … I wanted to refine is not around the calculation, but around the implementation. I have noticed that when chargin power is low (eg 1 or 2A), the km range does not increase much, and in some cases, range will actually go backwards. This is particularly prominant at the end of the day when the sun is low and there is little to no charging, but the km range goes back in a noticable way. I assume this is because while it is charging, the car is using more power than we are putting in if we are only charging at 0 - 500w. Seems to be more than say sentury mode might consume so it is not insignificant on marginal days. So I wonder if a fact is how much I am changing the changing the charging rate. In my case, I am doing this every 2 seconds. So my thinking is to improve the implementation, so that instead of setting the charge rate every 2 seconds no matter what, only set the charge rate when the current changes which is a LOT less often usually. Again, this might be a waste of time, because that bit might not be using much power and the power might be burned up running the charger or just staying online.

In any case, because of the above, I went back to my previous implementation and improved that to I think address 1 and 2 above. And I have addressed most of 3. But I could probably make it better, and not require an additional meter on the tesla charger if someone can help me with some sort of global variable so I can set this with every change, and test this to see if it needs changing at the next poll.

So below I will outline what I have done. Some of this will be redundant and I am sure can be done more elegantly as I am really a “copy and paste” programmer who does not really understand what I am doing and better possibilities.

The 1st thing I have done is create a template sensor in the configuration.yaml which measures the free solar and converts that to Amps. A few things to not about below :-

  1. sensor.Modbus_Grid_Power_SUM is a Iammeter meter on the grid which updates every second (I totally recommend these meters, because they are well priced, accurate, can be read once a second and also have there own rich interface and very flexible).
  2. sensor.modbus_plugin1_current is also an Iammeter meter I have which measures power, current, voltage etc on the charger and is much faster updating so better way to read the current.
  3. input_number.freesolar_fudge_factor could be taken out if you want. But it is a helper I created for 2 reasons. 1) so if I set this to -1 as I typically do, it targets a number below zero so I further reduce the times grid import happens. You could set a bigger negative number for more margin if you wanted, and 2) I use this so I can simulate more marginal conditions for testing.
  4. sensor.Modbus_Grid_Voltage_C is my voltage at the grid connect for the phase the charger is on, and used to determine the free current from the power. In other implementations above, they seem to do this by using the nominal voltage and multiplying by something like 0.0033 though for 230v technically that would be 1/230 = 0.00435). But if you don’t have some way of reading voltage, this is not a bad cheat. So modify as you please.
  - sensor:
      - name: "freesolar_tesla_charge_current_fixed"
        unit_of_measurement: "A"
        state: >
          {% set grid_power_sum = states('sensor.Modbus_Grid_Power_SUM') | float %}
          {% set grid_voltage_c = states('sensor.Modbus_Grid_Voltage_C') | float %}
          {% set plugin1_current = states('sensor.modbus_plugin1_current') | int %}
          {% set freesolar_fudge = states('input_number.freesolar_fudge_factor') | int %}
          {% set tesla_charge_current = ((grid_power_sum *-1 // grid_voltage_c) + plugin1_current + freesolar_fudge ) | int %}
          {% if tesla_charge_current < 0 %} 0
          {% elif tesla_charge_current > 15 %} 15
          {% else %} {{ tesla_charge_current }}
          {% endif %}

Note, in the above I use “int” to make sure I am rounding current down, and also using // to make sure I am always rounding down in the calculation.

I use this sensor to have input into an automation :-

alias: GreyGhost - Charge with excess solar while at home during daylight v2 (Beta)
description: ""
trigger:
  - platform: time_pattern
    seconds: /1
condition:
  - condition: state
    entity_id: device_tracker.greyghost_location_tracker
    state: home
  - condition: sun
    before: sunset
    after: sunrise
    before_offset: "-01:40:00"
    after_offset: "00:40:00"
    enabled: true
  - condition: state
    entity_id: switch.greyghost_charger
    state: "on"
action:
  - if:
      - condition: template
        value_template: >-
          {{ states('sensor.freesolar_tesla_charge_current_fixed' ) | int !=
          states('sensor.modbus_plugin1_current' ) | int }}
    then:
      - service: script.tesla_set_charge_rate_v2_7_freesolar
        data: {}
mode: single

This only calls the script to set the Tesla charge rate if the charge current needs to change which significantly reduces the number of times we are setting the charge rate from once every 2 seconds, to only when the charge rate changes which way less often.

Note, I have a bunch of conditions that suit my location you can see above. eg the Sun condition is to make sure this only runs when the Sun is likely to be high enough to charge the car. At other times if someone has turned the charger on, I don’t want to override this as I assume they have set this manually on purpose. At some stage, I will probably add another condition so I can create a button to make it simple to override this so the charge rate can be set manaully in the daytime if that is wanted for some reason (ie maximum charge speed).

The script to set the charge rate becomes simple :-

alias: Tesla set charge rate v2_7 freesolar
sequence:
  - alias: set charger Rate
    service: number.set_value
    data:
      value: "{{ states('sensor.freesolar_tesla_charge_current_fixed') | int }}"
    target:
      entity_id: number.greyghost_charging_amps
description: set Charger rate
mode: single

I think this is working reasonably well. And keeps everything throttled so very little charging drawn from the grid. The only thing drawn from the grid is when there is a sudden big reduction in solar (ie cloud coming over) or big load turned on in the house, and this can lead to a draw for typically 2-4 seconds and sometimes up to 7-8 seconds at the higher. I assume this is due to delays in calculating, communicating and setting the Tesla charge rate and it ramping down the meters recording than change.

In terms of improvement, I would prefer to use some sort of global variable that holds the value of the last charge current change instead of sensor.modbus_plugin1_current (which might be a little delayed), just in case sensor.modbus_plugin1_current is running a bit behind. But in truth, it is working well and fast enough that it probably does not make a difference. But if someone knows how to create and set this global variable I might give that a try.

The other downside of my approach, it needs another fast meter on the Tesla charger (ie sensor.modbus_plugin1_current). But again, if someone knows how to create and set this global variable, it would alieviate the need for a meter, and I assume this would be easy to implement. It is just my lack of knowledge on these things.

Anyway, all input, improvements and corrections welcomed.

4 Likes

I should add, I have other automations to turn the Tesla charger on at a time there migth be enough solar to charge, and off at the end of the day when I know there is not enough solar to charge.

For complete disclosure I also have some other additional automations to do the following :-

  1. I have created a “Min Charge Threshold” helper that allows the easy setting of a value in km that I want charged to overnight.

  2. At 10pm (My off peak tarrif rate start time), if range is below this “Min Charge Threshold”, it turns the charger on, sets the charge current to 15a (I needed to add a delay to this, because it sometimes did not work if I turned it on and changed this straight away, I suspect because setting the charge current can be a problem if the car is not woken up and turned on which might take a some time???)

  3. I have automation that then turns the charger off, once I get to the “Min Charge Threshold”

Generally I leave the Min Charge Threshold" set to about 270km of range which is enough for the typical days driving, plus a safety margin for unforsean trips etc. But it is a quick tweak in HA to pump this up to full charge when I need max range, or down because I know I am at home tomorrow and the Sun can do its thing. But mostly I don’t need to do anything than plug in to charger when the car gets home, and possibly manually turn the charger off if I plug in after the solar charging has finished, but before off peak time. But I assume I could also automate that as well if I get around to it.

2 Likes

Many thanks to all who have submitted to this post. I managed to get my combination of hardware/software set up yesterday and it works as well as I can have expected. I’m more familiar with creating automations inside node-red but got stuck at passing the variable amps to the Tesla api as the node red node can only send a number.

FYI my hardware is Tesla M3/Tesla Powerwall/Fronius Inverter/Meter/Openevse wall connector

Here is my version,

template:
  - sensor:
  # Template sensor for calculating the amount (amps) of excess solar to charge the car
    - name: "excesssolar_tesla_charge_current_fixed"
      unit_of_measurement: "A"
      state: >
        {% set grid_power_sum = states('sensor.apf_grid_entity') | float %}
        {% set grid_voltage_c = states('sensor.voltage_ac_phase_1_fronius_meter_0_192_168_100_32') | float %}
        {% set plugin1_current = states('sensor.openevse_charging_current') | int %}
        {% set freesolar_fudge = states('input_number.tesla_amps_fudge_factor') | int %}
        {% set tesla_charge_current = ((grid_power_sum // grid_voltage_c) + plugin1_current - freesolar_fudge) | int %}
        {% if tesla_charge_current < 0 %} 0
        {% elif tesla_charge_current > 32 %} 32
        {% else %} {{ tesla_charge_current }}
        {% endif %}  
        
input_number:
  tesla_amps_fudge_factor:
    name: Tesla Amps Fudge Factor
    initial: 1
    min: 0
    max: 5
    step: 1

Minor differences are:

  1. My EVSE is capable of 32A - the ‘if’ statement is amended to extend the range

  2. My power to grid variable is “opposite” so I removed the *-1 calculation

  3. I left in the fudge factor but as I have a Powerwall battery it does not really matter as any transitory power usage in the house or a cloud obscuring the solar is taken up by a temporary draw on the battery

And the automation:

alias: Tesla - Charge with excess solar
description: Vary amps depending on excess solar generation
trigger:
  - platform: time_pattern
    seconds: /1
condition:
  - condition: state
    entity_id: device_tracker.heart_of_gold_location_tracker
    state: home
  - condition: sun
    before: sunset
    after: sunrise
    before_offset: "01:30:00"
    after_offset: "01:30:00"
  - condition: state
    entity_id: switch.heart_of_gold_charger
    state: "on"
  - condition: state
    entity_id: input_boolean.car_charge_override
    state: "off"
action:
  - if:
      - condition: template
        value_template: |2-
                    {{ states('sensor.excesssolar_tesla_charge_current_fixed' ) | int !=
                    states('sensor.openevse_charging_current' ) | int }}
    then:
      - service: script.set_telsa_charging_amps
        data: {}
mode: single

I’ve added another condition “input_boolean.car_charge_override” (see below) as you suggested in your last post that there will be times when you just want to charge at the maximum rate regardless of energy source. I’ve yet to fully implement/test this as I’ve discovered that trying to set the amps to anything above 16A doesn’t always seem to work. Possibly an issue of car being asleep and/or until the charger is connected and on.

Just 2 minor syntax question from the code above.

  1. My ‘value template’ has |2- at the end of the line whereas yours has >- which I’m more familiar with?
  2. I got a bit confused as I originally set the seconds = “1” thinking this was once/second whereas your code is /1 which is the correct notation (I think “1” means at that second every minute)?

Below is the input_boolean set up in configuration.yaml

input_boolean:
# Create button for over-riding charging amps variations
  car_charge_override:
      name: Car Charge Override
      icon: mdi:ev-station
      initial: true

This is the simple script to do this function:

alias: Tesla set charge rate to 32A
sequence:
  - alias: set charger rate to 32A
    service: number.set_value
    data:
      value: "32"
    target:
      entity_id: number.heart_of_gold_charging_amps
description: Set Charger Rate
mode: single

Anyway at the risk of boring everyone to death I’ll stop here! Thanks again to the contributors to this post.

1 Like

I’ve done a few iterations of this as well, here’s my charging automation with Solar + Load balanced + Off peak charging, with boolean toggles to switch modes. Few details about my setup:

  • charging from a regular 230V socket for now, 5-13A dynamic range
  • Huawei inverter + battery + smart meter
  • HomeWizard WiFi P1 Meter (optional, found it slightly more reliable than the Huawei integration)

One addition missing here is an individual kWh meter for the Tesla charger. Currently it’s inferred by combining the overall house consumption and using the amps + voltage from the Tesla integration.

My main 2 observations were:

  1. To get the combination of solar + load balanced + off peak working, the main trick was to come up with a single “Desired” amps you want to send to your Tesla. This made life much easier tbh compared to separate automations tbh. Once you have this number, you trigger a single automation whenever the desired amps changes to update.
  2. Due to polling, the actual charging amps you get from the Tesla API can be slow / outdated. To get around this, I use a variable (sensor.tesla_automation_charging_amps) which is updated whenever the Desired amps is set (see the script that’s called) or whenever I get an actual update from the Tesla API. This way you can get a more real-time view of how many amps are currently going to your car.

Required HACS integrations:

On top of this I use the Huawei Solar integration from HACS.

This is the entire package, barring some id changes you should be able to put this in packages/tesla.yaml:

# Tesla solar + load balance + off peak charging
automation:
  - alias: Tesla charging amps update
    description: ""
    trigger:
      - platform: state
        entity_id:
          - sensor.charger_power
        attribute: charger_amps_actual
    condition:
      - type: is_plugged_in
        condition: device
        device_id: <tesla_device_id>
        entity_id: binary_sensor.charger
        domain: binary_sensor
      - condition: device
        device_id: <tesla_device_id>
        domain: device_tracker
        entity_id: device_tracker.location_tracker
        type: is_home
    action:
      - service: variable.set_entity
        data:
          entity: sensor.tesla_automation_charging_amps
          value: "{{ min(state_attr('sensor.charger_power', 'charger_amps_actual'), 13) }}"
    mode: single
  - alias: Tesla - Charging (load + solar + off peak)
    description: ""
    trigger:
      - platform: state
        entity_id:
          - sensor.tesla_charging_desired_amps
      - type: plugged_in
        platform: device
        device_id: <tesla_device_id>
        entity_id: binary_sensor.charger
        domain: binary_sensor
      - platform: device
        type: turned_on
        device_id: <tesla_device_id>
        entity_id: switch.charger
        domain: switch
    condition: []
    action:
      - service: script.load_balanced_tesla_charging
        data: {}
      - delay:
          hours: 0
          minutes: 0
          seconds: 15
          milliseconds: 0
    mode: queued
    max: 15

script:
  - alias: Load balanced Tesla charging
    sequence:
      - condition: device
        device_id: <tesla_device_id>
        domain: device_tracker
        entity_id: device_tracker.location_tracker
        type: is_home
      - type: is_plugged_in
        condition: device
        device_id: <tesla_device_id>
        entity_id: binary_sensor.charger
        domain: binary_sensor
      - if:
          - condition: numeric_state
            entity_id: sensor.tesla_charging_desired_amps
            above: 4
        then:
          - if:
              - type: is_not_charging
                condition: device
                device_id: <tesla_device_id>
                entity_id: binary_sensor.charging
                domain: binary_sensor
            then:
              - type: turn_on
                device_id: <tesla_device_id>
                entity_id: switch.charger
                domain: switch
          - service: number.set_value
            data:
              value: "{{ states('sensor.tesla_charging_desired_amps') | int(0) }}"
            target:
              entity_id: number.charging_amps
          - service: variable.set_entity
            data:
              entity: sensor.tesla_automation_charging_amps
              value: "{{ states('sensor.tesla_charging_desired_amps') | int(0) }}"
        else:
          - type: turn_off
            device_id: <tesla_device_id>
            entity_id: switch.charger
            domain: switch
        enabled: true
    mode: single

input_number:
  load_balancing_grid_limit:
    name: Load Balancing Grid Limit
    initial: 3500
    min: 2500
    max: 8000
    step: 500
    unit_of_measurement: W
    icon: mdi:scale-balance

input_boolean:
  load_balancing_grid:
    name: Load Balancing Grid Toggle
    initial: true
    icon: mdi:scale-balance
  ev_charging_solar:
    name: EV Solar Charging Toggle
    initial: false
    icon: mdi:solar-power
  ev_charging_off_peak:
    name: EV Off Peak Charging Toggle
    initial: true
    icon: mdi:home-clock

variable:
  tesla_automation_charging_amps:
    value: 0
    restore: true
    domain: sensor
    attributes:
      state_class: measurement
      unit_of_measurement: A

binary_sensor:
  - platform: workday
    country: <2_letter_country_id>
  - platform: tod
    name: Off peak hours
    after: "22:00"
    before: "07:00"
    unique_id: off_peak_hours

template:
  - binary_sensor:
    - name: Off peak
      unique_id: off_peak
      icon: mdi:weather-night
      state: "{{ is_state('binary_sensor.workday_sensor', 'off') or is_state('binary_sensor.off_peak_hours', 'on') }}"
  - sensor:
    - name: "Battery Grid Charge power"
      unique_id: battery_grid_charge_power
      unit_of_measurement: "W"
      state_class: measurement
      device_class: power
      state: >
        {% set battery_charge_discharge_power = states('sensor.battery_charge_discharge_power') | int(0) %}
        {% set inverter_input_power = states('sensor.inverter_input_power') | int %}
        {% if inverter_input_power <= 0 and battery_charge_discharge_power >= 0 %}
        {{ battery_charge_discharge_power }}
        {% else %} 
        0
        {% endif %}
    - name: "House power consumption"
      unique_id: house_power_consumption
      unit_of_measurement: "W"
      state_class: measurement
      device_class: power
      state: >
        {% set power_meter_active_power = states('sensor.power_meter_active_power') | int %}
        {% set inverter_active_power = states('sensor.inverter_active_power') | int %}
        {% set battery_grid_charge_power = states('sensor.battery_grid_charge_power') | int %}
        {% set home_consumption = inverter_active_power - power_meter_active_power + battery_grid_charge_power | int(0) %}
        {{ max(home_consumption, 0) }}
    - name: "Load Balancing Grid - Excess"
      unique_id: load_balancing_grid_excess
      unit_of_measurement: "W"
      state_class: measurement
      device_class: power
      state: >
        {% set load_balancing_grid_limit = states("input_number.load_balancing_grid_limit") | int(3500) %}
        {% set power_meter_active_power = states('sensor.p1_meter_active_power') | int(0) %}
        {{ load_balancing_grid_limit - power_meter_active_power }}
    - name: Tesla - Home Charging Power
      unique_id: tesla_home_charging_power
      unit_of_measurement: "W"
      state_class: measurement
      device_class: power
      state: >
        {% if is_state('device_tracker.location_tracker', 'home') and is_state('binary_sensor.charging', 'on') %}
          {% set charger_volts = max(state_attr('sensor.charger_power', 'charger_volts') | int(230), 220) %}
          {% set charger_amps_actual = states('sensor.tesla_automation_charging_amps') | int(0) %}
          {{ charger_volts * charger_amps_actual | int(0) }}
        {% else %} 
          0
        {% endif %}
    - name: "Tesla - Desired Amps (off peak + load balanced + solar)"
      unique_id: tesla_charging_desired_amps
      unit_of_measurement: "A"
      state_class: measurement
      device_class: power
      state: >
        {% if (is_state('device_tracker.location_tracker', 'home') and is_state('binary_sensor.charger', 'on'))
          and ( states("sensor.battery") | int < states("number.charge_limit") | int )
          and ((is_state('input_boolean.ev_charging_off_peak', 'on') and is_state('binary_sensor.off_peak', 'on')) or is_state('input_boolean.ev_charging_off_peak', 'off'))
        %}
          {% set max_tesla_charging_amps = state_attr("number.charging_amps", "max") | int(13) %}
          {% set min_tesla_charging_amps = 5 %}
          {% if is_state('input_boolean.ev_charging_solar', 'on') %}
            {% set house_power_consumption = states('sensor.house_power_consumption') | int %}
            {% set inverter_input_power = max(states('sensor.inverter_input_power') | int(0), 0) %}
            {% set tesla_home_charging_power = states("sensor.tesla_home_charging_power") | int(0) %}
            {% set free_watts =  max(inverter_input_power - (house_power_consumption - tesla_home_charging_power), 0) %}
            {% set free_amps = min(max(free_watts / 1000 * 4.2, 0), max_tesla_charging_amps) %}
            {% if free_amps >= min_tesla_charging_amps %}
              {{ free_amps | round(0, 'floor') }}
            {% else %}
              0
            {% endif %}
          {% elif is_state('input_boolean.load_balancing_grid', 'on') %}
            {% set load_balancing_grid_excess = states("sensor.load_balancing_grid_excess") | int(0) %}
            {% set tesla_home_charging_power = states("sensor.tesla_home_charging_power") | int(0) %}
            {% set free_watts = load_balancing_grid_excess + tesla_home_charging_power %}
            {% set free_amps = min(max(free_watts / 1000 * 4.2, 0), max_tesla_charging_amps) %}
            {% if free_amps >= min_tesla_charging_amps %}
              {{ free_amps | round(0, 'floor') }}
            {% else %}
              0
            {% endif %}
          {% else %}
            max_tesla_charging_amps
          {% endif %}
        {% else %} 
          0
        {% endif %}
5 Likes

This looks to be exactly what I am looking for. A couple of basic questions…
I have an enphase solar system and have an entity available called grid export_power (in watts), so it looks like it would replace your sensor.poweropti_aktuell field. I also have a Tesla Model X and have installed the Tesla custom integration using a token from teslafi. com. This looks to be an excellent and efficient way to control excess solar into the Tesla. So if I replace tai_daishar with my Tesla’s name, it looks like its edited and I also have only 1 phase power. So, what do I do with the script ? How often should I run it ?

How do I limit it to 13 amps or so ?

1 Like

Hi there!

The script you posted is for 1 phase power (230V though since I am in Germany) and it is already limited to 13 Amps. So if you replace the sensor and the car you are ready to go. To make this work you need the rest of the automations though…you can find them all in this thread. Change the names for sensor and car and it should work.

Btw…you can test the script in the Dev Tools - Template Editor to check before you deploy

I am loving it. I did have to make some changes. Since I have an Enphase solar system (no battery), I have a term for grid_import_energy and grid_export_energy. I found that I needed to remove the “*-1” from your script. I was also able to subtract out the power that I was importing, to better tune the algorythm. Behold:

**`alias: Solar Scraper 2
sequence:

  • if:
    • condition: sun
      after: sunrise
      before: sunset
      then:
    • service: number.set_value
      data:
      value: >-
      {{ ([0, (states(‘sensor.grid_export_power’) |
      float(0)-states(‘sensor.grid_import_power’) | float(0)) *0.0033 +
      states(‘number.baller_charging_amps’) |float(0) , 12] | sort)[1] |
      round(0) }}
      target:
      entity_id: number.baller_charging_amps
  • delay:
    hours: 0
    minutes: 2
    seconds: 0
    milliseconds: 0
    mode: single
    icon: mdi:battery-charging-60
    `**

I ended up writing an automation that waits 1 hour 30 until after sunrise, then calls this script every 2 minutes if the car is plugged in. I ended up re-wiring my car charger to 240V from 120V to be more capable of using all the power that my recently expanded solar system can provide. Its tracking really well. Currently only pulling 44 watts from the grid.

I DID have an issue, as the script would quietly bomb out if it tried to set a charge rate above the max of 13 amps. In fact, I had to hard code mine to 12 amps to get it to solidly run. I can now expand it to 20 amps, with the doubling of my voltage. Nice.

1 Like

Glad it works for you! It has occasional glitches for me, especially when it goes down to the low amp range since setting 1 or 2 amps doesn’t always sticky but generally runs reasonably well.

I can’t believe no one said anything about this? Looks really nice.
Did you write this in 2017? Am I getting this right? your post say Jan17 but it’s after Dec 22 posts…
Do you still use it or have you updated it since then? :wink:
I have 2 Tesla’s but I’m guessing it should work if I duplicate the code all the times a car is taken into account.
What do you mean by <tesla_device_id>?
What is load balance though? I’m guessing that’s a power wall.
I’m guessing I can’t use your code if I don’t have one.

Thanks

Just be aware, that if you enphase system is the same as mine, this is only reporting power every 5 minutes. If this is the same for you, there is probably not much point in running your script more than once every 5 minutes. That is why I don’t use Enphase for my reading for grid usage, and instead use Iammeters because they can give me 1 second granulatity which enable much faster and closer matching.

Also be aware that you report it tracking very well. But if you only have Enphase reporting every 5 minutes, that will be partically as a result of the low granulatity of the enphase monitoring. But for a lot of people it will be more than good enough.

I think you are getting Jan 17 2023 confused with the month of Jan in 2017.

If you use the GUI to create the automation, and in the Actions select you Tesla car name and action all will be done for you and you will not have to worry about the <tesla_device_id>. That will pull all the relevant Device IDs (though if you stick to the GUI, it is all hinden under the covers of the GUI and you don’t need to worry about it).

If you want to do it via CLI, you can use this technique of the GUI, and then change to CLI and you will see you tesla_device_id which is a long number and you can us that to duplicate in your code where needed.

There is probably a better way, but you might find it easier to try and implement some of these scripts using the GUI as it does connect a few dots like this (takes a bit of guessing and enterpreting to find the right things to select, but it works for me).

From my experience of HA, the GUI works pretty well, though there are some limits. I am sure there are people who only do CLI. But for us non programmers, the GUI can help us with the syntax etc and is invaluable. I suspect the reason a lot of people post here in CLI is because that is easy and efficient and duplicatable that posting CLI screen shots. But my development is done as a combination of CLI and GUI. But all postings here would be with the final CLI code.

hi @swainstm - could you share the three other automations your using?

For those of you coming to this new, the below scripts go with the solution I outlined in Nov 22 you will see further up in the thread, but answering @aziwa questions for my other automations.

“Min Charge Threshold” is a helper I created under “Helpers” so you can set that to whatever you want.

The following automation then turned the charger on in my offpeak time if range is below the threshold :-

alias: GreyGhost - Turn on Charger at 10pm if below Min_Charge_Threshold
description: ""
trigger:
  - platform: time
    at: "22:00:00"
condition:
  - condition: state
    entity_id: device_tracker.greyghost_location_tracker
    state: home
  - condition: template
    value_template: >-
      {{(states.sensor.greyghost_range.state | int) <=
      (states.input_number.min_charge_threshold.state | int)}}
action:
  - type: turn_on
    device_id: <xxxxxxx device_id>
    entity_id: switch.greyghost_charger
    domain: switch
  - delay:
      hours: 0
      minutes: 2
      seconds: 0
      milliseconds: 0
  - device_id: <xxxxxxx device_id>
    domain: number
    entity_id: number.greyghost_charging_amps
    type: set_value
    value: 15
mode: single

The following automation turns the changer off once it reaches the threshold :-

alias: GreyGhost - Turn off charger when we get to Min_Charge_Threshold
description: ""
trigger:
  - platform: template
    value_template: >-
      {{(states.sensor.greyghost_range.state | int) >=
      (states.input_number.min_charge_threshold.state | int)}}
condition:
  - condition: state
    entity_id: device_tracker.greyghost_location_tracker
    state: home
  - condition: time
    before: "06:00:00"
    after: "22:00:00"
  - condition: sun
    before: sunrise
    before_offset: "24:20:00"
    enabled: false
action:
  - type: turn_off
    device_id: <xxxxxxx device_id>
    entity_id: switch.greyghost_charger
    domain: switch
mode: single

To Auto turn off charger when plugged in at peak or shoulder times :-

alias: GreyGhost - Auto turn off charger when plugged in at peak or shoulder times
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.greyghost_charger
    to: "on"
    from: "off"
condition:
  - condition: state
    entity_id: device_tracker.greyghost_location_tracker
    state: home
  - condition: sun
    after: sunset
    after_offset: "-01:40:00"
  - condition: time
    before: "22:00:00"
    after: "00:00:00"
action:
  - type: turn_off
    device_id: <xxxxxxx device_id>
    entity_id: switch.greyghost_charger
    domain: switch
mode: single

To go along with this, I also have an automation that makes sure the charger turns itself off if it is plugged in outside of peak/shoulder times if charge is above the threshold :-

alias: GreyGhost - Auto turn off charger when plugged at night outside of peak
description: >-
  Auto turn off charger when plugged at night outside of peak and above
  threshold
trigger:
  - platform: state
    entity_id:
      - binary_sensor.greyghost_charger
    to: "on"
    from: "off"
condition:
  - condition: state
    entity_id: device_tracker.greyghost_location_tracker
    state: home
  - condition: or
    conditions:
      - condition: time
        before: "00:00:00"
        after: "22:00:00"
      - condition: sun
        before: sunrise
        before_offset: "00:30:00"
  - condition: template
    value_template: >-
      {{(states.sensor.greyghost_range.state | int) >=
      (states.input_number.min_charge_threshold.state | int)}}
action:
  - type: turn_off
    device_id: <xxxxxxx device_id>
    entity_id: switch.greyghost_charger
    domain: switch
mode: single

Very much related to this is automation to turn the charger on in the morning when the sun comes up and we might be in the zone to be producing enough power to be exporting (adjust for your own circumstance, and make sure these adjustments align to the settings in the automations above) :-

alias: GreyGhost - Turn on charger at sunrise +40m
description: ""
trigger:
  - platform: sun
    event: sunrise
    offset: "00:40:00"
condition:
  - condition: state
    entity_id: device_tracker.greyghost_location_tracker
    state: home
action:
  - type: turn_on
    device_id: <xxxxxxx device_id>
    entity_id: switch.greyghost_charger
    domain: switch
  - device_id: <xxxxxxx device_id>
    domain: number
    entity_id: number.greyghost_charging_amps
    type: set_value
    value: 0
mode: single

And likewise to turn the charger off in the evening when you are unlikely to have enough solar to do any changing :-

alias: GreyGhost - Turn off charger 1:40 before sunset
description: ""
trigger:
  - platform: sun
    event: sunset
    offset: "-01:40:00"
condition:
  - condition: state
    entity_id: device_tracker.greyghost_location_tracker
    state: home
action:
  - type: turn_off
    device_id: <xxxxxxx device_id>
    entity_id: switch.greyghost_charger
    domain: switch
mode: single

Adjust all of this to suit your own circumstance based on spare solar you have and what times etc etc etc.

Further to the post above, I have noticed a change in behaviour in the last day which cases updates from the Tesla integration to be quite delayed. Some time ago, I changed the “Seconds between polling” from the default of 660 seconds to 66 seconds, and it has been running like the successful all this time. It means HA learns about changes within a minute or so, and is more quickly able to respond to events like plugging in the charger (which starts the charging) and turning it off when needed. But I suspect something has changed in the last day, and now it takes more like 10-20 minutes or so to pick up these events and respond to them which is not ideal.

Another issue related to this I noticed this morning when the charger came on, it immediately started charging at 2.8kW before I started exporting solar. Really my script should have throttle charging current to 0 under these conditions. However, that did not happen for 16 minutes. On investigation, it appears that the HA was confused about the “switch.greyghost_charger” thinking the charger was off (despite the fact that the script above did turn it on, and it was on). But if HA is confused about this, the script that matches charger output to solar output will not be running, because “switch.greyghost_charger” being on is one of the conditions for that to run. I think the explanation for the above is related to the a delay between setting the entity and this value being reflected when you read it back. I have checked back through the history, and this happening seems to be rare (I have gone back about a week, and I have only seen it this once). So there might be other explanations??

I suspect a small improvement to reduce the impact of the above, is to add an action to the automation above to set the charging current to 0 when it is turned on. But I have not posted that because I have not tested it.

I don’t know what triggered this change, but I would be very suspicious that it might be related to the update to v3.11.0 which happening in the last day or so.

Has noticed a delay in the integration updating despite have “Seconds between polling” set to 66 seconds?

Further to the post above, it looks like there has been changes to the Tesla integration I assume in 3.11.0 which has affected how quickly certain switches and sensors are updated which has reduced the immediacy of updates from some of the automations above.

For more info see Car Status stays on "Connected" but it isnt · Issue #556 · alandtse/tesla · GitHub which is likely the same issue I am having.