Using excess solar energy variable in heaters and chargers

Hi community,

I set up home assistant to track solar/windpower production and consumption of the whole farm.
I use a Shelly 3EM for reading energy & power import and export (power-flow with positive or negative values).

Then I have templates that calculate the used power and the generated power, added up in Watts over all phases.

I built some ESPhome hardware for measurements based on the PZEM-004, but used also Tasmota plugs temporarely for reading energy production.

Also I made a power controller. The esp8266 outputs a pwm signal, which feeds a dimmer which is capable to regulate a few kilkowatts.

The ESP gets a power value from HA and controlls the power of an heating element.
Also the esp runs a service, where i can send an positive or negative offset to the actual power.
That was a long way, I worked several days to get it running and to calibrate. My knopwledge in coding is very basic.
All works fine so far.

The calibration is not very exact, I think because of voltage differences of the net and deviation of the dimmer because of heating up.
Because its a phase cutting dimmer, the power output is also not linear to the pwm-input.
But I’m inside 10% accuracy.

The YAML of the ESP might be interesting for some:

esphome:
  name: leistungssteller
  friendly_name: Leistungssteller

esp8266:
  board: esp01_1m

# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxxxxx"

    
  
  services:
    - service: adjust_power
      variables:
        offset: float
      then:
        - lambda: |-
            if ((id(output_power).state) + offset >= id(max_power).state)
              { id(output_power).publish_state(id(max_power).state); }
            if ((id(output_power).state) + offset <= 0)
              { id(output_power).publish_state(0); }
            else
              { id(output_power).publish_state(id(output_power).state + offset); }

ota:



wifi:
  ssid: "xxxxxxxxxxxxxxxxxxxx"
  password: ""

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "xxxxxxxxxxx"
    password: "xxxxxxxx"

captive_portal:


output:
  - platform: esp8266_pwm
    pin: GPIO16
    frequency: 1000 Hz
    id: pwm_output
    inverted: True
    min_power: 0.20
    max_power: 0.95
    zero_means_zero: True
    
sensor:
  - platform: homeassistant
    name: "Sollwert"
    entity_id: input_number.dumpload_power
    id: sollwert_vorgabe
    icon: "mdi:radiator"
    device_class: "power"
    unit_of_measurement: "W"
    accuracy_decimals: 0
    internal: True
    on_value:
      then:
        - lambda: |-
            id(output_power).publish_state(x);
       
  # - platform: homeassistant
    # entity_id: sensor.3phase_meter_pzem_pzem_004t_v3_power
    # id: power_flow
            
  - platform: template
    name: "Maximalleistung"
    id: max_power
    lambda: 'return 2120;'
    device_class: "power"
    unit_of_measurement: "W"

  - platform: template
    name: "Leistung"
    id: output_power
    device_class: "power"
    unit_of_measurement: "W"
    on_value:
      then:
        - lambda: |-
            id(pwm).publish_state(x);
            
  - platform: template
    name: "PWM output"
    id: pwm
    accuracy_decimals: 3
    icon: "mdi:pulse"
    filters:
      - calibrate_polynomial:
          degree: 3
          datapoints:
           - 0    -> 0
           - 2    -> 100
           - 36   -> 150
           - 59   -> 200
           - 110  -> 300
           - 182  -> 400
           - 285  -> 500
           - 407  -> 600
           - 550  -> 700
           - 708  -> 800
           - 875  -> 900
           - 1050 -> 1000
           - 1370 -> 1200
           - 1500 -> 1300
           - 1650 -> 1400
           - 1850 -> 1600
           - 2000 -> 1800
           - 2120 -> 1900
      - lambda: 'return x / id(max_power).state;'
    on_value:
      then:
        - lambda: |-
            id(pwm_output).set_level(x);

Now im looking for an automation: The goal is to use up most of the leftover energy in several dump loads in a cascade, each with its own ESPhome dimmer.
Later the same could be used to control an charger.

This is how I made it now via 2 automations in the automation dialog:

- id: '1679041958358'
  alias: Dumpload hoch
  description: ''
  trigger:
  - platform: numeric_state
    entity_id: sensor.power_flow
    for:
      hours: 0
      minutes: 0
      seconds: 0
    below: -100
  condition:
  - condition: numeric_state
    entity_id: sensor.power_flow
    below: -100
  - condition: numeric_state
    entity_id: sensor.leistungssteller_leistung
    above: sensor.leistungssteller_maximalleistung
  action:
  - repeat:
      while:
      - condition: numeric_state
        entity_id: sensor.power_flow
        below: -100
      sequence:
      - delay:
          hours: 0
          minutes: 0
          seconds: 2
          milliseconds: 0
      - service: esphome.leistungssteller_adjust_power
        data:
          offset: 50
  mode: single
- id: '1679074461130'
  alias: Dumpload runter
  description: ''
  trigger:
  - platform: numeric_state
    entity_id: sensor.power_flow
    for:
      hours: 0
      minutes: 0
      seconds: 0
    above: -50
    enabled: true
  condition:
  - condition: numeric_state
    entity_id: sensor.power_flow
    above: -50
    enabled: true
  - condition: numeric_state
    entity_id: sensor.leistungssteller_leistung
    above: 0
  action:
  - repeat:
      while:
      - condition: numeric_state
        entity_id: sensor.power_flow
        above: -50
      sequence:
      - service: esphome.leistungssteller_adjust_power
        data:
          offset: -50
      - delay:
          hours: 0
          minutes: 0
          seconds: 2
          milliseconds: 0
  mode: single

It works, but quite slow!
And somehow I think its not a good way to do.

If I reduce the delay, the power goes to much up and down, because the power_flow entity has some lag.

I also tried the PID-function in ESPhome, but I could not get this working. I think its the wrong application for this.

Whats a good solution for this? I’m really interested how other users would realize this.
Also with (later) distributed loads with priorities and some logic. We have different water heaters etc.

Thanks for advice!
Also for links to similar projects