Optimizing use of unused Solar Power to charge a Tesla

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