This is about diverting your solar power to charge an EV and tracking excess production so it goes to the car instead of getting exported or stored in the main batteries.

After getting rooftop solar, I got my hands on an OpenEVSE unit and installed it my garage, the final goal was to precisely control the charge current in harmony with solar production and state of charge of the house batteries. After some time on and off working on this, I culminated the project automating the charge current based on excess solar. Before we had to manually adjust the current or adjust the powerwall settings to avoid wearing down the batteries while charging the car. This is specially annoying in cloudy days where production varies a lot.

I made some changes to the OpenEVSE divert logic since it wasn’t doing what I wanted. I pushed the changes to the “new_divert” branch of my OpenEVSE WiFi fork in github: OpenEVSE WiFi, new divert

I made a small daemon in Python to collect powerwall metrics and publish them to the MQTT broker in my house: powerwall_mqtt

OpenEVSE gathers the readings for the divert logic from the MQTT feed from the Tesla Energy Gateway (powerwall).

The goal here is to use excess solar power to charge the car once the demand of the house is met. That means the car will be charged and some residual power, in my case 200W are used to feed into the powerwall or export if the powerwalls are full.

teg


In the main openevse page, charging should be in automatic mode, and the eco mode activated. Timers should be disabled as timers charge at maximum current, so they are not compatible with divert currently.

openevse status

The parameters for the divert logic can be adjusted in the “Self Production” page in the settings.

openevse self production

The parameters that govern how OpenEVSE is using this value are:

  • divert_reserve_power_w: Power that will not be used for charging to avoid going into import
  • divert_hysteresis_power_w: Additional power to reach above available - reserve_power to start charging
  • divert_attack_smoothing_time: The time constant value used for the input filter when increasing power (in sec). Value of 0 means no filtering
  • divert_decay_smoothing_time: The time constant value used for the input filter when decreasing power (in sec). Value of 0 means no filtering
  • divert_min_charge_time: The minimum amount of time (seconds) to charge the car once enabled via the self production divert. This can help minimise wear and tear on the EVSE.

In the poll_pw function of powerwall_mqtt, we derive a energy flux monitor from the difference between solar production and what’s consumed in the home

def poll_pw(pw: pypowerwall.Powerwall, client: mqtt.Client) -> None:
    grid = pw.grid()
    solar = pw.solar()
    battery = pw.battery()
    home = pw.home()
    soc = pw.level()
    voltage = calculate_voltage(pw)
    solar_excess_w = solar - home
    solar_excess_neg_w = -solar_excess_w

solar_excess_neg_w is the power that is flowing to the powerwall batteries or the grid as an excess from solar. When is negative it means we have an excess of power as used by OpenEVSE.

This value is polled every 10s. These updates and the current status of openevse can be monitored and plotted with the nice mqtt client mqtt-explorer.

mqtt view


The maximum time for an EV to react to pilot changes is 5 seconds. So polling and updating every 10s should be a good compromise.

The smoothing constants can be set so the charging current doesn’t change too quickly. Also the hysteresis power is important in the morning or evening to avoid charge restarts and wearing down the relay. A 600w hysteresis is a good value as it provides 2.5 amps of hysteresis to start charging. So in the morning, the EVSE will start charging only when the excess power is above the minimum current (6 A) + (2.5 A) + (reserve / 240V). So when the smoothed current reaches 9A. Charging is continued for a minimum of min_charge_time seconds, even if the excess current falls below the minimum (6 A). After that the relay will close.

This changes the previous behaviour in which the hysteresis value was too small (0.5 A). Now is configurable in the GUI. For my 8KW solar system, 0.5 produced too many restars as production is ramping up.

I’m testing my current changes in my OpenEVSE and so far I’m pretty satisfied with the results. You are welcome to use these code changes and give feedback or send updates on github.

This is the solar graph in the Tesla app for a charging session, you can see how the home usage tracks right below the solar production as expected.

tesla app